Refactor the fast path for pixel unpack buffers, and fix a few validation gaps with texture completeness.
TRAC #23997
Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index dc2e2d1..3b56717 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -223,8 +223,13 @@
}
}
+bool Texture::isFastUnpackable(const PixelUnpackState &unpack, GLint sizedInternalFormat)
+{
+ return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+}
+
bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
- GLenum sizedInternalFormat, GLenum type, GLint level)
+ GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget)
{
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
{
@@ -233,16 +238,11 @@
// In order to perform the fast copy through the shader, we must have the right format, and be able
// to create a render target.
- if (mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat))
- {
- unsigned int offset = reinterpret_cast<unsigned int>(pixels);
- rx::RenderTarget *destRenderTarget = getStorage(true)->getStorageInstance()->getRenderTarget(level);
+ ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
- return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
- }
+ unsigned int offset = reinterpret_cast<unsigned int>(pixels);
- // Return false if we do not support fast unpack
- return false;
+ return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
}
void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
@@ -435,15 +435,25 @@
: GetSizedInternalFormat(format, type, clientVersion);
redefineImage(level, sizedInternalFormat, width, height);
+ bool fastUnpacked = false;
+
// Attempt a fast gpu copy of the pixel data to the surface
- // If we want to support rendering (which is necessary for GPU unpack buffers), level 0 must be complete
- Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
- if (unpack.pixelBuffer.id() != 0 && isLevelComplete(0) && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, level))
+ if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
{
- // Ensure we don't overwrite our newly initialized data
- mImageArray[level]->markClean();
+ // Will try to create RT storage if it does not exist
+ rx::RenderTarget *destRenderTarget = getRenderTarget(level);
+ Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);
+
+ if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+
+ fastUnpacked = true;
+ }
}
- else
+
+ if (!fastUnpacked)
{
Texture::setImage(unpack, type, pixels, mImageArray[level]);
}
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 34dfe52..b7e51e9 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -118,8 +118,9 @@
void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image);
bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image);
+ bool isFastUnpackable(const PixelUnpackState &unpack, GLint sizedInternalFormat);
bool fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
- GLenum sizedInternalFormat, GLenum type, GLint level);
+ GLenum sizedInternalFormat, GLenum type, rx::RenderTarget *destRenderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
GLint creationLevels(GLsizei width, GLsizei height) const;