Commit 88fe1ad7 by Gregoire Payen de La Garanderie Committed by Jamie Madill

Update the texture storage after generateMipmaps and setStorage.

Also adds a few assert in SetData and various places to ensure that images are not dirty before modifying the storage. BUG=angle:873 Change-Id: I7cc922b33da0d79a1b5aefe216e9ccfaaf86a306 Reviewed-on: https://chromium-review.googlesource.com/241880Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGregoire Payen de La Garanderie <Gregory.Payen@imgtec.com>
parent b9266276
......@@ -435,6 +435,11 @@ gl::Error TextureD3D::generateMipmaps()
}
}
if (mTexStorage)
{
updateStorage();
}
return gl::Error(GL_NO_ERROR);
}
......@@ -656,8 +661,6 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box
{
ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
bool fastUnpacked = false;
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
{
......@@ -668,24 +671,14 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box
return error;
}
error = fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
if (error.isError())
{
return error;
}
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
ASSERT(!mImageArray[level]->isDirty());
fastUnpacked = true;
return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
}
if (!fastUnpacked)
else
{
return TextureD3D::subImage(index, area, format, type, unpack, pixels);
}
return gl::Error(GL_NO_ERROR);
}
......@@ -840,6 +833,13 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna
return error;
}
error = updateStorage();
if (error.isError())
{
return error;
}
mImmutable = true;
return gl::Error(GL_NO_ERROR);
......@@ -1391,6 +1391,13 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter
return error;
}
error = updateStorage();
if (error.isError())
{
return error;
}
mImmutable = true;
return gl::Error(GL_NO_ERROR);
......@@ -1846,8 +1853,6 @@ gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box
{
ASSERT(target == GL_TEXTURE_3D);
bool fastUnpacked = false;
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
......@@ -1860,24 +1865,14 @@ gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box
return error;
}
error = fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
if (error.isError())
{
return error;
}
// Ensure we don't overwrite our newly initialized data
mImageArray[level]->markClean();
ASSERT(!mImageArray[level]->isDirty());
fastUnpacked = true;
return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
}
if (!fastUnpacked)
else
{
return TextureD3D::subImage(index, area, format, type, unpack, pixels);
}
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureD3D_3D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
......@@ -1988,6 +1983,13 @@ gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum interna
return error;
}
error = updateStorage();
if (error.isError())
{
return error;
}
mImmutable = true;
return gl::Error(GL_NO_ERROR);
......@@ -2065,7 +2067,7 @@ gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
return gl::Error(GL_NO_ERROR);
}
bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
TextureStorage *storage = NULL;
gl::Error error = createCompleteStorage(createRenderTarget, &storage);
......@@ -2530,6 +2532,13 @@ gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum in
return error;
}
error = updateStorage();
if (error.isError())
{
return error;
}
mImmutable = true;
return gl::Error(GL_NO_ERROR);
......@@ -2601,7 +2610,7 @@ gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
return gl::Error(GL_NO_ERROR);
}
bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
TextureStorage *storage = NULL;
gl::Error error = createCompleteStorage(createRenderTarget, &storage);
......
......@@ -523,6 +523,8 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
{
ASSERT(!image->isDirty());
ID3D11Resource *resource = NULL;
gl::Error error = getResource(&resource);
if (error.isError())
......
......@@ -242,3 +242,95 @@ TYPED_TEST(TextureTest, CubeMapFBO)
EXPECT_GL_NO_ERROR();
}
// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a default color.
TYPED_TEST(TextureTest, TexStorage)
{
int width = getWindowWidth();
int height = getWindowHeight();
GLuint tex2D;
glGenTextures(1, &tex2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex2D);
// Fill with red
std::vector<GLubyte> pixels(3 * 16 * 16);
for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
{
pixels[pixelId * 3 + 0] = 255;
pixels[pixelId * 3 + 1] = 0;
pixels[pixelId * 3 + 2] = 0;
}
// ANGLE internally uses RGBA as the DirectX format for RGB images
// therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
// The data is kept in a CPU-side image and the image is marked as dirty.
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
// Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
// glTexSubImage2D should take into account that the image is dirty.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, pixels.data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUseProgram(m2DProgram);
glUniform1i(mTexture2DUniformLocation, 0);
glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
drawQuad(m2DProgram, "position", 0.5f);
glDeleteTextures(1, &tex2D);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(3*width/4, 3*height/4, 0, 0, 0, 255);
EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
}
// Test that glTexSubImage2D combined with a PBO works properly when glTexStorage2DEXT has initialized the image with a default color.
TYPED_TEST(TextureTest, TexStorageWithPBO)
{
if (extensionEnabled("NV_pixel_buffer_object"))
{
int width = getWindowWidth();
int height = getWindowHeight();
GLuint tex2D;
glGenTextures(1, &tex2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex2D);
// Fill with red
std::vector<GLubyte> pixels(3 * 16 * 16);
for (size_t pixelId = 0; pixelId < 16 * 16; ++pixelId)
{
pixels[pixelId * 3 + 0] = 255;
pixels[pixelId * 3 + 1] = 0;
pixels[pixelId * 3 + 2] = 0;
}
// Read 16x16 region from red backbuffer to PBO
GLuint pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * 16 * 16, pixels.data(), GL_STATIC_DRAW);
// ANGLE internally uses RGBA as the DirectX format for RGB images
// therefore glTexStorage2DEXT initializes the image to a default color to get a consistent alpha color.
// The data is kept in a CPU-side image and the image is marked as dirty.
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGB8, 16, 16);
// Initializes the color of the upper-left 8x8 pixels, leaves the other pixels untouched.
// glTexSubImage2D should take into account that the image is dirty.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 8, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUseProgram(m2DProgram);
glUniform1i(mTexture2DUniformLocation, 0);
glUniform2f(mTextureScaleUniformLocation, 1.f, 1.f);
drawQuad(m2DProgram, "position", 0.5f);
glDeleteTextures(1, &tex2D);
glDeleteTextures(1, &pbo);
EXPECT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(3 * width / 4, 3 * height / 4, 0, 0, 0, 255);
EXPECT_PIXEL_EQ(width / 4, height / 4, 255, 0, 0, 255);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment