aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-11-16 20:36:03 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-11-16 20:36:03 +0000
commit6f3795105b2b458079e53a721c1735c9518f6bb5 (patch)
tree107d2ec0b8986a3bf96220fe9e86974fe9f7b8e3 /src
parentaa336da0838c3da8b3be2e0348da3c6abeebf273 (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.cpp10
-rw-r--r--src/gpu/GrContext.cpp83
-rw-r--r--src/gpu/GrGLTexture.cpp80
-rw-r--r--src/gpu/GrGLTexture.h16
-rw-r--r--src/gpu/GrGpu.cpp11
-rw-r--r--src/gpu/GrGpu.h22
-rw-r--r--src/gpu/GrGpuGL.cpp163
-rw-r--r--src/gpu/GrGpuGL.h20
-rw-r--r--src/gpu/GrRenderTarget.cpp27
-rw-r--r--src/gpu/GrTexture.cpp29
-rw-r--r--src/gpu/SkGpuDevice.cpp11
-rw-r--r--src/gpu/SkGr.cpp12
-rw-r--r--src/gpu/SkGrTexturePixelRef.cpp4
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;
}