Apply effective base and max level on GL backend

This works around GL drivers that neglect to clamp the base level or
max level of immutable textures.

BUG=angleproject:596
BUG=610800
TEST=angle_end2end_tests

Change-Id: Ie4e04aaa9253f2befd73bccefa7759486b3ef487
Reviewed-on: https://chromium-review.googlesource.com/344590
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
This commit is contained in:
Olli Etuaho 2016-05-12 20:38:38 +03:00 коммит произвёл Commit Bot
Родитель 53ea9cc655
Коммит be815a4fef
4 изменённых файлов: 31 добавлений и 24 удалений

Просмотреть файл

@ -80,6 +80,7 @@ GLuint TextureState::getEffectiveBaseLevel() const
{
if (immutableFormat)
{
// GLES 3.0.4 section 3.8.10
return std::min(baseLevel, immutableLevels - 1);
}
// Some classes use the effective base level to index arrays with level data. By clamping the
@ -89,6 +90,18 @@ GLuint TextureState::getEffectiveBaseLevel() const
return std::min(baseLevel, static_cast<GLuint>(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
}
GLuint TextureState::getEffectiveMaxLevel() const
{
if (immutableFormat)
{
// GLES 3.0.4 section 3.8.10
GLuint clampedMaxLevel = std::max(maxLevel, getEffectiveBaseLevel());
clampedMaxLevel = std::min(clampedMaxLevel, immutableLevels - 1);
return clampedMaxLevel;
}
return maxLevel;
}
Texture::Texture(rx::GLImplFactory *factory, GLuint id, GLenum target)
: egl::ImageSibling(id),
mState(target),

Просмотреть файл

@ -49,6 +49,7 @@ struct TextureState final : public angle::NonCopyable
bool swizzleRequired() const;
GLuint getEffectiveBaseLevel() const;
GLuint getEffectiveMaxLevel() const;
// TODO(jmadill): Make the data members here private.

Просмотреть файл

@ -726,12 +726,25 @@ void TextureGL::syncState(size_t textureUnit) const
}
};
// clang-format off
// Sync texture state
SyncTextureStateMember(mFunctions, applyTextureFunc, mState, mAppliedTextureState, mState.target, GL_TEXTURE_BASE_LEVEL, &gl::TextureState::baseLevel);
SyncTextureStateMember(mFunctions, applyTextureFunc, mState, mAppliedTextureState, mState.target, GL_TEXTURE_MAX_LEVEL, &gl::TextureState::maxLevel);
// Apply the effective base level and max level instead of the base level and max level set from
// the API. This can help with buggy drivers.
if (mAppliedTextureState.getEffectiveBaseLevel() != mState.getEffectiveBaseLevel())
{
applyTextureFunc();
mFunctions->texParameteri(mState.target, GL_TEXTURE_BASE_LEVEL,
mState.getEffectiveBaseLevel());
}
mAppliedTextureState.baseLevel = mState.baseLevel;
if (mAppliedTextureState.getEffectiveMaxLevel() != mState.getEffectiveMaxLevel())
{
applyTextureFunc();
mFunctions->texParameteri(mState.target, GL_TEXTURE_MAX_LEVEL,
mState.getEffectiveMaxLevel());
}
mAppliedTextureState.maxLevel = mState.maxLevel;
// clang-format off
const LevelInfoGL &levelInfo = mLevelInfo[mState.getEffectiveBaseLevel()];
SyncTextureStateSwizzle(mFunctions, applyTextureFunc, levelInfo, mState, mAppliedTextureState, mState.target, GL_TEXTURE_SWIZZLE_R, &gl::TextureState::swizzleRed);
SyncTextureStateSwizzle(mFunctions, applyTextureFunc, levelInfo, mState, mAppliedTextureState, mState.target, GL_TEXTURE_SWIZZLE_G, &gl::TextureState::swizzleGreen);

Просмотреть файл

@ -2126,26 +2126,6 @@ TEST_P(Texture2DTestES3, TextureBaseLevelGreaterThanMaxLevel)
// GLES 3.0.4 section 3.8.10 subsection Mipmapping
TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
{
if (IsOSX())
{
// Observed incorrect rendering on OSX.
std::cout << "Test skipped on OSX." << std::endl;
return;
}
if (IsAMD() && isOpenGL())
{
// Observed incorrect rendering on AMD OpenGL.
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
if (IsLinux() && IsIntel() && isOpenGL())
{
// The Mesa Intel driver doesn't clamp the base level
std::cout << "Test skipped on Intel Linux OpenGL." << std::endl;
return;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);