Updates for SkGPipe.
authorscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 2 May 2012 19:09:40 +0000 (19:09 +0000)
committerscroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 2 May 2012 19:09:40 +0000 (19:09 +0000)
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

src/pipe/SkGPipePriv.h
src/pipe/SkGPipeRead.cpp
src/pipe/SkGPipeWrite.cpp

index 2baf75aaccde59e192821f2b047ff9881c0e6968..5b6bcc0ed4e262882698971f25697c202ffaea10 100644 (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,
index 7642f356895431bcfc1d2f6ba0ae672a4ab61f6a..cc7361f046c5b7c691ff89bdf1d4866a0c9aebe3 100644 (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;
index 9802b124c2ee6dbd38d2ac79b7f7822d51dafeea..b06d40e8d188d8b1ec629d83fd81e871f1571cfe 100644 (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();
+
+    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,