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
This commit is contained in:
reed@google.com 2011-04-01 19:05:36 +00:00
parent 5d561959dc
commit 50dfa0130b
5 changed files with 73 additions and 28 deletions

View File

@ -20,7 +20,9 @@
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "SkString.h" #include "SkString.h"
class SkBitmap;
class SkColorTable; class SkColorTable;
struct SkIRect;
class SkMutex; class SkMutex;
class SkFlattenableReadBuffer; class SkFlattenableReadBuffer;
class SkFlattenableWriteBuffer; class SkFlattenableWriteBuffer;
@ -112,6 +114,8 @@ public:
*/ */
virtual SkGpuTexture* getTexture() { return NULL; } virtual SkGpuTexture* getTexture() { return NULL; }
bool readPixels(SkBitmap* dst, const SkIRect* subset = NULL);
// serialization // serialization
typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&); typedef SkPixelRef* (*Factory)(SkFlattenableReadBuffer&);
@ -157,6 +161,14 @@ protected:
*/ */
virtual void onUnlockPixels() = 0; 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 /** Return the mutex associated with this pixelref. This value is assigned
in the constructor, and cannot change during the lifetime of the object. in the constructor, and cannot change during the lifetime of the object.
*/ */

View File

@ -40,6 +40,7 @@ protected:
// override from SkPixelRef // override from SkPixelRef
virtual void onUnlockPixels() {} virtual void onUnlockPixels() {}
virtual bool onReadPixels(SkBitmap* dst, const SkIRect* subset);
private: private:
GrTexture* fTexture; GrTexture* fTexture;

View File

@ -865,61 +865,82 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
return false; 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 // we lock this now, since we may need its colortable
SkAutoLockPixels srclock(*this); SkAutoLockPixels srclock(*src);
if (!this->readyToDraw()) { if (!src->readyToDraw()) {
return false; return false;
} }
SkBitmap tmp; SkBitmap tmpDst;
tmp.setConfig(dstConfig, this->width(), this->height()); tmpDst.setConfig(dstConfig, src->width(), src->height());
// allocate colortable if srcConfig == kIndex8_Config // allocate colortable if srcConfig == kIndex8_Config
SkColorTable* ctable = (dstConfig == kIndex8_Config) ? SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
new SkColorTable(*this->getColorTable()) : NULL; new SkColorTable(*src->getColorTable()) : NULL;
SkAutoUnref au(ctable); SkAutoUnref au(ctable);
if (!tmp.allocPixels(alloc, ctable)) { if (!tmpDst.allocPixels(alloc, ctable)) {
return false; return false;
} }
SkAutoLockPixels dstlock(tmp); SkAutoLockPixels dstlock(tmpDst);
if (!tmp.readyToDraw()) { if (!tmpDst.readyToDraw()) {
// allocator/lock failed // allocator/lock failed
return false; return false;
} }
/* do memcpy for the same configs cases, else use drawing /* do memcpy for the same configs cases, else use drawing
*/ */
if (this->config() == dstConfig) { if (src->config() == dstConfig) {
if (tmp.getSize() == this->getSize()) { if (tmpDst.getSize() == src->getSize()) {
memcpy(tmp.getPixels(), this->getPixels(), this->getSafeSize()); memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
} else { } else {
const char* srcP = reinterpret_cast<const char*>(this->getPixels()); const char* srcP = reinterpret_cast<const char*>(src->getPixels());
char* dstP = reinterpret_cast<char*>(tmp.getPixels()); char* dstP = reinterpret_cast<char*>(tmpDst.getPixels());
// to be sure we don't read too much, only copy our logical pixels // to be sure we don't read too much, only copy our logical pixels
size_t bytesToCopy = tmp.width() * tmp.bytesPerPixel(); size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel();
for (int y = 0; y < tmp.height(); y++) { for (int y = 0; y < tmpDst.height(); y++) {
memcpy(dstP, srcP, bytesToCopy); memcpy(dstP, srcP, bytesToCopy);
srcP += this->rowBytes(); srcP += src->rowBytes();
dstP += tmp.rowBytes(); dstP += tmpDst.rowBytes();
} }
} }
} else { } else {
// if the src has alpha, we have to clear the dst first // if the src has alpha, we have to clear the dst first
if (!this->isOpaque()) { if (!src->isOpaque()) {
tmp.eraseColor(0); tmpDst.eraseColor(0);
} }
SkCanvas canvas(tmp); SkCanvas canvas(tmpDst);
SkPaint paint; SkPaint paint;
paint.setDither(true); 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; return true;
} }

View File

@ -79,6 +79,14 @@ void SkPixelRef::setImmutable() {
fIsImmutable = true; 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 #define MAX_PAIR_COUNT 16

View File

@ -27,4 +27,7 @@ SkGrTexturePixelRef::~SkGrTexturePixelRef() {
GrSafeUnref(fTexture); GrSafeUnref(fTexture);
} }
bool SkGrTexturePixelRef::onReadPixels(SkBitmap* dst, const SkIRect* subset) {
return false;
}