Enable unpack buffer support for initializing 2D textures in TexImage2D.
TRAC #23843
Signed-off-by: Geoff Lang
Signed-off-by: Shannon Woods
diff --git a/src/libGLESv2/Texture.cpp b/src/libGLESv2/Texture.cpp
index 9bfde17..fe213e8 100644
--- a/src/libGLESv2/Texture.cpp
+++ b/src/libGLESv2/Texture.cpp
@@ -21,6 +21,8 @@
#include "libGLESv2/renderer/Renderer.h"
#include "libGLESv2/renderer/TextureStorage.h"
#include "libEGL/Surface.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/renderer/BufferStorage.h"
namespace gl
{
@@ -273,13 +275,46 @@
{
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
- if (pixels != NULL)
+ const void *pixelData = pixels;
+
+ if (unpack.pixelBuffer.id() != 0)
{
- image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixels);
+ // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
+ Buffer *pixelBuffer = unpack.pixelBuffer.get();
+ ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+ const void *bufferData = pixelBuffer->getStorage()->getData();
+ pixelData = static_cast<const unsigned char *>(bufferData) + offset;
+ }
+
+ if (pixelData != NULL)
+ {
+ image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
mDirtyImages = true;
}
}
+bool Texture::fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, GLint level)
+{
+ if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
+ {
+ return true;
+ }
+
+ // 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 (IsFastCopyBufferToTextureSupported(sizedInternalFormat, mRenderer->getCurrentClientVersion()))
+ {
+ unsigned int offset = reinterpret_cast<unsigned int>(pixels);
+ rx::RenderTarget *destRenderTarget = getStorage(true)->getStorageInstance()->getRenderTarget(level);
+
+ return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea);
+ }
+
+ // Return false if we do not support fast unpack
+ return false;
+}
+
void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image)
{
if (pixels != NULL)
@@ -470,7 +505,18 @@
: GetSizedInternalFormat(format, type, clientVersion);
redefineImage(level, sizedInternalFormat, width, height);
- Texture::setImage(unpack, type, pixels, mImageArray[level]);
+ // 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))
+ {
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[level]->markClean();
+ }
+ else
+ {
+ Texture::setImage(unpack, type, pixels, mImageArray[level]);
+ }
}
void Texture2D::bindTexImage(egl::Surface *surface)
diff --git a/src/libGLESv2/Texture.h b/src/libGLESv2/Texture.h
index 345b60d..2d729f6 100644
--- a/src/libGLESv2/Texture.h
+++ b/src/libGLESv2/Texture.h
@@ -113,6 +113,8 @@
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 fastUnpackPixels(const PixelUnpackState &unpack, const void *pixels, const Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, GLint level);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
GLint creationLevels(GLsizei width, GLsizei height) const;