From 50dfa0130b0705414df7ba7da9915139f6320b09 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Fri, 1 Apr 2011 19:05:36 +0000 Subject: add pixelref->readPixels() unimplemented (for now) on the gpu side git-svn-id: http://skia.googlecode.com/svn/trunk@1037 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkPixelRef.h | 12 +++++++ include/gpu/SkGrTexturePixelRef.h | 1 + src/core/SkBitmap.cpp | 75 +++++++++++++++++++++++++-------------- src/core/SkPixelRef.cpp | 8 +++++ src/gpu/SkGrTexturePixelRef.cpp | 3 ++ 5 files changed, 72 insertions(+), 27 deletions(-) diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index 177ececf5d..8fb368ac32 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -20,7 +20,9 @@ #include "SkRefCnt.h" #include "SkString.h" +class SkBitmap; class SkColorTable; +struct SkIRect; class SkMutex; class SkFlattenableReadBuffer; class SkFlattenableWriteBuffer; @@ -112,6 +114,8 @@ public: */ virtual SkGpuTexture* getTexture() { return NULL; } + bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL); + // serialization typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&); @@ -157,6 +161,14 @@ protected: */ virtual void onUnlockPixels() = 0; + /** + * For pixelrefs that don't have access to their raw pixels, they may be + * able to make a copy of them (e.g. if the pixels are on the GPU). + * + * The base class implementation returns false; + */ + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subsetOrNull); + /** Return the mutex associated with this pixelref. This value is assigned in the constructor, and cannot change during the lifetime of the object. */ diff --git a/include/gpu/SkGrTexturePixelRef.h b/include/gpu/SkGrTexturePixelRef.h index 1f5133f86d..a423251c78 100644 --- a/include/gpu/SkGrTexturePixelRef.h +++ b/include/gpu/SkGrTexturePixelRef.h @@ -40,6 +40,7 @@ protected: // override from SkPixelRef virtual void onUnlockPixels() {} + virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset); private: GrTexture* fTexture; diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index a5f7d57ad5..a9b9c99d9e 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -865,61 +865,82 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { return false; } + // if we have a texture, first get those pixels + SkBitmap tmpSrc; + const SkBitmap* src = this; + + if (this->getTexture()) { + if (!fPixelRef->readPixels(&tmpSrc)) { + return false; + } + SkASSERT(tmpSrc.width() == this->width()); + SkASSERT(tmpSrc.height() == this->height()); + + // did we get lucky and we can just return tmpSrc? + if (tmpSrc.config() == dstConfig && NULL == alloc) { + dst->swap(tmpSrc); + return true; + } + + // fall through to the raster case + src = &tmpSrc; + } + // we lock this now, since we may need its colortable - SkAutoLockPixels srclock(*this); - if (!this->readyToDraw()) { + SkAutoLockPixels srclock(*src); + if (!src->readyToDraw()) { return false; } - - SkBitmap tmp; - tmp.setConfig(dstConfig, this->width(), this->height()); - + + SkBitmap tmpDst; + tmpDst.setConfig(dstConfig, src->width(), src->height()); + // allocate colortable if srcConfig == kIndex8_Config SkColorTable* ctable = (dstConfig == kIndex8_Config) ? - new SkColorTable(*this->getColorTable()) : NULL; + new SkColorTable(*src->getColorTable()) : NULL; SkAutoUnref au(ctable); - if (!tmp.allocPixels(alloc, ctable)) { + if (!tmpDst.allocPixels(alloc, ctable)) { return false; } - - SkAutoLockPixels dstlock(tmp); - if (!tmp.readyToDraw()) { + + SkAutoLockPixels dstlock(tmpDst); + if (!tmpDst.readyToDraw()) { // allocator/lock failed return false; } - + /* do memcpy for the same configs cases, else use drawing */ - if (this->config() == dstConfig) { - if (tmp.getSize() == this->getSize()) { - memcpy(tmp.getPixels(), this->getPixels(), this->getSafeSize()); + if (src->config() == dstConfig) { + if (tmpDst.getSize() == src->getSize()) { + memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); } else { - const char* srcP = reinterpret_cast(this->getPixels()); - char* dstP = reinterpret_cast(tmp.getPixels()); + const char* srcP = reinterpret_cast(src->getPixels()); + char* dstP = reinterpret_cast(tmpDst.getPixels()); // to be sure we don't read too much, only copy our logical pixels - size_t bytesToCopy = tmp.width() * tmp.bytesPerPixel(); - for (int y = 0; y < tmp.height(); y++) { + size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); + for (int y = 0; y < tmpDst.height(); y++) { memcpy(dstP, srcP, bytesToCopy); - srcP += this->rowBytes(); - dstP += tmp.rowBytes(); + srcP += src->rowBytes(); + dstP += tmpDst.rowBytes(); } } } else { // if the src has alpha, we have to clear the dst first - if (!this->isOpaque()) { - tmp.eraseColor(0); + if (!src->isOpaque()) { + tmpDst.eraseColor(0); } - SkCanvas canvas(tmp); + SkCanvas canvas(tmpDst); SkPaint paint; paint.setDither(true); - canvas.drawBitmap(*this, 0, 0, &paint); + canvas.drawBitmap(*src, 0, 0, &paint); } - tmp.setIsOpaque(this->isOpaque()); + tmpDst.setIsOpaque(src->isOpaque()); - dst->swap(tmp); + dst->swap(tmpDst); return true; } diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp index f558f52c2d..9b12226af2 100644 --- a/src/core/SkPixelRef.cpp +++ b/src/core/SkPixelRef.cpp @@ -79,6 +79,14 @@ void SkPixelRef::setImmutable() { fIsImmutable = true; } +bool SkPixelRef::readPixels(SkBitmap* dst, const SkIRect* subset) { + return this->onReadPixels(dst, subset); +} + +bool SkPixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + return false; +} + /////////////////////////////////////////////////////////////////////////////// #define MAX_PAIR_COUNT 16 diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index da9ac1a692..de19f1da32 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -27,4 +27,7 @@ SkGrTexturePixelRef::~SkGrTexturePixelRef() { GrSafeUnref(fTexture); } +bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) { + return false; +} -- cgit v1.2.3