Updates for SkGPipe.
Keep track of SkBitmaps which have been flattened by
the PipeWriter so we can reuse them.
Implement other flavors of drawBitmap (except
drawBitmapMatrix).
Flatten SkImageFilters in SkPaints.
Do not notify if no new data has been written.
Review URL: https://codereview.appspot.com/6128062
git-svn-id: http://skia.googlecode.com/svn/trunk@3826 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h
index 2baf75a..5b6bcc0 100644
--- a/src/pipe/SkGPipePriv.h
+++ b/src/pipe/SkGPipePriv.h
@@ -23,6 +23,7 @@
kPathEffect_PaintFlat,
kRasterizer_PaintFlat,
kShader_PaintFlat,
+ kImageFilter_PaintFlat,
kXfermode_PaintFlat,
kLast_PaintFlat = kXfermode_PaintFlat
@@ -39,6 +40,7 @@
kConcat_DrawOp,
kDrawBitmap_DrawOp,
kDrawBitmapMatrix_DrawOp,
+ kDrawBitmapNine_DrawOp,
kDrawBitmapRect_DrawOp,
kDrawClear_DrawOp,
kDrawData_DrawOp,
@@ -66,6 +68,7 @@
kDef_Typeface_DrawOp,
kDef_Flattenable_DrawOp,
+ kDef_Bitmap_DrawOp,
// these are signals to playback, not drawing verbs
kDone_DrawOp,
diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp
index 7642f35..cc7361f 100644
--- a/src/pipe/SkGPipeRead.cpp
+++ b/src/pipe/SkGPipeRead.cpp
@@ -46,6 +46,9 @@
case kShader_PaintFlat:
paint->setShader((SkShader*)obj);
break;
+ case kImageFilter_PaintFlat:
+ paint->setImageFilter((SkImageFilter*)obj);
+ break;
case kXfermode_PaintFlat:
paint->setXfermode((SkXfermode*)obj);
break;
@@ -85,6 +88,19 @@
*fFlatArray.append() = obj;
}
+ void addBitmap(int index) {
+ SkASSERT(fBitmaps.count() == index);
+ SkBitmap* bm = new SkBitmap();
+ size_t size = fReader->readU32();
+ SkOrderedReadBuffer readBuffer(fReader->skip(size), size);
+ bm->unflatten(readBuffer);
+ *fBitmaps.append() = bm;
+ }
+
+ SkBitmap* getBitmap(unsigned index) {
+ return fBitmaps[index];
+ }
+
void addTypeface() {
size_t size = fReader->readU32();
const void* data = fReader->skip(SkAlign4(size));
@@ -102,6 +118,7 @@
SkTDArray<SkFlattenable*> fFlatArray;
SkTDArray<SkTypeface*> fTypefaces;
SkTDArray<SkFlattenable::Factory> fFactoryArray;
+ SkTDArray<SkBitmap*> fBitmaps;
};
///////////////////////////////////////////////////////////////////////////////
@@ -329,14 +346,12 @@
static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
- uint32_t bitmapSize = reader->readU32();
- SkOrderedReadBuffer readBuffer(reader->skip(bitmapSize), bitmapSize);
- SkBitmap bm;
- bm.unflatten(readBuffer);
+ unsigned index = DrawOp_unpackData(op32);
+ SkBitmap* bm = state->getBitmap(index);
bool hasPaint = reader->readBool();
SkScalar left = reader->readScalar();
SkScalar top = reader->readScalar();
- canvas->drawBitmap(bm, left, top, hasPaint ? &state->paint() : NULL);
+ canvas->drawBitmap(*bm, left, top, hasPaint ? &state->paint() : NULL);
}
static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
@@ -344,14 +359,41 @@
UNIMPLEMENTED
}
-static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
- SkGPipeState* state) {
- UNIMPLEMENTED
+static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
+ uint32_t op32, SkGPipeState* state) {
+ unsigned index = DrawOp_unpackData(op32);
+ SkBitmap* bm = state->getBitmap(index);
+ bool hasPaint = reader->readBool();
+ SkIRect center = SkIRect::MakeLTRB(reader->readInt(), reader->readInt(),
+ reader->readInt(), reader->readInt());
+ const SkRect* dst = skip<SkRect>(reader);
+ canvas->drawBitmapNine(*bm, center, *dst,
+ hasPaint ? &state->paint() : NULL);
+}
+
+static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
+ uint32_t op32, SkGPipeState* state) {
+ unsigned index = DrawOp_unpackData(op32);
+ SkBitmap* bm = state->getBitmap(index);
+ bool hasPaint = reader->readBool();
+ bool hasSrc = reader->readBool();
+ SkIRect src;
+ if (hasSrc) {
+ src = SkIRect::MakeLTRB(reader->readInt(), reader->readInt(),
+ reader->readInt(), reader->readInt());
+ }
+ const SkRect* dst = skip<SkRect>(reader);
+ canvas->drawBitmapRect(*bm, hasSrc ? &src : NULL, *dst,
+ hasPaint ? &state->paint() : NULL);
}
static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
- UNIMPLEMENTED
+ unsigned index = DrawOp_unpackData(op32);
+ SkBitmap* bm = state->getBitmap(index);
+ bool hasPaint = reader->readBool();
+ canvas->drawSprite(*bm, reader->readInt(), reader->readInt(),
+ hasPaint ? &state->paint() : NULL);
}
///////////////////////////////////////////////////////////////////////////////
@@ -432,6 +474,12 @@
state->defFlattenable(pf, index);
}
+static void def_Bitmap_rp(SkCanvas*, SkReader32*, uint32_t op32,
+ SkGPipeState* state) {
+ unsigned index = DrawOp_unpackData(op32);
+ state->addBitmap(index);
+}
+
///////////////////////////////////////////////////////////////////////////////
static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
@@ -451,6 +499,7 @@
concat_rp,
drawBitmap_rp,
drawBitmapMatrix_rp,
+ drawBitmapNine_rp,
drawBitmapRect_rp,
drawClear_rp,
drawData_rp,
@@ -477,6 +526,7 @@
paintOp_rp,
def_Typeface_rp,
def_PaintFlat_rp,
+ def_Bitmap_rp,
done_rp
};
@@ -488,6 +538,7 @@
SkGPipeState::~SkGPipeState() {
fTypefaces.safeUnrefAll();
fFlatArray.safeUnrefAll();
+ fBitmaps.deleteAll();
}
///////////////////////////////////////////////////////////////////////////////
@@ -541,7 +592,8 @@
if (readAtom &&
(table[op] != paintOp_rp &&
table[op] != def_Typeface_rp &&
- table[op] != def_PaintFlat_rp
+ table[op] != def_PaintFlat_rp &&
+ table[op] != def_Bitmap_rp
)) {
status = kReadAtom_Status;
break;
diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp
index 9802b12..b06d40e 100644
--- a/src/pipe/SkGPipeWrite.cpp
+++ b/src/pipe/SkGPipeWrite.cpp
@@ -14,6 +14,7 @@
#include "SkPaint.h"
#include "SkGPipe.h"
#include "SkGPipePriv.h"
+#include "SkImageFilter.h"
#include "SkStream.h"
#include "SkTSearch.h"
#include "SkTypeface.h"
@@ -34,6 +35,7 @@
case kPathEffect_PaintFlat: return paint.getPathEffect();
case kRasterizer_PaintFlat: return paint.getRasterizer();
case kShader_PaintFlat: return paint.getShader();
+ case kImageFilter_PaintFlat: return paint.getImageFilter();
case kXfermode_PaintFlat: return paint.getXfermode();
}
SkDEBUGFAIL("never gets here");
@@ -161,8 +163,10 @@
inline void doNotify() {
if (!fDone) {
size_t bytes = fWriter.size() - fBytesNotified;
- fController->notifyWritten(bytes);
- fBytesNotified += bytes;
+ if (bytes > 0) {
+ fController->notifyWritten(bytes);
+ fBytesNotified += bytes;
+ }
}
}
@@ -176,6 +180,10 @@
return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
}
};
+
+ SkTDArray<FlatData*> fBitmapArray;
+ int flattenToIndex(const SkBitmap&);
+
SkTDArray<FlatData*> fFlatArray;
int fCurrFlatIndex[kCount_PaintFlats];
int flattenToIndex(SkFlattenable* obj, PaintFlats);
@@ -195,6 +203,41 @@
typedef SkCanvas INHERITED;
};
+int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
+ SkOrderedWriteBuffer tmpWriter(1024);
+ // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
+ // so that we can store a pointer to a bitmap's pixels during flattening.
+ tmpWriter.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
+ bitmap.flatten(tmpWriter);
+
+ size_t len = tmpWriter.size();
+ size_t allocSize = len + sizeof(FlatData);
+
+ SkAutoSMalloc<1024> storage(allocSize);
+ FlatData* flat = (FlatData*)storage.get();
+ flat->fSize = len;
+ tmpWriter.flatten(flat->data());
+
+ int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
+ fBitmapArray.count(), flat, sizeof(flat),
+ &FlatData::Compare);
+ if (index < 0) {
+ index = ~index;
+ FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
+ memcpy(copy, flat, allocSize);
+ // For bitmaps, we can use zero based indices, since we will never ask
+ // for a NULL bitmap (unlike with paint flattenables).
+ copy->fIndex = fBitmapArray.count();
+ *fBitmapArray.insert(index) = copy;
+ if (this->needOpBytes(len + sizeof(uint32_t))) {
+ this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
+ fWriter.write32(len);
+ fWriter.write(copy->data(), len);
+ }
+ }
+ return fBitmapArray[index]->fIndex;
+}
+
// return 0 for NULL (or unflattenable obj), or index-base-1
int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
if (NULL == obj) {
@@ -267,6 +310,7 @@
this->finish();
fFlatArray.freeAll();
+ fBitmapArray.freeAll();
}
bool SkGPipeCanvas::needOpBytes(size_t needed) {
@@ -516,42 +560,84 @@
if (paint) {
this->writePaint(*paint);
}
- SkOrderedWriteBuffer writeBuffer(0);
- // FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
- // so that we can store a pointer to a bitmap's pixels during flattening.
- writeBuffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
- bm.flatten(writeBuffer);
- int size = writeBuffer.size();
+
+ int bitmapIndex = this->flattenToIndex(bm);
- if (this->needOpBytes(sizeof(uint32_t) + size + sizeof(SkScalar)*2)
- + sizeof(bool)) {
- // Record the act of drawing the bitmap
- this->writeOp(kDrawBitmap_DrawOp);
- fWriter.writeInt(size);
- void* ptr = (void*) fWriter.reserve(size);
- writeBuffer.flatten(ptr);
+ if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool))) {
+ this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
fWriter.writeBool(paint != NULL);
fWriter.writeScalar(left);
fWriter.writeScalar(top);
}
}
-void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
- const SkRect& dst, const SkPaint*) {
- UNIMPLEMENTED
+void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
+ const SkRect& dst, const SkPaint* paint) {
+ NOTIFY_SETUP(this);
+ if (paint) {
+ this->writePaint(*paint);
+ }
+
+ int bitmapIndex = this->flattenToIndex(bm);
+
+ size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
+ bool hasSrc = src != NULL;
+ if (hasSrc) {
+ opBytesNeeded += sizeof(int32_t) * 4;
+ }
+ if (this->needOpBytes(opBytesNeeded)) {
+ this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
+ fWriter.writeBool(paint != NULL);
+ fWriter.writeBool(hasSrc);
+ if (hasSrc) {
+ fWriter.write32(src->fLeft);
+ fWriter.write32(src->fTop);
+ fWriter.write32(src->fRight);
+ fWriter.write32(src->fBottom);
+ }
+ fWriter.writeRect(dst);
+ }
}
void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
const SkPaint*) {
UNIMPLEMENTED
}
-void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
+
+void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
const SkRect& dst, const SkPaint* paint) {
- UNIMPLEMENTED
+ 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);
+ fWriter.writeBool(paint != NULL);
+ fWriter.write32(center.fLeft);
+ fWriter.write32(center.fTop);
+ fWriter.write32(center.fRight);
+ fWriter.write32(center.fBottom);
+ fWriter.writeRect(dst);
+ }
}
-void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
- const SkPaint*) {
- UNIMPLEMENTED
+
+void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
+ const SkPaint* paint) {
+ 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);
+ fWriter.writeBool(paint != NULL);
+ fWriter.write32(left);
+ fWriter.write32(top);
+ }
}
void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,