D3D: Reallocate storage when texture format changes with base level

Different levels of the same texture may have different formats, so
changing the base level may affect the format that should be used for
the storage. Take this into account in the D3D backend.

The added test fails on some GL drivers.

TEST=angle_end2end_tests
BUG=angleproject:596

Change-Id: I5380e942694a75685ebb510edb01c0489e0d5179
Reviewed-on: https://chromium-review.googlesource.com/344230
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
This commit is contained in:
Olli Etuaho 2016-05-11 14:25:21 +03:00 коммит произвёл Commit Bot
Родитель 77ae8d578b
Коммит 87fc71c456
4 изменённых файлов: 70 добавлений и 2 удалений

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

@ -649,6 +649,7 @@ void TextureD3D::setBaseLevel(GLuint baseLevel)
const int oldStorageWidth = std::max(1, getLevelZeroWidth());
const int oldStorageHeight = std::max(1, getLevelZeroHeight());
const int oldStorageDepth = std::max(1, getLevelZeroDepth());
const int oldStorageFormat = getBaseLevelInternalFormat();
mBaseLevel = baseLevel;
// When the base level changes, the texture storage might not be valid anymore, since it could
@ -656,8 +657,10 @@ void TextureD3D::setBaseLevel(GLuint baseLevel)
const int newStorageWidth = std::max(1, getLevelZeroWidth());
const int newStorageHeight = std::max(1, getLevelZeroHeight());
const int newStorageDepth = std::max(1, getLevelZeroDepth());
if (mTexStorage && (newStorageWidth != oldStorageWidth ||
newStorageHeight != oldStorageHeight || newStorageDepth != oldStorageDepth))
const int newStorageFormat = getBaseLevelInternalFormat();
if (mTexStorage &&
(newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
{
markAllImagesDirty();
SafeDelete(mTexStorage);

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

@ -2171,6 +2171,65 @@ TEST_P(Texture2DTestES3, ImmutableTextureBaseLevelOutOfRange)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Test that changing base level works when it affects the format of the texture.
TEST_P(Texture2DTestES3, TextureFormatChangesWithBaseLevel)
{
if (IsNVIDIA() && (isOpenGL() || isGLES()))
{
// Observed rendering corruption on NVIDIA OpenGL.
std::cout << "Test skipped on NVIDIA OpenGL." << std::endl;
return;
}
if (IsIntel() && isOpenGL())
{
// Observed incorrect rendering on Intel OpenGL.
std::cout << "Test skipped on Intel OpenGL." << std::endl;
return;
}
if (IsAMD() && isOpenGL())
{
// Observed incorrect rendering on AMD OpenGL.
std::cout << "Test skipped on AMD OpenGL." << std::endl;
return;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTexture2D);
std::vector<GLColor> texDataCyan(4u * 4u, GLColor::cyan);
std::vector<GLColor> texDataGreen(4u * 4u, GLColor::green);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// RGBA8 level that's initially unused.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
texDataCyan.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
// RG8 level that's initially used, with consistent dimensions with level 0 but a different
// format. It reads green channel data from the green and alpha channels of texDataGreen
// (this is a bit hacky but works).
glTexImage2D(GL_TEXTURE_2D, 1, GL_RG8, 2, 2, 0, GL_RG, GL_UNSIGNED_BYTE, texDataGreen.data());
EXPECT_GL_NO_ERROR();
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
// Switch the texture to use the cyan level 0 with the RGBA format.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
EXPECT_GL_NO_ERROR();
drawQuad(mProgram, "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
}
// Test that setting a texture image works when base level is out of range.
TEST_P(Texture2DTestES3, SetImageWhenBaseLevelOutOfRange)
{

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

@ -615,6 +615,11 @@ bool ANGLETest::isOpenGL() const
return getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
}
bool ANGLETest::isGLES() const
{
return getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
}
EGLint ANGLETest::getPlatformRenderer() const
{
assert(mEGLWindow);

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

@ -171,6 +171,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
bool isMultisampleEnabled() const;
bool isOpenGL() const;
bool isGLES() const;
EGLint getPlatformRenderer() const;
void ignoreD3D11SDKLayersWarnings();