diff options
author | 2011-11-16 20:36:03 +0000 | |
---|---|---|
committer | 2011-11-16 20:36:03 +0000 | |
commit | 6f3795105b2b458079e53a721c1735c9518f6bb5 (patch) | |
tree | 107d2ec0b8986a3bf96220fe9e86974fe9f7b8e3 /src | |
parent | aa336da0838c3da8b3be2e0348da3c6abeebf273 (diff) |
Make all pixel ops go thru ctx so we can correctly flush. Unify two texture upload code paths.
Review URL: http://codereview.appspot.com/5373108/
git-svn-id: http://skia.googlecode.com/svn/trunk@2701 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrAtlas.cpp | 10 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 83 | ||||
-rw-r--r-- | src/gpu/GrGLTexture.cpp | 80 | ||||
-rw-r--r-- | src/gpu/GrGLTexture.h | 16 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 11 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 22 | ||||
-rw-r--r-- | src/gpu/GrGpuGL.cpp | 163 | ||||
-rw-r--r-- | src/gpu/GrGpuGL.h | 20 | ||||
-rw-r--r-- | src/gpu/GrRenderTarget.cpp | 27 | ||||
-rw-r--r-- | src/gpu/GrTexture.cpp | 29 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 11 | ||||
-rw-r--r-- | src/gpu/SkGr.cpp | 12 | ||||
-rw-r--r-- | src/gpu/SkGrTexturePixelRef.cpp | 4 |
13 files changed, 282 insertions, 206 deletions
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp index 7b88498c15..5c951536b6 100644 --- a/src/gpu/GrAtlas.cpp +++ b/src/gpu/GrAtlas.cpp @@ -9,6 +9,7 @@ #include "GrAtlas.h" +#include "GrContext.h" #include "GrGpu.h" #include "GrRectanizer.h" #include "GrPlotMgr.h" @@ -109,7 +110,14 @@ bool GrAtlas::addSubImage(int width, int height, const void* image, image = storage.get(); } adjustForPlot(loc, fPlot); - fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image, 0); + GrContext* context = fTexture->getContext(); + // We call the internal version so that we don't force a flush. We assume + // our caller is smart and hasn't referenced the part of the texture we're + // about to update since the last flush. + context->internalWriteTexturePixels(fTexture, loc->fX, loc->fY, + dstW, dstH, fTexture->config(), + image, 0, + GrContext::kDontFlush_PixelOpsFlag); // now tell the caller to skip the top/left BORDER loc->fX += BORDER; diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 47a2a6b260..fe85b97b92 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1637,28 +1637,59 @@ void GrContext::flushDrawBuffer() { #endif } -bool GrContext::readTexturePixels(GrTexture* texture, - int left, int top, int width, int height, - GrPixelConfig config, void* buffer) { +void GrContext::internalWriteTexturePixels(GrTexture* texture, + int left, int top, + int width, int height, + GrPixelConfig config, + const void* buffer, + size_t rowBytes, + uint32_t flags) { + SK_TRACE_EVENT0("GrContext::writeTexturePixels"); + if (!(kDontFlush_PixelOpsFlag & flags)) { + this->flush(); + } + // TODO: use scratch texture to perform conversion + if (GrPixelConfigIsUnpremultiplied(texture->config()) != + GrPixelConfigIsUnpremultiplied(config)) { + return; + } + + fGpu->writeTexturePixels(texture, left, top, width, height, + config, buffer, rowBytes); +} + +bool GrContext::internalReadTexturePixels(GrTexture* texture, + int left, int top, + int width, int height, + GrPixelConfig config, + void* buffer, + size_t rowBytes, + uint32_t flags) { SK_TRACE_EVENT0("GrContext::readTexturePixels"); // TODO: code read pixels for textures that aren't rendertargets - this->flush(); + if (!(kDontFlush_PixelOpsFlag & flags)) { + this->flush(); + } GrRenderTarget* target = texture->asRenderTarget(); if (NULL != target) { - return this->readRenderTargetPixels(target, - left, top, width, height, - config, buffer, 0); + return this->internalReadRenderTargetPixels(target, + left, top, width, height, + config, buffer, rowBytes, + flags); } else { return false; } } -bool GrContext::readRenderTargetPixels(GrRenderTarget* target, - int left, int top, int width, int height, - GrPixelConfig config, void* buffer, - size_t rowBytes) { +bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, + int left, int top, + int width, int height, + GrPixelConfig config, + void* buffer, + size_t rowBytes, + uint32_t flags) { SK_TRACE_EVENT0("GrContext::readRenderTargetPixels"); if (NULL == target) { target = fGpu->getRenderTarget(); @@ -1675,7 +1706,9 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target, return false; } - this->flush(); + if (!(kDontFlush_PixelOpsFlag & flags)) { + this->flush(); + } GrTexture* src = target->asTexture(); bool swapRAndB = NULL != src && @@ -1751,16 +1784,25 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target, config, buffer, rowBytes, flipY); } -void GrContext::writePixels(int left, int top, int width, int height, - GrPixelConfig config, const void* buffer, - size_t stride) { - SK_TRACE_EVENT0("GrContext::writePixels"); +void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, + int left, int top, + int width, int height, + GrPixelConfig config, + const void* buffer, + size_t rowBytes, + uint32_t flags) { + SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels"); + + if (NULL == target) { + target = fGpu->getRenderTarget(); + if (NULL == target) { + return; + } + } // TODO: when underlying api has a direct way to do this we should use it // (e.g. glDrawPixels on desktop GL). - this->flush(kForceCurrentRenderTarget_FlushBit); - const GrTextureDesc desc = { kNone_GrTextureFlags, kNone_GrAALevel, width, height, { config } }; @@ -1769,7 +1811,8 @@ void GrContext::writePixels(int left, int top, int width, int height, if (NULL == texture) { return; } - texture->uploadTextureData(0, 0, width, height, buffer, stride); + this->internalWriteTexturePixels(texture, 0, 0, width, height, + config, buffer, rowBytes, flags); GrDrawTarget::AutoStateRestore asr(fGpu); reset_target_state(fGpu); @@ -1777,7 +1820,7 @@ void GrContext::writePixels(int left, int top, int width, int height, GrMatrix matrix; matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); fGpu->setViewMatrix(matrix); - + fGpu->setRenderTarget(target); fGpu->setTexture(0, texture); GrSamplerState sampler; diff --git a/src/gpu/GrGLTexture.cpp b/src/gpu/GrGLTexture.cpp index 6e93b6c361..327f7cf613 100644 --- a/src/gpu/GrGLTexture.cpp +++ b/src/gpu/GrGLTexture.cpp @@ -35,8 +35,7 @@ void GrGLTexture::init(GrGpuGL* gpu, fTexIDObj = new GrGLTexID(GPUGL->glInterface(), textureDesc.fTextureID, textureDesc.fOwnsID); - fUploadFormat = textureDesc.fUploadFormat; - fUploadType = textureDesc.fUploadType; + fInternalFormat = textureDesc.fInternalFormat; fOrientation = textureDesc.fOrientation; if (NULL != rtDesc) { @@ -86,83 +85,6 @@ void GrGLTexture::onAbandon() { } } -void GrGLTexture::uploadTextureData(int x, - int y, - int width, - int height, - const void* srcData, - size_t rowBytes) { - GrIRect bounds = GrIRect::MakeWH(this->width(), this->height()); - GrIRect subrect = GrIRect::MakeXYWH(x,y,width, height); - if (!bounds.contains(subrect)) { - return; - } - GPUGL->setSpareTextureUnit(); - - // 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> tempStorage; - - size_t bpp = GrBytesPerPixel(this->config()); - size_t trimRowBytes = width * bpp; - if (!rowBytes) { - rowBytes = trimRowBytes; - } - /* - * 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 may not let us specify - * GL_UNPACK_ROW_LENGTH. - */ - bool restoreGLRowLength = false; - bool flipY = kBottomUp_Orientation == fOrientation; - if (GPUGL->glCaps().fUnpackRowLengthSupport && !flipY) { - // can't use this for flipping, only non-neg values allowed. :( - if (srcData && rowBytes != trimRowBytes) { - GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); - GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); - restoreGLRowLength = true; - } - } else { - 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; - if (flipY) { - src += (height - 1) * rowBytes; - } - char* dst = (char*)tempStorage.reset(trimSize); - for (int y = 0; y < height; y++) { - memcpy(dst, src, trimRowBytes); - if (flipY) { - src -= rowBytes; - } else { - src += rowBytes; - } - dst += trimRowBytes; - } - // now point srcData to our copied version - srcData = tempStorage.get(); - } - } - - if (flipY) { - y = this->height() - (y + height); - } - GL_CALL(BindTexture(GR_GL_TEXTURE_2D, fTexIDObj->id())); - GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp))); - GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, x, y, width, height, - fUploadFormat, fUploadType, srcData)); - - if (restoreGLRowLength) { - GrAssert(GPUGL->glCaps().fUnpackRowLengthSupport); - GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); - } -} - intptr_t GrGLTexture::getTextureHandle() const { return fTexIDObj->id(); } diff --git a/src/gpu/GrGLTexture.h b/src/gpu/GrGLTexture.h index cedac5a63b..b023bc6d20 100644 --- a/src/gpu/GrGLTexture.h +++ b/src/gpu/GrGLTexture.h @@ -64,9 +64,8 @@ public: int fHeight; GrPixelConfig fConfig; GrGLuint fTextureID; + GrGLenum fInternalFormat; bool fOwnsID; - GrGLenum fUploadFormat; - GrGLenum fUploadType; Orientation fOrientation; }; @@ -82,13 +81,6 @@ public: virtual ~GrGLTexture() { this->release(); } - // overrides of GrTexture - virtual void uploadTextureData(int x, - int y, - int width, - int height, - const void* srcData, - size_t rowBytes); virtual intptr_t getTextureHandle() const; // these functions @@ -103,8 +95,7 @@ public: } GrGLuint textureID() const { return fTexIDObj->id(); } - GrGLenum uploadFormat() const { return fUploadFormat; } - GrGLenum uploadType() const { return fUploadType; } + GrGLenum internalFormat() const { return fInternalFormat; } // Ganesh assumes texture coordinates have their origin // in the top-left corner of the image. OpenGL, however, @@ -128,8 +119,7 @@ private: TexParams fTexParams; GrGpu::ResetTimestamp fTexParamsTimestamp; GrGLTexID* fTexIDObj; - GrGLenum fUploadFormat; - GrGLenum fUploadType; + GrGLenum fInternalFormat; Orientation fOrientation; void init(GrGpuGL* gpu, diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 1e6b420a8b..764ccd3eaf 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -253,6 +253,17 @@ bool GrGpu::readPixels(GrRenderTarget* target, config, buffer, rowBytes, invertY); } +void GrGpu::writeTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) { + GrAssert(GrPixelConfigIsUnpremultiplied(config) == + GrPixelConfigIsUnpremultiplied(texture->config())); + this->handleDirtyContext(); + this->onWriteTexturePixels(texture, left, top, width, height, + config, buffer, rowBytes); +} + //////////////////////////////////////////////////////////////////////////////// static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index cec03bcf50..9b39319f4f 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -245,6 +245,22 @@ public: GrPixelConfig config, void* buffer, size_t rowBytes, bool invertY); + /** + * Updates the pixels in a rectangle of a texture. + * @param left left edge of the rectangle to write (inclusive) + * @param top top edge of the rectangle to write (inclusive) + * @param width width of rectangle to write in pixels. + * @param height height of rectangle to write in pixels. + * @param config the pixel config of the source buffer + * @param buffer memory to read pixels from + * @param rowBytes number of bytes bewtween consecutive rows. Zero + * means rows are tightly packed. + */ + void writeTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes); + const GrGpuStats& getStats() const; void resetStats(); void printStats() const; @@ -402,6 +418,12 @@ protected: size_t rowBytes, bool invertY) = 0; + // overridden by API-specific derived class to perform the texture update + virtual void onWriteTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) = 0; + // called to program the vertex data, indexCount will be 0 if drawing non- // indexed geometry. The subclass may adjust the startVertex and/or // startIndex since it may have already accounted for these in the setup. diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp index 86a95a973c..facfac914a 100644 --- a/src/gpu/GrGpuGL.cpp +++ b/src/gpu/GrGpuGL.cpp @@ -523,10 +523,10 @@ void GrGpuGL::onResetContext() { } GrTexture* GrGpuGL::onCreatePlatformTexture(const GrPlatformTextureDesc& desc) { - GrGLenum internalFormat; // we don't need this value + GrGLenum dontCare; GrGLTexture::Desc glTexDesc; - if (!this->canBeTexture(desc.fConfig, &internalFormat, - &glTexDesc.fUploadFormat, &glTexDesc.fUploadType)) { + if (!this->canBeTexture(desc.fConfig, &glTexDesc.fInternalFormat, + &dontCare, &dontCare)) { return NULL; } @@ -639,9 +639,8 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) if (isTexture) { GrGLTexture::Desc texDesc; GrGLenum dontCare; - if (!canBeTexture(desc.fConfig, &dontCare, - &texDesc.fUploadFormat, - &texDesc.fUploadType)) { + if (!canBeTexture(desc.fConfig, &texDesc.fInternalFormat, + &dontCare, &dontCare)) { return NULL; } texDesc.fWidth = desc.fWidth; @@ -675,44 +674,82 @@ GrResource* GrGpuGL::onCreatePlatformSurface(const GrPlatformSurfaceDesc& desc) //////////////////////////////////////////////////////////////////////////////// -void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc, - GrGLenum internalFormat, - const void* data, - size_t rowBytes) { - // we assume the texture is bound +void GrGpuGL::onWriteTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) { + GrGLTexture* glTex = static_cast<GrGLTexture*>(texture); - size_t bpp = GrBytesPerPixel(desc.fConfig); - size_t trimRowBytes = desc.fWidth * bpp; + this->setSpareTextureUnit(); + GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTex->textureID())); + GrGLTexture::Desc desc; + desc.fConfig = glTex->config(); + desc.fWidth = glTex->width(); + desc.fHeight = glTex->height(); + desc.fOrientation = glTex->orientation(); + desc.fTextureID = glTex->textureID(); + desc.fInternalFormat = glTex->internalFormat(); + + this->uploadTexData(desc, left, top, width, height, config, buffer, rowBytes); +} - if (!rowBytes) { - rowBytes = trimRowBytes; +void GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc, + int left, int top, int width, int height, + GrPixelConfig dataConfig, + const void* data, + size_t rowBytes) { + GrIRect bounds = GrIRect::MakeWH(desc.fWidth, desc.fHeight); + GrIRect subrect = GrIRect::MakeXYWH(left, top, width, height); + if (!bounds.contains(subrect)) { + return; } + // ES2 glCompressedTexSubImage2D doesn't support any formats + // (at least without extensions) + GrAssert(desc.fInternalFormat != GR_GL_PALETTE8_RGBA8 || + bounds == subrect); + // in case we need a temporary, trimmed copy of the src pixels SkAutoSMalloc<128 * 128> tempStorage; + GrGLenum dontCare; + GrGLenum externalFormat; + GrGLenum externalType; + if (!this->canBeTexture(dataConfig, &dontCare, + &externalFormat, &externalType)) { + return; + } + + size_t bpp = GrBytesPerPixel(dataConfig); + size_t trimRowBytes = width * bpp; + if (!rowBytes) { + rowBytes = trimRowBytes; + } /* - * 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. + * 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 may not let us specify + * GL_UNPACK_ROW_LENGTH. */ + bool restoreGLRowLength = false; bool flipY = GrGLTexture::kBottomUp_Orientation == desc.fOrientation; if (this->glCaps().fUnpackRowLengthSupport && !flipY) { - if (data && rowBytes != trimRowBytes) { + // can't use this for flipping, only non-neg values allowed. :( + if (rowBytes != trimRowBytes) { GrGLint rowLength = static_cast<GrGLint>(rowBytes / bpp); GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, rowLength)); + restoreGLRowLength = true; } } else { - if (data && (trimRowBytes != rowBytes || flipY)) { + if (trimRowBytes != rowBytes || flipY) { // copy the data into our new storage, skipping the trailing bytes - size_t trimSize = desc.fHeight * trimRowBytes; + size_t trimSize = height * trimRowBytes; const char* src = (const char*)data; if (flipY) { - src += (desc.fHeight - 1) * rowBytes; + src += (height - 1) * rowBytes; } char* dst = (char*)tempStorage.reset(trimSize); - for (int y = 0; y < desc.fHeight; y++) { + for (int y = 0; y < height; y++) { memcpy(dst, src, trimRowBytes); if (flipY) { src -= rowBytes; @@ -721,31 +758,27 @@ void GrGpuGL::allocateAndUploadTexData(const GrGLTexture::Desc& desc, } dst += trimRowBytes; } - // now point data to our trimmed version + // now point dat to our copied version data = tempStorage.get(); - rowBytes = trimRowBytes; } } GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, static_cast<GrGLint>(bpp))); - if (kIndex_8_GrPixelConfig == desc.fConfig && - this->getCaps().f8BitPaletteSupport) { - // ES only supports CompressedTexImage2D, not CompressedTexSubimage2D - GrGLsizei imageSize = desc.fWidth * desc.fHeight + - kGrColorTableSize; - GL_CALL(CompressedTexImage2D(GR_GL_TEXTURE_2D, 0, desc.fUploadFormat, - desc.fWidth, desc.fHeight, - 0, imageSize, data)); - if (this->glCaps().fUnpackRowLengthSupport) { - GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); - } + if (bounds == subrect) { + GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, desc.fInternalFormat, + desc.fWidth, desc.fHeight, 0, + externalFormat, externalType, data)); } else { - GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, internalFormat, - desc.fWidth, desc.fHeight, 0, - desc.fUploadFormat, desc.fUploadType, data)); - if (this->glCaps().fUnpackRowLengthSupport) { - GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); + if (flipY) { + top = desc.fHeight - (top + height); } + GL_CALL(TexSubImage2D(GR_GL_TEXTURE_2D, 0, left, top, width, height, + externalFormat, externalType, data)); + } + + if (restoreGLRowLength) { + GrAssert(this->glCaps().fUnpackRowLengthSupport); + GL_CALL(PixelStorei(GR_GL_UNPACK_ROW_LENGTH, 0)); } } @@ -856,7 +889,8 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, GrGLTexture::Desc glTexDesc; GrGLRenderTarget::Desc glRTDesc; - GrGLenum internalFormat; + GrGLenum externalFormat; + GrGLenum externalType; glTexDesc.fWidth = desc.fWidth; glTexDesc.fHeight = desc.fHeight; @@ -871,9 +905,9 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, bool renderTarget = 0 != (desc.fFlags & kRenderTarget_GrTextureFlagBit); if (!canBeTexture(desc.fConfig, - &internalFormat, - &glTexDesc.fUploadFormat, - &glTexDesc.fUploadType)) { + &glTexDesc.fInternalFormat, + &externalFormat, + &externalType)) { return return_null_texture(); } @@ -928,7 +962,14 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, initialTexParams.fWrapT)); - this->allocateAndUploadTexData(glTexDesc, internalFormat,srcData, rowBytes); + if (NULL == srcData) { + GL_CALL(TexImage2D(GR_GL_TEXTURE_2D, 0, glTexDesc.fInternalFormat, + glTexDesc.fWidth, glTexDesc.fHeight, 0, + externalFormat, externalType, NULL)); + } else { + this->uploadTexData(glTexDesc, 0, 0, glTexDesc.fWidth, glTexDesc.fHeight, + desc.fConfig, srcData, rowBytes); + } GrGLTexture* tex; if (renderTarget) { @@ -2075,51 +2116,51 @@ void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { bool GrGpuGL::canBeTexture(GrPixelConfig config, GrGLenum* internalFormat, - GrGLenum* format, - GrGLenum* type) { + GrGLenum* externalFormat, + GrGLenum* externalType) { switch (config) { case kRGBA_8888_PM_GrPixelConfig: case kRGBA_8888_UPM_GrPixelConfig: - *format = GR_GL_RGBA; + *externalFormat = GR_GL_RGBA; *internalFormat = GR_GL_RGBA; - *type = GR_GL_UNSIGNED_BYTE; + *externalType = GR_GL_UNSIGNED_BYTE; break; case kBGRA_8888_PM_GrPixelConfig: case kBGRA_8888_UPM_GrPixelConfig: if (!fGLCaps.fBGRAFormatSupport) { return false; } - *format = GR_GL_BGRA; + *externalFormat = GR_GL_BGRA; if (fGLCaps.fBGRAIsInternalFormat) { *internalFormat = GR_GL_BGRA; } else { *internalFormat = GR_GL_RGBA; } - *type = GR_GL_UNSIGNED_BYTE; + *externalType = GR_GL_UNSIGNED_BYTE; break; case kRGB_565_GrPixelConfig: - *format = GR_GL_RGB; + *externalFormat = GR_GL_RGB; *internalFormat = GR_GL_RGB; - *type = GR_GL_UNSIGNED_SHORT_5_6_5; + *externalType = GR_GL_UNSIGNED_SHORT_5_6_5; break; case kRGBA_4444_GrPixelConfig: - *format = GR_GL_RGBA; + *externalFormat = GR_GL_RGBA; *internalFormat = GR_GL_RGBA; - *type = GR_GL_UNSIGNED_SHORT_4_4_4_4; + *externalType = GR_GL_UNSIGNED_SHORT_4_4_4_4; break; case kIndex_8_GrPixelConfig: if (this->getCaps().f8BitPaletteSupport) { - *format = GR_GL_PALETTE8_RGBA8; + *externalFormat = GR_GL_PALETTE8_RGBA8; *internalFormat = GR_GL_PALETTE8_RGBA8; - *type = GR_GL_UNSIGNED_BYTE; // unused I think + *externalType = GR_GL_UNSIGNED_BYTE; // unused I think } else { return false; } break; case kAlpha_8_GrPixelConfig: - *format = GR_GL_ALPHA; + *externalFormat = GR_GL_ALPHA; *internalFormat = GR_GL_ALPHA; - *type = GR_GL_UNSIGNED_BYTE; + *externalType = GR_GL_UNSIGNED_BYTE; break; default: return false; diff --git a/src/gpu/GrGpuGL.h b/src/gpu/GrGpuGL.h index c1b17eeaeb..18baedf968 100644 --- a/src/gpu/GrGpuGL.h +++ b/src/gpu/GrGpuGL.h @@ -175,6 +175,11 @@ protected: size_t rowBytes, bool invertY) SK_OVERRIDE; + virtual void onWriteTexturePixels(GrTexture* texture, + int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) SK_OVERRIDE; + virtual void onGpuDrawIndexed(GrPrimitiveType type, uint32_t startVertex, uint32_t startIndex, @@ -262,13 +267,14 @@ private: bool canBeTexture(GrPixelConfig config, GrGLenum* internalFormat, - GrGLenum* format, - GrGLenum* type); - // helpers for onCreateTexture - void allocateAndUploadTexData(const GrGLTexture::Desc& desc, - GrGLenum internalFormat, - const void* data, - size_t rowBytes); + GrGLenum* externalFormat, + GrGLenum* externalType); + // helper for onCreateTexture and writeTexturePixels + void uploadTexData(const GrGLTexture::Desc& desc, + int left, int top, int width, int height, + GrPixelConfig dataConfig, + const void* data, + size_t rowBytes); bool createRenderTargetObjects(int width, int height, GrGLuint texID, diff --git a/src/gpu/GrRenderTarget.cpp b/src/gpu/GrRenderTarget.cpp index 7a53c0b301..7901648d3a 100644 --- a/src/gpu/GrRenderTarget.cpp +++ b/src/gpu/GrRenderTarget.cpp @@ -14,14 +14,31 @@ #include "GrStencilBuffer.h" bool GrRenderTarget::readPixels(int left, int top, int width, int height, - GrPixelConfig config, void* buffer) { + GrPixelConfig config, void* buffer, + size_t rowBytes) { // go through context so that all necessary flushing occurs - GrContext* context = this->getGpu()->getContext(); - GrAssert(NULL != context); + GrContext* context = this->getContext(); + if (NULL == context) { + return false; + } return context->readRenderTargetPixels(this, - left, top, + left, top, width, height, - config, buffer); + config, buffer, rowBytes); +} + +void GrRenderTarget::writePixels(int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) { + // go through context so that all necessary flushing occurs + GrContext* context = this->getContext(); + if (NULL == context) { + return; + } + context->writeRenderTargetPixels(this, + left, top, + width, height, + config, buffer, rowBytes); } size_t GrRenderTarget::sizeInBytes() const { diff --git a/src/gpu/GrTexture.cpp b/src/gpu/GrTexture.cpp index 77868dfc9f..c145c71a1b 100644 --- a/src/gpu/GrTexture.cpp +++ b/src/gpu/GrTexture.cpp @@ -14,14 +14,31 @@ #include "GrRenderTarget.h" bool GrTexture::readPixels(int left, int top, int width, int height, - GrPixelConfig config, void* buffer) { + GrPixelConfig config, void* buffer, + size_t rowBytes) { // go through context so that all necessary flushing occurs - GrContext* context = this->getGpu()->getContext(); - GrAssert(NULL != context); + GrContext* context = this->getContext(); + if (NULL == context) { + return false; + } return context->readTexturePixels(this, - left, top, - width, height, - config, buffer); + left, top, + width, height, + config, buffer, rowBytes); +} + +void GrTexture::writePixels(int left, int top, int width, int height, + GrPixelConfig config, const void* buffer, + size_t rowBytes) { + // go through context so that all necessary flushing occurs + GrContext* context = this->getContext(); + if (NULL == context) { + return; + } + context->writeTexturePixels(this, + left, top, + width, height, + config, buffer, rowBytes); } void GrTexture::releaseRenderTarget() { diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 91184b70ff..69973be928 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -314,13 +314,8 @@ void SkGpuDevice::writePixels(const SkBitmap& bitmap, int x, int y, bitmap.isOpaque()); } - fContext->setRenderTarget(fRenderTarget); - // we aren't setting the clip or matrix, so mark as dirty - // we don't need to set them for this call and don't have them anyway - fNeedPrepareRenderTarget = true; - - fContext->writePixels(x, y, bitmap.width(), bitmap.height(), - config, bitmap.getPixels(), bitmap.rowBytes()); + fRenderTarget->writePixels(x, y, bitmap.width(), bitmap.height(), + config, bitmap.getPixels(), bitmap.rowBytes()); } /////////////////////////////////////////////////////////////////////////////// @@ -1031,7 +1026,7 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path, if (NULL == texture) { return false; } - texture->uploadTextureData(0, 0, desc.fWidth, desc.fHeight, + texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig, dstM.fImage, dstM.fRowBytes); if (grp->hasTextureOrMask() && ivm.invert(&ivm)) { diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 6a3941079c..e76ec5db6e 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -99,8 +99,9 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, } else { entry = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); - entry.texture()->uploadTextureData(0, 0, bitmap->width(), - bitmap->height(), storage.get(), 0); + entry.texture()->writePixels(0, 0, bitmap->width(), + bitmap->height(), desc.fConfig, + storage.get(), 0); return entry; } @@ -119,8 +120,11 @@ GrContext::TextureCacheEntry sk_gr_create_bitmap_texture(GrContext* ctx, } else { entry = ctx->lockScratchTexture(desc, GrContext::kExact_ScratchTexMatch); - entry.texture()->uploadTextureData(0, 0, bitmap->width(), - bitmap->height(), bitmap->getPixels(), bitmap->rowBytes()); + entry.texture()->writePixels(0, 0, + bitmap->width(), bitmap->height(), + desc.fConfig, + bitmap->getPixels(), + bitmap->rowBytes()); return entry; } } diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index 140993a6aa..8d0eb892c8 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -79,7 +79,7 @@ bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { void* buffer = dst->getPixels(); return fTexture->readPixels(left, top, width, height, kSkia8888_PM_GrPixelConfig, - buffer); + buffer, dst->rowBytes()); } else { return false; } @@ -123,7 +123,7 @@ bool SkGrRenderTargetPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset void* buffer = dst->getPixels(); return fRenderTarget->readPixels(left, top, width, height, kSkia8888_PM_GrPixelConfig, - buffer); + buffer, dst->rowBytes()); } else { return false; } |