From 39c17c0b1b83a315cf8f19fc249ab0a2e8c0ab5c Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Wed, 5 Aug 2026 01:24:29 -0400 Subject: [PATCH] [Fix] (MG_Impl): validate the float texture parameter setter and the compressed size query Two independent gaps in the texture parameter paths, both reported by direct_state_access: TexParameterf_State never ran ValidateTextureParameterForTarget. The integer setter reaches it through TextureParameterObject_State and the scalar float setter through TextureParameterObjectf_State, but glTexParameterfv and glTextureParameterfv funnel every non-vector pname straight into TexParameterf_State - so in float form MobileGL accepted sampler state on a multisample texture, a mipmapping min filter or a REPEAT wrap on a rectangle texture, and a negative TEXTURE_BASE_LEVEL/TEXTURE_MAX_LEVEL, all of which the integer form rejected. It now validates first, passing the same anisotropy-exempt param the by-object float setter uses so the anisotropy range check is not run twice. GL_TEXTURE_COMPRESSED_IMAGE_SIZE answered 0 for every texture. GL 4.6 core 8.11 makes the query INVALID_OPERATION on an image whose internal format is uncompressed and on any proxy target. TextureInternalFormat has no compressed enumerator, so that is every texture MobileGL can hold today; the condition is still written against an IsCompressedTextureFormat predicate so both level getters answer consistently once compressed formats land, and GL_TEXTURE_COMPRESSED now reads from the same predicate instead of a hardcoded false. Takes textures_parameter_setup_errors and textures_level_parameter_errors from failing to passing on both backends. --- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index df8a6a1a..a3e46b93 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -211,6 +211,14 @@ namespace MobileGL::MG_Impl::GLImpl { } } + // TextureInternalFormat has no compressed enumerator and CompressedTexImage* rejects every + // compressed format up front, so no texture image MobileGL holds can be compressed. Written + // as a predicate rather than a literal false so both level-parameter getters stay in step + // once compressed formats do land. + Bool IsCompressedTextureFormat(TextureInternalFormat) { + return false; + } + GLint GetTextureLevelComponentParameter(TextureInternalFormat textureInternalFormat, GLenum pname) { const ComponentSizes componentSizes = MG_Util::GetComponentSizesForInternalFormat(textureInternalFormat); switch (pname) { @@ -1445,6 +1453,13 @@ namespace MobileGL::MG_Impl::GLImpl { auto& textureObject = GetTextureObjectByTargetForParameter(textureUploadTarget, textureTarget); if (!textureObject) return; + // The per-object setters run this before writing, and glTexParameterfv/glTextureParameterfv + // funnel everything that is not a vector pname down here - so without it the float forms of + // the setter accepted sampler state on a multisample texture, a mipmapping filter on a + // rectangle texture and a negative base level, all of which the integer forms rejected. + const GLint validationParam = pname == GL_TEXTURE_MAX_ANISOTROPY_EXT ? 1 : static_cast(param); + if (!ValidateTextureParameterForTarget(textureObject, pname, validationParam, __func__)) return; + switch (pname) { case GL_TEXTURE_MAG_FILTER: textureObject->GetSamplerObject()->SetMagFilter(MG_Util::ConvertGLEnumToSamplerFilterMode((GLenum)param)); @@ -2756,10 +2771,21 @@ namespace MobileGL::MG_Impl::GLImpl { break; case GL_TEXTURE_COMPRESSED: if (params) { - *params = GL_FALSE; + *params = IsCompressedTextureFormat(textureObject->GetFormat()) ? GL_TRUE : GL_FALSE; } break; case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: + // GL 4.6 core 8.11: there is no compressed size to report for an image whose internal + // format is uncompressed, nor for a proxy target, and the query is INVALID_OPERATION + // rather than a zero. + if (isProxy || !IsCompressedTextureFormat(textureObject->GetFormat())) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique( + "MG_Impl/GLImpl", "GetTexLevelParameteriv_State", + "GL_TEXTURE_COMPRESSED_IMAGE_SIZE needs a compressed, non-proxy texture image.")); + return; + } if (params) { *params = 0; } @@ -2868,10 +2894,20 @@ namespace MobileGL::MG_Impl::GLImpl { break; case GL_TEXTURE_COMPRESSED: if (params) { - *params = 0.0f; + *params = IsCompressedTextureFormat(textureObject->GetFormat()) ? 1.0f : 0.0f; } break; case GL_TEXTURE_COMPRESSED_IMAGE_SIZE: + // See GetTexLevelParameteriv_State: uncompressed images and proxy targets have no + // compressed size to report, so GL 4.6 core 8.11 makes the query an error. + if (isProxy || !IsCompressedTextureFormat(textureObject->GetFormat())) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique( + "MG_Impl/GLImpl", "GetTexLevelParameterfv_State", + "GL_TEXTURE_COMPRESSED_IMAGE_SIZE needs a compressed, non-proxy texture image.")); + return; + } if (params) { *params = 0.0f; }