Allow texture-backed bitmaps to perform a read-back when lockPixels is called.
This means we have to be even more cautious about when we call lock, and we should
always check getTexture() first if we can handle a texture directly, rather than
forcing the read-back to get the bits.
git-svn-id: http://skia.googlecode.com/svn/trunk@1815 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index cdb74bb..92ff88a 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -350,6 +350,14 @@
SkDEBUGCODE(this->validate();)
}
+bool SkBitmap::lockPixelsAreWritable() const {
+ if (fPixelRef) {
+ return fPixelRef->lockPixelsAreWritable();
+ } else {
+ return fPixels != NULL;
+ }
+}
+
void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
this->freePixels();
fPixels = p;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 78b2dcc..b4f5866 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -57,11 +57,15 @@
}
void SkDevice::lockPixels() {
- fBitmap.lockPixels();
+ if (fBitmap.lockPixelsAreWritable()) {
+ fBitmap.lockPixels();
+ }
}
void SkDevice::unlockPixels() {
- fBitmap.unlockPixels();
+ if (fBitmap.lockPixelsAreWritable()) {
+ fBitmap.unlockPixels();
+ }
}
const SkBitmap& SkDevice::accessBitmap(bool changePixels) {
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index 967a872..f850891 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -4,7 +4,8 @@
static SkMutex gPixelRefMutex;
-extern int32_t SkNextPixelRefGenerationID() {
+extern int32_t SkNextPixelRefGenerationID();
+int32_t SkNextPixelRefGenerationID() {
static int32_t gPixelRefGenerationID;
// do a loop in case our global wraps around, as we never want to
// return a 0
@@ -63,6 +64,14 @@
}
}
+bool SkPixelRef::lockPixelsAreWritable() const {
+ return this->onLockPixelsAreWritable();
+}
+
+bool SkPixelRef::onLockPixelsAreWritable() const {
+ return true;
+}
+
uint32_t SkPixelRef::getGenerationID() const {
if (0 == fGenerationID) {
fGenerationID = SkNextPixelRefGenerationID();
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index b8cc2bb..508ace0 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1088,8 +1088,9 @@
SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() &&
bitmap.height() <= fContext->getMaxTextureSize());
- SkAutoLockPixels alp(bitmap);
+ SkAutoLockPixels alp(bitmap, !bitmap.getTexture());
if (!bitmap.getTexture() && !bitmap.readyToDraw()) {
+ SkDebugf("nothing to draw\n");
return;
}
diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp
index 8becfd4..4fc03ab 100644
--- a/src/gpu/SkGrTexturePixelRef.cpp
+++ b/src/gpu/SkGrTexturePixelRef.cpp
@@ -16,11 +16,42 @@
#include "SkGrTexturePixelRef.h"
-
#include "GrTexture.h"
-
#include "SkRect.h"
-#include "SkBitmap.h"
+
+// since we call lockPixels recursively on fBitmap, we need a distinct mutex,
+// to avoid deadlock with the default one provided by SkPixelRef.
+static SkMutex gROLockPixelsPixelRefMutex;
+
+SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) {
+}
+
+SkROLockPixelsPixelRef::~SkROLockPixelsPixelRef() {
+}
+
+void* SkROLockPixelsPixelRef::onLockPixels(SkColorTable** ctable) {
+ if (ctable) {
+ *ctable = NULL;
+ }
+ fBitmap.reset();
+// SkDebugf("---------- calling readpixels in support of lockpixels\n");
+ if (!this->onReadPixels(&fBitmap, NULL)) {
+ SkDebugf("SkROLockPixelsPixelRef::onLockPixels failed!\n");
+ return NULL;
+ }
+ fBitmap.lockPixels();
+ return fBitmap.getPixels();
+}
+
+void SkROLockPixelsPixelRef::onUnlockPixels() {
+ fBitmap.unlockPixels();
+}
+
+bool SkROLockPixelsPixelRef::onLockPixelsAreWritable() const {
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
SkGrTexturePixelRef::SkGrTexturePixelRef(GrTexture* tex) {
fTexture = tex;
@@ -31,6 +62,10 @@
GrSafeUnref(fTexture);
}
+SkGpuTexture* SkGrTexturePixelRef::getTexture() {
+ return (SkGpuTexture*)fTexture;
+}
+
bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
if (NULL != fTexture && fTexture->isValid()) {
int left, top, width, height;
@@ -57,7 +92,7 @@
}
}
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
SkGrRenderTargetPixelRef::SkGrRenderTargetPixelRef(GrRenderTarget* rt) {
fRenderTarget = rt;
@@ -100,3 +135,4 @@
return false;
}
}
+