Split texture upload out from onCreateTexture
Review URL: http://codereview.appspot.com/4809060/
git-svn-id: http://skia.googlecode.com/svn/trunk@2003 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index bf7c895..b8a0406 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -897,6 +897,146 @@
}
}
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc,
+ GrGLenum internalFormat,
+ const void* data,
+ size_t rowBytes) {
+ // we assume the texture is bound;
+ if (!rowBytes) {
+ rowBytes = desc.fUploadByteCount * desc.fContentWidth;
+ }
+
+ // in case we need a temporary, trimmed copy of the src pixels
+ SkAutoSMalloc<128 * 128> tempStorage;
+
+ /*
+ * check whether to allocate a temporary buffer for flipping y or
+ * because our data 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.
+ */
+ bool flipY = GrGLTexture::kBottomUp_Orientation == desc.fOrientation;
+ if (GR_GL_SUPPORT_DESKTOP && !flipY) {
+ if (data && rowBytes != desc.fContentWidth * desc.fUploadByteCount) {
+ GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
+ rowBytes / desc.fUploadByteCount));
+ }
+ } else {
+ size_t trimRowBytes = desc.fContentWidth * desc.fUploadByteCount;
+ if (data && (trimRowBytes < rowBytes || flipY)) {
+ // copy the data into our new storage, skipping the trailing bytes
+ size_t trimSize = desc.fContentHeight * trimRowBytes;
+ const char* src = (const char*)data;
+ if (flipY) {
+ src += (desc.fContentHeight - 1) * rowBytes;
+ }
+ char* dst = (char*)tempStorage.realloc(trimSize);
+ for (int y = 0; y < desc.fContentHeight; y++) {
+ memcpy(dst, src, trimRowBytes);
+ if (flipY) {
+ src -= rowBytes;
+ } else {
+ src += rowBytes;
+ }
+ dst += trimRowBytes;
+ }
+ // now point data to our trimmed version
+ data = tempStorage.get();
+ rowBytes = trimRowBytes;
+ }
+ }
+
+ GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, desc.fUploadByteCount));
+ if (kIndex_8_GrPixelConfig == desc.fFormat &&
+ supports8BitPalette()) {
+ // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
+ GrAssert(desc.fContentWidth == desc.fAllocWidth);
+ GrAssert(desc.fContentHeight == desc.fAllocHeight);
+ GrGLsizei imageSize = desc.fAllocWidth * desc.fAllocHeight +
+ kGrColorTableSize;
+ GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, desc.fUploadFormat,
+ desc.fAllocWidth, desc.fAllocHeight,
+ 0, imageSize, data));
+ GrGLRestoreResetRowLength();
+ } else {
+ if (NULL != data && (desc.fAllocWidth != desc.fContentWidth ||
+ desc.fAllocHeight != desc.fContentHeight)) {
+ GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
+ desc.fAllocWidth, desc.fAllocHeight,
+ 0, desc.fUploadFormat, desc.fUploadType, NULL));
+ GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fContentWidth,
+ desc.fContentHeight, desc.fUploadFormat,
+ desc.fUploadType, data));
+ GrGLRestoreResetRowLength();
+
+ int extraW = desc.fAllocWidth - desc.fContentWidth;
+ int extraH = desc.fAllocHeight - desc.fContentHeight;
+ int maxTexels = extraW * extraH;
+ maxTexels = GrMax(extraW * desc.fContentHeight, maxTexels);
+ maxTexels = GrMax(desc.fContentWidth * extraH, maxTexels);
+
+ SkAutoSMalloc<128*128> texels(desc.fUploadByteCount * maxTexels);
+
+ // rowBytes is actual stride between rows in data
+ // rowDataBytes is the actual amount of non-pad data in a row
+ // and the stride used for uploading extraH rows.
+ uint32_t rowDataBytes = desc.fContentWidth * desc.fUploadByteCount;
+ if (extraH) {
+ uint8_t* lastRowStart = (uint8_t*) data +
+ (desc.fContentHeight - 1) * rowBytes;
+ uint8_t* extraRowStart = (uint8_t*)texels.get();
+
+ for (int i = 0; i < extraH; ++i) {
+ memcpy(extraRowStart, lastRowStart, rowDataBytes);
+ extraRowStart += rowDataBytes;
+ }
+ GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fContentHeight,
+ desc.fContentWidth, extraH,
+ desc.fUploadFormat, desc.fUploadType,
+ texels.get()));
+ }
+ if (extraW) {
+ uint8_t* edgeTexel = (uint8_t*)data +
+ rowDataBytes - desc.fUploadByteCount;
+ uint8_t* extraTexel = (uint8_t*)texels.get();
+ for (int j = 0; j < desc.fContentHeight; ++j) {
+ for (int i = 0; i < extraW; ++i) {
+ memcpy(extraTexel, edgeTexel, desc.fUploadByteCount);
+ extraTexel += desc.fUploadByteCount;
+ }
+ edgeTexel += rowBytes;
+ }
+ GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fContentWidth, 0,
+ extraW, desc.fContentHeight,
+ desc.fUploadFormat, desc.fUploadType,
+ texels.get()));
+ }
+ if (extraW && extraH) {
+ uint8_t* cornerTexel = (uint8_t*)data +
+ desc.fContentHeight * rowBytes -
+ desc.fUploadByteCount;
+ uint8_t* extraTexel = (uint8_t*)texels.get();
+ for (int i = 0; i < extraW*extraH; ++i) {
+ memcpy(extraTexel, cornerTexel, desc.fUploadByteCount);
+ extraTexel += desc.fUploadByteCount;
+ }
+ GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fContentWidth,
+ desc.fContentHeight, extraW, extraH,
+ desc.fUploadFormat, desc.fUploadType,
+ texels.get()));
+ }
+
+ } else {
+ GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
+ desc.fAllocWidth, desc.fAllocHeight, 0,
+ desc.fUploadFormat, desc.fUploadType, data));
+ GrGLRestoreResetRowLength();
+ }
+ }
+}
+
// good to set a break-point here to know when createTexture fails
static GrTexture* return_null_texture() {
// GrAssert(!"null texture");
@@ -917,8 +1057,6 @@
++fStats.fTextureCreateCnt;
#endif
- this->setSpareTextureUnit();
-
static const GrGLTexture::TexParams DEFAULT_PARAMS = {
GR_GL_NEAREST,
GR_GL_CLAMP_TO_EDGE,
@@ -926,6 +1064,7 @@
};
GrGLTexture::Desc glTexDesc;
+ GrGLRenderTarget::Desc glRTDesc;
GrGLenum internalFormat;
glTexDesc.fContentWidth = desc.fWidth;
@@ -935,6 +1074,13 @@
glTexDesc.fFormat = desc.fFormat;
glTexDesc.fOwnsID = true;
+ glRTDesc.fStencilRenderbufferID = 0;
+ glRTDesc.fMSColorRenderbufferID = 0;
+ glRTDesc.fRTFBOID = 0;
+ glRTDesc.fTexFBOID = 0;
+ glRTDesc.fOwnIDs = true;
+ glRTDesc.fConfig = glTexDesc.fFormat;
+
bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit);
if (!canBeTexture(desc.fFormat,
&internalFormat,
@@ -950,56 +1096,13 @@
GrGLTexture::kTopDown_Orientation;
GrAssert(as_size_t(desc.fAALevel) < GR_ARRAY_COUNT(fAASamples));
- GrGLint samples = fAASamples[desc.fAALevel];
+ glRTDesc.fSampleCnt = fAASamples[desc.fAALevel];
if (kNone_MSFBO == fMSFBOType && desc.fAALevel != kNone_GrAALevel) {
GrPrintf("AA RT requested but not supported on this platform.");
}
glTexDesc.fUploadByteCount = GrBytesPerPixel(desc.fFormat);
- // in case we need a temporary, trimmed copy of the src pixels
- SkAutoSMalloc<128 * 128> tempStorage;
-
- if (!rowBytes) {
- rowBytes = glTexDesc.fUploadByteCount * desc.fWidth;
- }
- /*
- * 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.
- */
- bool flipY = GrGLTexture::kBottomUp_Orientation == glTexDesc.fOrientation;
- if (GR_GL_SUPPORT_DESKTOP && !flipY) {
- if (srcData && rowBytes != desc.fWidth * glTexDesc.fUploadByteCount) {
- GR_GL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH,
- rowBytes / glTexDesc.fUploadByteCount));
- }
- } else {
- size_t trimRowBytes = desc.fWidth * glTexDesc.fUploadByteCount;
- 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;
- 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);
- if (flipY) {
- src -= rowBytes;
- } else {
- src += rowBytes;
- }
- dst += trimRowBytes;
- }
- // now point srcData to our trimmed version
- srcData = tempStorage.get();
- rowBytes = trimRowBytes;
- }
- }
-
if (renderTarget) {
if (!this->npotRenderTargetSupport()) {
glTexDesc.fAllocWidth = GrNextPow2(desc.fWidth);
@@ -1028,6 +1131,7 @@
return return_null_texture();
}
+ this->setSpareTextureUnit();
GR_GL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID));
GR_GL(TexParameteri(GR_GL_TEXTURE_2D,
GR_GL_TEXTURE_MAG_FILTER,
@@ -1042,102 +1146,10 @@
GR_GL_TEXTURE_WRAP_T,
DEFAULT_PARAMS.fWrapT));
- GR_GL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, glTexDesc.fUploadByteCount));
- if (kIndex_8_GrPixelConfig == desc.fFormat &&
- supports8BitPalette()) {
- // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D
- GrAssert(desc.fWidth == glTexDesc.fAllocWidth);
- GrAssert(desc.fHeight == glTexDesc.fAllocHeight);
- GrGLsizei imageSize = glTexDesc.fAllocWidth * glTexDesc.fAllocHeight +
- kGrColorTableSize;
- GR_GL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, glTexDesc.fUploadFormat,
- glTexDesc.fAllocWidth, glTexDesc.fAllocHeight,
- 0, imageSize, srcData));
- GrGLRestoreResetRowLength();
- } else {
- if (NULL != srcData && (glTexDesc.fAllocWidth != desc.fWidth ||
- glTexDesc.fAllocHeight != desc.fHeight)) {
- GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat,
- glTexDesc.fAllocWidth, glTexDesc.fAllocHeight,
- 0, glTexDesc.fUploadFormat, glTexDesc.fUploadType, NULL));
- GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, 0, desc.fWidth,
- desc.fHeight, glTexDesc.fUploadFormat,
- glTexDesc.fUploadType, srcData));
- GrGLRestoreResetRowLength();
-
- int extraW = glTexDesc.fAllocWidth - desc.fWidth;
- int extraH = glTexDesc.fAllocHeight - desc.fHeight;
- int maxTexels = extraW * extraH;
- maxTexels = GrMax(extraW * desc.fHeight, maxTexels);
- maxTexels = GrMax(desc.fWidth * extraH, maxTexels);
-
- SkAutoSMalloc<128*128> texels(glTexDesc.fUploadByteCount * maxTexels);
-
- // 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 * glTexDesc.fUploadByteCount;
- if (extraH) {
- uint8_t* lastRowStart = (uint8_t*) srcData +
- (desc.fHeight - 1) * rowBytes;
- uint8_t* extraRowStart = (uint8_t*)texels.get();
-
- for (int i = 0; i < extraH; ++i) {
- memcpy(extraRowStart, lastRowStart, rowDataBytes);
- extraRowStart += rowDataBytes;
- }
- GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, 0, desc.fHeight, desc.fWidth,
- extraH, glTexDesc.fUploadFormat, glTexDesc.fUploadType,
- texels.get()));
- }
- if (extraW) {
- uint8_t* edgeTexel = (uint8_t*)srcData + rowDataBytes - glTexDesc.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, glTexDesc.fUploadByteCount);
- extraTexel += glTexDesc.fUploadByteCount;
- }
- edgeTexel += rowBytes;
- }
- GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, 0, extraW,
- desc.fHeight, glTexDesc.fUploadFormat,
- glTexDesc.fUploadType, texels.get()));
- }
- if (extraW && extraH) {
- uint8_t* cornerTexel = (uint8_t*)srcData + desc.fHeight * rowBytes
- - glTexDesc.fUploadByteCount;
- uint8_t* extraTexel = (uint8_t*)texels.get();
- for (int i = 0; i < extraW*extraH; ++i) {
- memcpy(extraTexel, cornerTexel, glTexDesc.fUploadByteCount);
- extraTexel += glTexDesc.fUploadByteCount;
- }
- GR_GL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, desc.fWidth, desc.fHeight,
- extraW, extraH, glTexDesc.fUploadFormat,
- glTexDesc.fUploadType, texels.get()));
- }
-
- } else {
- GR_GL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, glTexDesc.fAllocWidth,
- glTexDesc.fAllocHeight, 0, glTexDesc.fUploadFormat,
- glTexDesc.fUploadType, srcData));
- GrGLRestoreResetRowLength();
- }
- }
-
-
- GrGLRenderTarget::Desc glRTDesc;
- glRTDesc.fStencilRenderbufferID = 0;
- glRTDesc.fMSColorRenderbufferID = 0;
- glRTDesc.fRTFBOID = 0;
- glRTDesc.fTexFBOID = 0;
- glRTDesc.fOwnIDs = true;
- glRTDesc.fConfig = glTexDesc.fFormat;
- glRTDesc.fSampleCnt = samples;
-
- GrGLenum msColorRenderbufferFormat = -1;
+ this->allocateAndUploadTexData(glTexDesc, internalFormat,srcData, rowBytes);
if (renderTarget) {
+ GrGLenum msColorRenderbufferFormat = -1;
#if GR_COLLECT_STATS
++fStats.fRenderTargetCreateCnt;
#endif
@@ -1150,7 +1162,7 @@
// If we are using multisampling and we will create two FBOS We render
// to one and then resolve to the texture bound to the other.
- if (samples > 1 && kNone_MSFBO != fMSFBOType) {
+ if (glRTDesc.fSampleCnt > 0 && kNone_MSFBO != fMSFBOType) {
GR_GL(GenFramebuffers(1, &glRTDesc.fRTFBOID));
GrAssert(0 != glRTDesc.fRTFBOID);
GR_GL(GenRenderbuffers(1, &glRTDesc.fMSColorRenderbufferID));
@@ -1193,10 +1205,10 @@
if (glRTDesc.fStencilRenderbufferID) {
GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
glRTDesc.fStencilRenderbufferID));
- if (samples > 1) {
+ if (glRTDesc.fSampleCnt > 0) {
GR_GL_NO_ERR(RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
- samples,
+ glRTDesc.fSampleCnt,
fStencilFormats[sIdx].fEnum,
glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight));
@@ -1212,12 +1224,12 @@
}
}
if (glRTDesc.fRTFBOID != glRTDesc.fTexFBOID) {
- GrAssert(samples > 1);
+ GrAssert(glRTDesc.fSampleCnt > 0);
GR_GL(BindRenderbuffer(GR_GL_RENDERBUFFER,
glRTDesc.fMSColorRenderbufferID));
GR_GL_NO_ERR(RenderbufferStorageMultisample(
GR_GL_RENDERBUFFER,
- samples,
+ glRTDesc.fSampleCnt,
msColorRenderbufferFormat,
glTexDesc.fAllocWidth,
glTexDesc.fAllocHeight));
@@ -1272,9 +1284,8 @@
if (glRTDesc.fStencilRenderbufferID &&
fStencilFormats[sIdx].fPacked) {
GR_GL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
- GR_GL_DEPTH_ATTACHMENT,
- GR_GL_RENDERBUFFER,
- 0));
+ GR_GL_DEPTH_ATTACHMENT,
+ GR_GL_RENDERBUFFER, 0));
}
continue;
}
@@ -1332,6 +1343,8 @@
}
}
+////////////////////////////////////////////////////////////////////////////////
+
GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
GrGLuint id;
GR_GL(GenBuffers(1, &id));