зеркало из https://github.com/AvaloniaUI/angle.git
Work around Mac glGenerateMipmap with missing levels bug.
Some Mac GL drivers fail to generate mipmaps if level zero is not set before the texture is first used, all mipmap data is black. To work around this, whenever a texture level is allocated, ensure that level zero is also allocated with at least a 1x1 image. Bug: angleproject:5223 Change-Id: If1a728e017dec600c77a54f7ae185b719aaaae84 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2497569 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Kenneth Russell <kbr@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Родитель
5c2db1c5e5
Коммит
f02a6e0c7f
|
@ -499,6 +499,12 @@ struct FeaturesGL : FeatureSetBase
|
||||||
"keep_buffer_shadow_copy", FeatureCategory::OpenGLWorkarounds,
|
"keep_buffer_shadow_copy", FeatureCategory::OpenGLWorkarounds,
|
||||||
"Maintain a shadow copy of buffer data when the GL API does not permit reading data back.",
|
"Maintain a shadow copy of buffer data when the GL API does not permit reading data back.",
|
||||||
&members};
|
&members};
|
||||||
|
|
||||||
|
// glGenerateMipmap fails if the zero texture level is not set on some Mac drivers
|
||||||
|
Feature setZeroLevelBeforeGenerateMipmap = {
|
||||||
|
"set_zero_level_before_generating_mipmap", FeatureCategory::OpenGLWorkarounds,
|
||||||
|
"glGenerateMipmap fails if the zero texture level is not set on some Mac drivers.",
|
||||||
|
&members};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline FeaturesGL::FeaturesGL() = default;
|
inline FeaturesGL::FeaturesGL() = default;
|
||||||
|
|
|
@ -265,8 +265,29 @@ angle::Result TextureGL::setImageHelper(const gl::Context *context,
|
||||||
texImageFormat.type, pixels));
|
texImageFormat.type, pixels));
|
||||||
}
|
}
|
||||||
|
|
||||||
setLevelInfo(context, target, level, 1,
|
LevelInfoGL levelInfo = GetLevelInfo(features, internalFormat, texImageFormat.internalFormat);
|
||||||
GetLevelInfo(features, internalFormat, texImageFormat.internalFormat));
|
setLevelInfo(context, target, level, 1, levelInfo);
|
||||||
|
|
||||||
|
if (features.setZeroLevelBeforeGenerateMipmap.enabled && getType() == gl::TextureType::_2D &&
|
||||||
|
level != 0 && mLevelInfo[0].nativeInternalFormat == GL_NONE)
|
||||||
|
{
|
||||||
|
// Only fill level zero if it's possible that mipmaps can be generated with this format
|
||||||
|
const gl::InternalFormat &internalFormatInfo =
|
||||||
|
gl::GetInternalFormatInfo(internalFormat, type);
|
||||||
|
if (!internalFormatInfo.sized ||
|
||||||
|
(internalFormatInfo.filterSupport(context->getClientVersion(),
|
||||||
|
context->getExtensions()) &&
|
||||||
|
internalFormatInfo.textureAttachmentSupport(context->getClientVersion(),
|
||||||
|
context->getExtensions())))
|
||||||
|
{
|
||||||
|
ANGLE_GL_TRY_ALWAYS_CHECK(
|
||||||
|
context,
|
||||||
|
functions->texImage2D(nativegl::GetTextureBindingTarget(target), 0,
|
||||||
|
texImageFormat.internalFormat, 1, 1, 0, texImageFormat.format,
|
||||||
|
texImageFormat.type, nullptr));
|
||||||
|
setLevelInfo(context, target, 0, 1, levelInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return angle::Result::Continue;
|
return angle::Result::Continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1837,6 +1837,8 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
|
||||||
ANGLE_FEATURE_CONDITION(features, disableSyncControlSupport, false);
|
ANGLE_FEATURE_CONDITION(features, disableSyncControlSupport, false);
|
||||||
|
|
||||||
ANGLE_FEATURE_CONDITION(features, keepBufferShadowCopy, !CanMapBufferForRead(functions));
|
ANGLE_FEATURE_CONDITION(features, keepBufferShadowCopy, !CanMapBufferForRead(functions));
|
||||||
|
|
||||||
|
ANGLE_FEATURE_CONDITION(features, setZeroLevelBeforeGenerateMipmap, IsApple());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
|
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
|
||||||
|
|
|
@ -605,6 +605,38 @@ TEST_P(MipmapTest, DISABLED_ThreeLevelsInitData)
|
||||||
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
|
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 8, getWindowHeight() / 8, GLColor::red);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test generating mipmaps with base level and max level set. Ported from part of the
|
||||||
|
// conformance2/textures/misc/tex-mipmap-levels WebGL2 test.
|
||||||
|
TEST_P(MipmapTestES3, GenerateMipmapPartialLevels)
|
||||||
|
{
|
||||||
|
const std::vector<GLColor> kRedData(64, GLColor::red);
|
||||||
|
const std::vector<GLColor> kGreenData(16, GLColor::green);
|
||||||
|
const std::vector<GLColor> kBlueData(4, GLColor::blue);
|
||||||
|
|
||||||
|
// Initialize mips 2 to 4
|
||||||
|
GLTexture texture;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, kRedData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, kGreenData.data());
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, kBlueData.data());
|
||||||
|
|
||||||
|
// Set base and max levels
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 2);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
|
||||||
|
// Verify the data
|
||||||
|
clearAndDrawQuad(m2DProgram, 2, 2);
|
||||||
|
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||||
|
|
||||||
|
// Test that generateMipmap works with partial levels.
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
clearAndDrawQuad(m2DProgram, 2, 2);
|
||||||
|
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||||
|
}
|
||||||
|
|
||||||
// This test generates mipmaps for a 1x1 texture, which should be a no-op.
|
// This test generates mipmaps for a 1x1 texture, which should be a no-op.
|
||||||
TEST_P(MipmapTestES3, GenerateMipmap1x1Texture)
|
TEST_P(MipmapTestES3, GenerateMipmap1x1Texture)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче