From b7d42faac018662d6314d8333bc4c38cc76b552a Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Mon, 12 Oct 2026 08:01:54 -0400 Subject: [PATCH] [Fix] (GL): answer GL_TEXTURE_BUFFER_DATA_STORE_BINDING in glGetTexLevelParameter --- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 15 +++++++ MobileGL/MG_Test/Texture/TextureTest.cpp | 45 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index f50f5393..25aed3dd 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -806,6 +806,15 @@ namespace MobileGL::MG_Impl::GLImpl { return static_cast(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(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(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(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 diff --git a/MobileGL/MG_Test/Texture/TextureTest.cpp b/MobileGL/MG_Test/Texture/TextureTest.cpp index c81762e0..9816c420 100644 --- a/MobileGL/MG_Test/Texture/TextureTest.cpp +++ b/MobileGL/MG_Test/Texture/TextureTest.cpp @@ -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(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(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