diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 99d536d0..2c7fa7ad 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -439,10 +439,8 @@ namespace MobileGL::MG_Impl::GLImpl { } // namespace const SharedPtr& GetTextureObjectByName(GLuint texture, const char* caller) { - if (texture == 0 || !TextureImpl::ValidateTextureName(texture, true)) return nullTextureObject; - auto& textureObject = MG_State::pGLContext->GetTextureObject(texture); - if (!TextureImpl::ValidateTextureObject(textureObject)) { + if (!textureObject) { MG_State::pGLContext->RecordError( ErrorCode::InvalidOperation, MakeUnique("MG_Impl/GLImpl", caller, @@ -452,6 +450,67 @@ namespace MobileGL::MG_Impl::GLImpl { return textureObject; } + Bool ValidateTextureParameterForTarget(const SharedPtr& textureObject, + GLenum pname, GLint param, const char* caller) { + const auto target = textureObject->GetTarget(); + if ((pname == GL_TEXTURE_BASE_LEVEL || pname == GL_TEXTURE_MAX_LEVEL) && param < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "Texture level parameter must be non-negative.")); + return false; + } + + if ((target == TextureTarget::Texture2DMultisample || + target == TextureTarget::Texture2DMultisampleArray) && + pname == GL_TEXTURE_BASE_LEVEL && param != 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, + "Multisample texture base level must be zero.")); + return false; + } + + if (target == TextureTarget::TextureRectangle && pname == GL_TEXTURE_BASE_LEVEL && param != 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, "Rectangle texture base level must be zero.")); + return false; + } + + if ((target == TextureTarget::Texture2DMultisample || + target == TextureTarget::Texture2DMultisampleArray) && + (pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T || pname == GL_TEXTURE_WRAP_R || + pname == GL_TEXTURE_MIN_FILTER || pname == GL_TEXTURE_MAG_FILTER || pname == GL_TEXTURE_MIN_LOD || + pname == GL_TEXTURE_MAX_LOD || pname == GL_TEXTURE_LOD_BIAS || pname == GL_TEXTURE_COMPARE_MODE || + pname == GL_TEXTURE_COMPARE_FUNC || pname == GL_TEXTURE_BORDER_COLOR)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", caller, + "Sampler state is invalid for multisample textures.")); + return false; + } + + if (target == TextureTarget::TextureRectangle) { + if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && + (param == GL_MIRROR_CLAMP_TO_EDGE || param == GL_MIRRORED_REPEAT || param == GL_REPEAT)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", caller, + "Invalid wrap mode for rectangle texture.")); + return false; + } + if (pname == GL_TEXTURE_MIN_FILTER && param != GL_NEAREST && param != GL_LINEAR) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique("MG_Impl/GLImpl", caller, + "Invalid min filter for rectangle texture.")); + return false; + } + } + + return true; + } + TextureUploadTarget GetPrimaryUploadTarget(const SharedPtr& textureObject) { if (!textureObject) return TextureUploadTarget::Unknown; const auto& uploadTargets = textureObject->GetUploadTargets(); @@ -461,6 +520,7 @@ namespace MobileGL::MG_Impl::GLImpl { void TextureParameterObject_State(const SharedPtr& textureObject, GLenum pname, GLint param, const char* caller) { if (!textureObject) return; + if (!ValidateTextureParameterForTarget(textureObject, pname, param, caller)) return; switch (pname) { case GL_TEXTURE_MAG_FILTER: @@ -529,6 +589,7 @@ namespace MobileGL::MG_Impl::GLImpl { void TextureParameterObjectf_State(const SharedPtr& textureObject, GLenum pname, GLfloat param, const char* caller) { if (!textureObject) return; + if (!ValidateTextureParameterForTarget(textureObject, pname, static_cast(param), caller)) return; switch (pname) { case GL_TEXTURE_MAG_FILTER: diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp index 98e36501..96b7dfaa 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.cpp @@ -7,6 +7,7 @@ // End of Source File Header #include "Validators.h" +#include #include #include #include @@ -83,8 +84,20 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl { return false; } - // TODO: GL_INVALID_VALUE may be generated if level is greater than log2(max), where max is the returned - // value of GL_MAX_TEXTURE_SIZE. + Int maxTextureSize = MG_Backend::DynamicBackendParameters{}.MaxTextureSize; + if (MG_Backend::pActiveBackendObject) { + maxTextureSize = MG_Backend::pActiveBackendObject->GetDynamicParameters().MaxTextureSize; + } + Int maxLevel = 0; + for (Int size = std::max(maxTextureSize, 1); size > 1; size >>= 1) { + ++maxLevel; + } + if (level > maxLevel) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeUnique("MG_Impl/GLImpl", "ValidateTextureLevelNumber", + "Texture level exceeds GL_MAX_TEXTURE_SIZE")); + return false; + } return true; } @@ -129,7 +142,7 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl { return true; } - Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth) { + Bool ValidateTextureSizeRange(Int width, Int height, Int depth) { if (width < 0 || height < 0 || depth < 0) { MG_State::pGLContext->RecordError( ErrorCode::InvalidValue, MakeUnique("MG_Impl/GLImpl", "ValidateTextureSizeRange", diff --git a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h index e4d22f84..b88fdc6d 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/Validators.h @@ -20,7 +20,7 @@ namespace MobileGL::MG_Impl::GLImpl::TextureImpl { Bool ValidateTexturePixelDataType(TexturePixelDataType texturePixelDataType); Bool ValidateTextureLevelNumber(Int level); Bool ValidateTextureSizeWithTextureUploadTarget(TextureUploadTarget target, GLsizei width, GLsizei height); - Bool ValidateTextureSizeRange(SizeT width, SizeT height, SizeT depth); + Bool ValidateTextureSizeRange(Int width, Int height, Int depth); Bool ValidateTextureInternalFormat(TextureInternalFormat format); Bool ValidateTextureBorderNumber(Int border); Bool ValidateTextureInternalFormatCompatibleWithInput(TextureInputFormat format,