diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-07-18 15:25:04 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-07-18 15:25:04 +0000 |
commit | d9f826c0dbc38f3608797a02948adf9bc99d5d50 (patch) | |
tree | 5dde65872bfe6793546ee0fa746c558b0eb4ddf0 /gpu | |
parent | 74d25b10492239fe6b721ff115eebdc0eef4a096 (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.cpp | 46 | ||||
-rw-r--r-- | gpu/src/GrGpuGL.cpp | 73 |
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); |