aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-07-18 15:25:04 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-07-18 15:25:04 +0000
commitd9f826c0dbc38f3608797a02948adf9bc99d5d50 (patch)
tree5dde65872bfe6793546ee0fa746c558b0eb4ddf0 /gpu
parent74d25b10492239fe6b721ff115eebdc0eef4a096 (diff)
flip Y in uploads to bottom-up textures (and add gm test)
Review URL: http://codereview.appspot.com/4756043/ git-svn-id: http://skia.googlecode.com/svn/trunk@1882 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'gpu')
-rw-r--r--gpu/src/GrGLTexture.cpp46
-rw-r--r--gpu/src/GrGpuGL.cpp73
2 files changed, 74 insertions, 45 deletions
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index 207246ba9d..bbca5ed175 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -162,51 +162,65 @@ void GrGLTexture::uploadTextureData(int x,
GPUGL->setSpareTextureUnit();
- // glCompressedTexSubImage2D doesn't support any formats
+ // ES2 glCompressedTexSubImage2D doesn't support any formats
// (at least without extensions)
GrAssert(fUploadFormat != GR_GL_PALETTE8_RGBA8);
// in case we need a temporary, trimmed copy of the src pixels
- SkAutoSMalloc<128 * 128> trimStorage;
+ SkAutoSMalloc<128 * 128> tempStorage;
+ if (!rowBytes) {
+ rowBytes = fUploadByteCount * width;
+ }
/*
- * check if our srcData has extra bytes past each row. If so, we need
- * to trim those off here, since GL doesn't let us pass the rowBytes as
- * a parameter to glTexImage2D
+ * check whether to allocate a temporary buffer for flipping y or
+ * because our srcData has extra bytes past each row. If so, we need
+ * to trim those off here, since GL ES doesn't let us specify
+ * GL_UNPACK_ROW_LENGTH.
*/
-
- if (GR_GL_SUPPORT_DESKTOP) {
+ bool restoreGLRowLength = false;
+ bool flipY = kBottomUp_Orientation == fOrientation;
+ if (GR_GL_SUPPORT_DESKTOP && !flipY) {
+ // can't use this for flipping, only non-neg values allowed. :(
if (srcData && rowBytes) {
GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
rowBytes / fUploadByteCount));
+ restoreGLRowLength = true;
}
} else {
size_t trimRowBytes = width * fUploadByteCount;
- if (srcData && (trimRowBytes < rowBytes)) {
+ if (srcData && (trimRowBytes < rowBytes || flipY)) {
// copy the data into our new storage, skipping the trailing bytes
size_t trimSize = height * trimRowBytes;
const char* src = (const char*)srcData;
- char* dst = (char*)trimStorage.realloc(trimSize);
+ if (flipY) {
+ src += (height - 1) * rowBytes;
+ }
+ char* dst = (char*)tempStorage.realloc(trimSize);
for (int y = 0; y < height; y++) {
memcpy(dst, src, trimRowBytes);
- src += rowBytes;
+ if (flipY) {
+ src -= rowBytes;
+ } else {
+ src += rowBytes;
+ }
dst += trimRowBytes;
}
- // now point srcData to our trimmed version
- srcData = trimStorage.get();
+ // now point srcData to our copied version
+ srcData = tempStorage.get();
}
}
- // If we need to update textures that are created upside down
- // then we have to modify this code to flip the srcData
- GrAssert(kTopDown_Orientation == fOrientation);
+ if (flipY) {
+ y = this->height() - (y + height);
+ }
GR_GL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id()));
GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, fUploadByteCount));
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height,
fUploadFormat, fUploadType, srcData));
if (GR_GL_SUPPORT_DESKTOP) {
- if (srcData && rowBytes) {
+ if (restoreGLRowLength) {
GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0));
}
}
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 1a9d7fe325..09b337c362 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -790,46 +790,60 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
return return_null_texture();
}
+ // We keep GrRenderTargets in GL's normal orientation so that they
+ // can be drawn to by the outside world without the client having
+ // to render upside down.
+ glDesc.fOrientation = renderTarget ? GrGLTexture::kBottomUp_Orientation :
+ GrGLTexture::kTopDown_Orientation;
+
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
GrGLint samples = fAASamples[desc.fAALevel];
if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
GrPrintf("AA RT requested but not supported on this platform.");
}
- GR_GL(GenTextures(1, &glDesc.fTextureID));
- if (!glDesc.fTextureID) {
- return return_null_texture();
- }
-
glDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
// in case we need a temporary, trimmed copy of the src pixels
- SkAutoSMalloc<128 * 128> trimStorage;
+ SkAutoSMalloc<128 * 128> tempStorage;
+ if (!rowBytes) {
+ rowBytes = glDesc.fUploadByteCount * desc.fWidth;
+ }
/*
- * check if our srcData has extra bytes past each row. If so, we need
- * to trim those off here, since GL doesn't let us pass the rowBytes as
- * a parameter to glTexImage2D
+ * check whether to allocate a temporary buffer for flipping y or
+ * because our srcData has extra bytes past each row. If so, we need
+ * to trim those off here, since GL ES doesn't let us specify
+ * GL_UNPACK_ROW_LENGTH.
*/
- if (GR_GL_SUPPORT_DESKTOP) {
- if (srcData) {
+ bool flipY = GrGLTexture::kBottomUp_Orientation == glDesc.fOrientation;
+ if (GR_GL_SUPPORT_DESKTOP && !flipY) {
+ if (srcData && rowBytes != desc.fWidth * glDesc.fUploadByteCount) {
GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
rowBytes / glDesc.fUploadByteCount));
}
} else {
size_t trimRowBytes = desc.fWidth * glDesc.fUploadByteCount;
- if (srcData && (trimRowBytes < rowBytes)) {
+ if (srcData && (trimRowBytes < rowBytes || flipY)) {
// copy the data into our new storage, skipping the trailing bytes
size_t trimSize = desc.fHeight * trimRowBytes;
const char* src = (const char*)srcData;
- char* dst = (char*)trimStorage.realloc(trimSize);
+ if (flipY) {
+ src += (desc.fHeight - 1) * rowBytes;
+ }
+ char* dst = (char*)tempStorage.realloc(trimSize);
for (int y = 0; y < desc.fHeight; y++) {
memcpy(dst, src, trimRowBytes);
- src += rowBytes;
+ if (flipY) {
+ src -= rowBytes;
+ } else {
+ src += rowBytes;
+ }
dst += trimRowBytes;
}
// now point srcData to our trimmed version
- srcData = trimStorage.get();
+ srcData = tempStorage.get();
+ rowBytes = trimRowBytes;
}
}
@@ -856,6 +870,11 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
}
}
+ GR_GL(GenTextures(1, &glDesc.fTextureID));
+ if (!glDesc.fTextureID) {
+ return return_null_texture();
+ }
+
GR_GL(BindTexture(GR_GL_TEXTURE_2D, glDesc.fTextureID));
GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_MAG_FILTER,
@@ -901,36 +920,39 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
SkAutoSMalloc<128*128> texels(glDesc.fUploadByteCount * maxTexels);
- uint32_t rowSize = desc.fWidth * glDesc.fUploadByteCount;
+ // rowBytes is actual stride between rows in srcData
+ // rowDataBytes is the actual amount of non-pad data in a row
+ // and the stride used for uploading extraH rows.
+ uint32_t rowDataBytes = desc.fWidth * glDesc.fUploadByteCount;
if (extraH) {
uint8_t* lastRowStart = (uint8_t*) srcData +
- (desc.fHeight - 1) * rowSize;
+ (desc.fHeight - 1) * rowBytes;
uint8_t* extraRowStart = (uint8_t*)texels.get();
for (int i = 0; i < extraH; ++i) {
- memcpy(extraRowStart, lastRowStart, rowSize);
- extraRowStart += rowSize;
+ memcpy(extraRowStart, lastRowStart, rowDataBytes);
+ extraRowStart += rowDataBytes;
}
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
extraH, glDesc.fUploadFormat, glDesc.fUploadType,
texels.get()));
}
if (extraW) {
- uint8_t* edgeTexel = (uint8_t*)srcData + rowSize - glDesc.fUploadByteCount;
+ uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glDesc.fUploadByteCount;
uint8_t* extraTexel = (uint8_t*)texels.get();
for (int j = 0; j < desc.fHeight; ++j) {
for (int i = 0; i < extraW; ++i) {
memcpy(extraTexel, edgeTexel, glDesc.fUploadByteCount);
extraTexel += glDesc.fUploadByteCount;
}
- edgeTexel += rowSize;
+ edgeTexel += rowBytes;
}
GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
desc.fHeight, glDesc.fUploadFormat,
glDesc.fUploadType, texels.get()));
}
if (extraW && extraH) {
- uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowSize
+ uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowBytes
- glDesc.fUploadByteCount;
uint8_t* extraTexel = (uint8_t*)texels.get();
for (int i = 0; i < extraW*extraH; ++i) {
@@ -950,7 +972,6 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
}
}
- glDesc.fOrientation = GrGLTexture::kTopDown_Orientation;
GrGLRenderTarget::GLRenderTargetIDs rtIDs;
rtIDs.fStencilRenderbufferID = 0;
@@ -968,12 +989,6 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc,
GrGLenum status;
GrGLint err;
- // If need have both RT flag and srcData we have
- // to invert the data before uploading because FBO
- // will be rendered bottom up
- GrAssert(NULL == srcData);
- glDesc.fOrientation = GrGLTexture::kBottomUp_Orientation;
-
GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
GrAssert(rtIDs.fTexFBOID);