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
This commit is contained in:
scroggo@google.com 2012-05-02 19:09:40 +00:00
parent 9c36a76102
commit 16d1d0b39a
3 changed files with 174 additions and 33 deletions

View File

@ -23,6 +23,7 @@ enum PaintFlats {
kPathEffect_PaintFlat,
kRasterizer_PaintFlat,
kShader_PaintFlat,
kImageFilter_PaintFlat,
kXfermode_PaintFlat,
kLast_PaintFlat = kXfermode_PaintFlat
@ -39,6 +40,7 @@ enum DrawOps {
kConcat_DrawOp,
kDrawBitmap_DrawOp,
kDrawBitmapMatrix_DrawOp,
kDrawBitmapNine_DrawOp,
kDrawBitmapRect_DrawOp,
kDrawClear_DrawOp,
kDrawData_DrawOp,
@ -66,6 +68,7 @@ enum DrawOps {
kDef_Typeface_DrawOp,
kDef_Flattenable_DrawOp,
kDef_Bitmap_DrawOp,
// these are signals to playback, not drawing verbs
kDone_DrawOp,

View File

@ -46,6 +46,9 @@ static void set_paintflat(SkPaint* paint, SkFlattenable* obj, unsigned paintFlat
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 @@ public:
*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 @@ private:
SkTDArray<SkFlattenable*> fFlatArray;
SkTDArray<SkTypeface*> fTypefaces;
SkTDArray<SkFlattenable::Factory> fFactoryArray;
SkTDArray<SkBitmap*> fBitmaps;
};
///////////////////////////////////////////////////////////////////////////////
@ -329,14 +346,12 @@ static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op3
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 @@ static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t o
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 @@ static void def_PaintFlat_rp(SkCanvas*, SkReader32*, uint32_t op32,
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 @@ static const ReadProc gReadTable[] = {
concat_rp,
drawBitmap_rp,
drawBitmapMatrix_rp,
drawBitmapNine_rp,
drawBitmapRect_rp,
drawClear_rp,
drawData_rp,
@ -477,6 +526,7 @@ static const ReadProc gReadTable[] = {
paintOp_rp,
def_Typeface_rp,
def_PaintFlat_rp,
def_Bitmap_rp,
done_rp
};
@ -488,6 +538,7 @@ SkGPipeState::SkGPipeState() {}
SkGPipeState::~SkGPipeState() {
fTypefaces.safeUnrefAll();
fFlatArray.safeUnrefAll();
fBitmaps.deleteAll();
}
///////////////////////////////////////////////////////////////////////////////
@ -541,7 +592,8 @@ SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length,
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;

View File

@ -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 @@ static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
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 @@ private:
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 @@ private:
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 @@ private:
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 @@ SkGPipeCanvas::~SkGPipeCanvas() {
this->finish();
fFlatArray.freeAll();
fBitmapArray.freeAll();
}
bool SkGPipeCanvas::needOpBytes(size_t needed) {
@ -516,42 +560,84 @@ void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
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();
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);
int bitmapIndex = this->flattenToIndex(bm);
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,