For SkGPipe, store bitmaps in a common location.

Also make a change to SkBitmap::copyTo() so that we do not
crash.
Review URL: https://codereview.appspot.com/6296066

git-svn-id: http://skia.googlecode.com/svn/trunk@4249 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
scroggo@google.com 2012-06-13 17:47:52 +00:00
parent aaf1688959
commit 8ae3c7f67e
3 changed files with 93 additions and 25 deletions

View File

@ -925,7 +925,6 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
return false;
}
SkAutoLockPixels dstlock(tmpDst);
if (!tmpDst.readyToDraw()) {
// allocator/lock failed
return false;

View File

@ -347,8 +347,7 @@ static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op3
static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
unsigned index = DrawOp_unpackData(op32);
SkBitmap* bm = state->getBitmap(index);
const SkBitmap* bm(static_cast<const SkBitmap*>(reader->readPtr()));
bool hasPaint = reader->readBool();
SkScalar left = reader->readScalar();
SkScalar top = reader->readScalar();
@ -362,8 +361,7 @@ static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t o
static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
uint32_t op32, SkGPipeState* state) {
unsigned index = DrawOp_unpackData(op32);
SkBitmap* bm = state->getBitmap(index);
const SkBitmap* bm(static_cast<const SkBitmap*>(reader->readPtr()));
bool hasPaint = reader->readBool();
const SkIRect* center = skip<SkIRect>(reader);
const SkRect* dst = skip<SkRect>(reader);
@ -373,8 +371,7 @@ static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
uint32_t op32, SkGPipeState* state) {
unsigned index = DrawOp_unpackData(op32);
SkBitmap* bm = state->getBitmap(index);
const SkBitmap* bm(static_cast<const SkBitmap*>(reader->readPtr()));
bool hasPaint = reader->readBool();
bool hasSrc = reader->readBool();
const SkIRect* src;
@ -389,8 +386,7 @@ static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
unsigned index = DrawOp_unpackData(op32);
SkBitmap* bm = state->getBitmap(index);
const SkBitmap* bm(static_cast<const SkBitmap*>(reader->readPtr()));
bool hasPaint = reader->readBool();
const SkIPoint* point = skip<SkIPoint>(reader);
canvas->drawSprite(*bm, point->fX, point->fY, hasPaint ? &state->paint() : NULL);

View File

@ -58,6 +58,62 @@ static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
///////////////////////////////////////////////////////////////////////////////
/*
* Shared heap for storing large things that can be shared, for a stream
* used by multiple readers.
* TODO: Make the allocations all come from cross process safe address space
* TODO: Store paths (others?)
* TODO: Allow reclaiming of memory. Will require us to know when all readers
* have used the object.
*/
class Heap {
public:
Heap() {}
~Heap() {
for (int i = 0; i < fBitmaps.count(); i++) {
delete fBitmaps[i].fBitmap;
}
}
/*
* Add a copy of a bitmap to the heap.
* @param bm The SkBitmap to be copied and placed in the heap.
* @return void* Pointer to the heap's copy of the bitmap. If NULL,
* the bitmap could not be copied.
*/
const SkBitmap* addBitmap(const SkBitmap& bm) {
const uint32_t genID = bm.getGenerationID();
for (int i = fBitmaps.count() - 1; i >= 0; i--) {
if (genID == fBitmaps[i].fGenID) {
return fBitmaps[i].fBitmap;
}
}
// TODO: Use a flag to determine whether we need the bitmap to be
// in shared cross process address space. If not, we can do a shallow
// copy.
SkBitmap* copy = new SkBitmap();
if (bm.copyTo(copy, bm.getConfig())) {
BitmapInfo* info = fBitmaps.append();
info->fBitmap = copy;
info->fGenID = genID;
return copy;
}
delete copy;
return NULL;
}
private:
struct BitmapInfo {
SkBitmap* fBitmap;
// Store the generation ID of the original bitmap, since copying does
// not copy this field, so fBitmap's generation ID will not be useful
// for comparing.
uint32_t fGenID;
};
SkTDArray<BitmapInfo>fBitmaps;
};
///////////////////////////////////////////////////////////////////////////////
class SkGPipeCanvas : public SkCanvas {
public:
SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*);
@ -124,6 +180,7 @@ public:
virtual void drawData(const void*, size_t) SK_OVERRIDE;
private:
Heap fHeap;
SkFactorySet* fFactorySet; // optional, only used if cross-process
SkGPipeController* fController;
SkWriter32& fWriter;
@ -539,17 +596,19 @@ void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
const SkPaint* paint) {
// This is the brute-force solution
// TODO: add the notion of a shared, counted for large immutable resources
const void* ptr(fHeap.addBitmap(bm));
if (NULL == ptr) {
return;
}
NOTIFY_SETUP(this);
if (paint) {
this->writePaint(*paint);
}
int bitmapIndex = this->flattenToIndex(bm);
if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool))) {
this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool) + sizeof(void*))) {
this->writeOp(kDrawBitmap_DrawOp, 0, 0);
fWriter.writePtr(const_cast<void*>(ptr));
fWriter.writeBool(paint != NULL);
fWriter.writeScalar(left);
fWriter.writeScalar(top);
@ -558,20 +617,24 @@ void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
const SkRect& dst, const SkPaint* paint) {
const void* ptr(fHeap.addBitmap(bm));
if (NULL == ptr) {
return;
}
NOTIFY_SETUP(this);
if (paint) {
this->writePaint(*paint);
}
int bitmapIndex = this->flattenToIndex(bm);
size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2 + sizeof(void*);
bool hasSrc = src != NULL;
if (hasSrc) {
opBytesNeeded += sizeof(int32_t) * 4;
}
if (this->needOpBytes(opBytesNeeded)) {
this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
this->writeOp(kDrawBitmapRect_DrawOp, 0, 0);
fWriter.writePtr(const_cast<void*>(ptr));
fWriter.writeBool(paint != NULL);
fWriter.writeBool(hasSrc);
if (hasSrc) {
@ -591,15 +654,20 @@ void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
const void* ptr(fHeap.addBitmap(bm));
if (NULL == ptr) {
return;
}
NOTIFY_SETUP(this);
if (paint) {
this->writePaint(*paint);
}
int bitmapIndex = this->flattenToIndex(bm);
if (this->needOpBytes(sizeof(int32_t) * 4 + sizeof(bool)
+ sizeof(SkRect))) {
this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
+ sizeof(SkRect) + sizeof(void*))) {
this->writeOp(kDrawBitmapNine_DrawOp, 0, 0);
fWriter.writePtr(const_cast<void*>(ptr));
fWriter.writeBool(paint != NULL);
fWriter.write32(center.fLeft);
fWriter.write32(center.fTop);
@ -611,14 +679,19 @@ void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
const SkPaint* paint) {
const void* ptr(fHeap.addBitmap(bm));
if (NULL == ptr) {
return;
}
NOTIFY_SETUP(this);
if (paint) {
this->writePaint(*paint);
}
int bitmapIndex = this->flattenToIndex(bm);
if (this->needOpBytes(sizeof(int32_t) * 2 + sizeof(bool))) {
this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
if (this->needOpBytes(sizeof(int32_t) * 2 + sizeof(bool) + sizeof(void*))) {
this->writeOp(kDrawSprite_DrawOp, 0, 0);
fWriter.writePtr(const_cast<void*>(ptr));
fWriter.writeBool(paint != NULL);
fWriter.write32(left);
fWriter.write32(top);