[Fix] (GL): answer GL_TEXTURE_BUFFER_DATA_STORE_BINDING in glGetTexLevelParameter

This commit is contained in:
2026-10-12 08:22:16 -04:00
parent 2f312262ea
commit b7d42faac0
2 changed files with 60 additions and 0 deletions
@@ -806,6 +806,15 @@ namespace MobileGL::MG_Impl::GLImpl {
return static_cast<GLint>(std::min(texelCount, maxTexelCount));
}
// GL_TEXTURE_BUFFER_DATA_STORE_BINDING: the name of the buffer a buffer texture is attached
// to, or 0 when none is - and 0, the state's initial value, for any other storage.
GLuint GetBufferTextureDataStoreBinding(MG_State::GLState::ITextureObject* textureObject) {
if (textureObject->GetStorageType() != TextureStorageType::Buffer) return 0u;
auto* bufferTextureObject = static_cast<MG_State::GLState::TextureObjectBuffer*>(textureObject);
const auto& buffer = bufferTextureObject->GetBufferBindingSlot().GetBoundObject();
return buffer != nullptr ? buffer->GetExternalIndex() : 0u;
}
// glGetTexLevelParameter{i,f}v answers WIDTH/HEIGHT/DEPTH out of the mipmap chain, and (since
// the buffer-texture arms above) out of the attached buffer range for GL_TEXTURE_BUFFER. This
// is what is left: a storage class with no level geometry at all. Report it instead of
@@ -3682,6 +3691,9 @@ namespace MobileGL::MG_Impl::GLImpl {
}
break;
}
case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
if (params) *params = static_cast<GLint>(GetBufferTextureDataStoreBinding(textureObject.get()));
break;
case GL_TEXTURE_BUFFER_SIZE:
case GL_TEXTURE_BUFFER_OFFSET: {
// GL 4.6 core 8.9: both describe the window of the attached buffer a GL_TEXTURE_BUFFER
@@ -3853,6 +3865,9 @@ namespace MobileGL::MG_Impl::GLImpl {
}
break;
}
case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
if (params) *params = static_cast<GLfloat>(GetBufferTextureDataStoreBinding(textureObject.get()));
break;
case GL_TEXTURE_BUFFER_SIZE:
case GL_TEXTURE_BUFFER_OFFSET: {
// See GetTexLevelParameteriv_State: both describe the attached buffer range of a
+45
View File
@@ -5369,6 +5369,51 @@ TEST_F(TextureTest, GetTexLevelParameterAnswersBufferStorageGeometry) {
}
}
// GL 4.6 core 8.11.3: GL_TEXTURE_BUFFER_DATA_STORE_BINDING names the buffer a buffer texture is
// attached to, 0 once it is detached - and its initial value 0 for any other storage.
TEST_F(TextureTest, GetTexLevelParameterReportsBufferDataStoreBinding) {
GLuint buffer = 0;
MG_Impl::GLImpl::CreateBuffers(1, &buffer);
MG_Impl::GLImpl::NamedBufferData(buffer, 64, nullptr, GL_STATIC_DRAW);
GLuint texture = 0;
MG_Impl::GLImpl::CreateTextures(GL_TEXTURE_BUFFER, 1, &texture);
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_BUFFER, texture);
MG_Impl::GLImpl::TexBuffer(GL_TEXTURE_BUFFER, GL_R8, buffer);
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
GLint binding = -1;
MG_Impl::GLImpl::GetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, &binding);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
EXPECT_EQ(binding, static_cast<GLint>(buffer));
GLfloat bindingFloat = -1.0f;
MG_Impl::GLImpl::GetTexLevelParameterfv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING,
&bindingFloat);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
EXPECT_EQ(bindingFloat, static_cast<GLfloat>(buffer));
MG_Impl::GLImpl::TexBuffer(GL_TEXTURE_BUFFER, GL_R8, 0);
MG_Impl::GLImpl::GetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, &binding);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
EXPECT_EQ(binding, 0);
GLuint plain = 0;
MG_Impl::GLImpl::GenTextures(1, &plain);
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, plain);
MG_Impl::GLImpl::TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
binding = -1;
MG_Impl::GLImpl::GetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, &binding);
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
EXPECT_EQ(binding, 0);
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_2D, 0);
MG_Impl::GLImpl::BindTexture(GL_TEXTURE_BUFFER, 0);
MG_Impl::GLImpl::DeleteTextures(1, &plain);
MG_Impl::GLImpl::DeleteTextures(1, &texture);
MG_Impl::GLImpl::DeleteBuffers(1, &buffer);
DrainPendingGlErrors();
}
// Immutable storage plus glCompressedTexSubImage2D is the modern way to upload a compressed
// texture, so glTexStorage2D has to commit its levels to a specific compressed internalformat
// exactly as glTexImage2D does. When it did not, the sub-image call found an uncompressed level