mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Fix] (MG_Impl/GLImpl, MG_State/GLState, MG_Test/Texture, scripts/data): keep GENERATE_MIPMAP on the texture, not keyed by GL name
- A process-wide map keyed by GL name gave a deleted texture's flag to the next texture created under the recycled name. - The flag is now texture object state, so it dies with its texture.
This commit is contained in:
@@ -59,7 +59,6 @@
|
||||
|
||||
namespace MobileGL::MG_Impl::GLImpl {
|
||||
static SharedPtr<MG_State::GLState::ITextureObject> nullTextureObject;
|
||||
static UnorderedMap<Uint, Bool> g_autoGenerateMipmapByTextureId;
|
||||
|
||||
namespace {
|
||||
void SetTextureBorderColorFromFloats(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject,
|
||||
@@ -1321,7 +1320,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
textureObject->GetSamplerObject()->SetMaxAnisotropy(static_cast<GLfloat>(param));
|
||||
break;
|
||||
case GL_GENERATE_MIPMAP:
|
||||
g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != GL_FALSE);
|
||||
textureObject->SetAutoGenerateMipmap(param != GL_FALSE);
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_TEXTURE_MODE:
|
||||
if (param != GL_DEPTH_COMPONENT && param != GL_STENCIL_INDEX) {
|
||||
@@ -1435,7 +1434,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
textureObject->GetSamplerObject()->SetMaxAnisotropy(param);
|
||||
break;
|
||||
case GL_GENERATE_MIPMAP:
|
||||
g_autoGenerateMipmapByTextureId[textureObject->GetExternalIndex()] = (param != 0.0f);
|
||||
textureObject->SetAutoGenerateMipmap(param != 0.0f);
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_TEXTURE_MODE:
|
||||
if (param != GL_DEPTH_COMPONENT && param != GL_STENCIL_INDEX) {
|
||||
@@ -1599,11 +1598,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
|
||||
void MaybeAutoGenerateMipmap(const SharedPtr<MG_State::GLState::ITextureObject>& textureObject, Bool isProxy,
|
||||
GLint level) {
|
||||
if (isProxy || level != 0 || !textureObject) {
|
||||
return;
|
||||
}
|
||||
const auto it = g_autoGenerateMipmapByTextureId.find(textureObject->GetExternalIndex());
|
||||
if (it == g_autoGenerateMipmapByTextureId.end() || !it->second) {
|
||||
if (isProxy || level != 0 || !textureObject || !textureObject->GetAutoGenerateMipmap()) {
|
||||
return;
|
||||
}
|
||||
GenerateMipmap_Backend(textureObject);
|
||||
|
||||
@@ -99,6 +99,9 @@ namespace MobileGL::MG_State::GLState {
|
||||
// DEPTH_COMPONENT until set, and meaningless for every other format.
|
||||
virtual GLenum GetDepthStencilTextureMode() const = 0;
|
||||
virtual void SetDepthStencilTextureMode(GLenum mode) = 0;
|
||||
// GENERATE_MIPMAP: level 0 uploads regenerate the chain. Frontend-only, so no version moves.
|
||||
virtual Bool GetAutoGenerateMipmap() const = 0;
|
||||
virtual void SetAutoGenerateMipmap(Bool enabled) = 0;
|
||||
|
||||
// ---- Texture views (ARB_texture_view / GL 4.6 core 8.18) ----
|
||||
// The texture object whose immutable storage this one's texels actually live in, or
|
||||
@@ -206,6 +209,8 @@ namespace MobileGL::MG_State::GLState {
|
||||
// set_texture_params is addressed by resource and is independent of every binding.
|
||||
PipePublishParams();
|
||||
}
|
||||
Bool GetAutoGenerateMipmap() const override { return m_autoGenerateMipmap; }
|
||||
void SetAutoGenerateMipmap(Bool enabled) override { m_autoGenerateMipmap = enabled; }
|
||||
|
||||
protected:
|
||||
static Uint64 AllocateLifetimeId();
|
||||
@@ -290,6 +295,7 @@ namespace MobileGL::MG_State::GLState {
|
||||
Uint m_viewNumLayers = 0;
|
||||
Int m_samples = 0;
|
||||
Bool m_fixedSampleLocations = true;
|
||||
Bool m_autoGenerateMipmap = false;
|
||||
};
|
||||
|
||||
class TextureObjectMipmap : public TextureObjectBase {
|
||||
|
||||
@@ -392,3 +392,29 @@ TEST_F(TextureByNameTest, MipmapGenerationChecksTheTargetOfBothForms) {
|
||||
MG_Impl::GLImpl::GenerateMipmap(GL_TEXTURE_RECTANGLE);
|
||||
ExpectSingleGlError(GL_INVALID_ENUM);
|
||||
}
|
||||
|
||||
// GENERATE_MIPMAP belongs to the texture it was set on. GL names are recycled, so the next texture
|
||||
// created under a deleted texture's name must start without the flag.
|
||||
TEST_F(TextureByNameTest, AutoMipmapFlagDoesNotOutliveItsTexture) {
|
||||
const ScopedBackendStubs stubs;
|
||||
static Int generated;
|
||||
generated = 0;
|
||||
MG_Backend::gBackendFunctionsTable.GL.GenerateTextureMipmap =
|
||||
[](const SharedPtr<MG_State::GLState::ITextureObject>&, GLenum) { ++generated; };
|
||||
const Uint8 pixels[4 * 4 * 4] = {};
|
||||
|
||||
const GLuint deleted = CreateTexture(GL_TEXTURE_2D);
|
||||
MG_Impl::GLImpl::TextureParameteri(deleted, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
MG_Impl::GLImpl::TextureStorage2D(deleted, 3, GL_RGBA8, 4, 4);
|
||||
MG_Impl::GLImpl::TextureSubImage2D(deleted, 0, 0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
ASSERT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
ASSERT_EQ(generated, 1) << "the flag did not generate mipmaps on its own texture";
|
||||
MG_Impl::GLImpl::DeleteTextures(1, &deleted);
|
||||
|
||||
const GLuint recycled = CreateTexture(GL_TEXTURE_2D);
|
||||
ASSERT_EQ(recycled, deleted) << "the name was not recycled, so nothing here is tested";
|
||||
MG_Impl::GLImpl::TextureStorage2D(recycled, 3, GL_RGBA8, 4, 4);
|
||||
MG_Impl::GLImpl::TextureSubImage2D(recycled, 0, 0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
EXPECT_EQ(generated, 1) << "the new texture inherited the deleted texture's GENERATE_MIPMAP";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"file_excess_lines": 21859,
|
||||
"file_excess_lines": 21854,
|
||||
"function_excess_lines": 15516,
|
||||
"layering_violations": 63
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user