diff --git a/include/utils/SkDeferredCanvas.h b/include/utils/SkDeferredCanvas.h index 5f781f8859..a1ac295185 100644 --- a/include/utils/SkDeferredCanvas.h +++ b/include/utils/SkDeferredCanvas.h @@ -164,8 +164,12 @@ public: virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, const SkPaint* paint) SK_OVERRIDE; virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, - const SkRect& dst, const SkPaint* paint) - SK_OVERRIDE; + const SkRect& dst, const SkPaint* paint) SK_OVERRIDE; + virtual void drawImage(const SkImage* image, SkScalar left, SkScalar top, + const SkPaint* paint) SK_OVERRIDE; + virtual void drawImageRect(const SkImage* image, const SkRect* src, + const SkRect& dst, + const SkPaint* paint) SK_OVERRIDE; virtual void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) SK_OVERRIDE; virtual void drawVertices(VertexMode vmode, int vertexCount, @@ -197,7 +201,7 @@ protected: virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) SK_OVERRIDE; - + virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE; diff --git a/src/pipe/SkGPipePriv.h b/src/pipe/SkGPipePriv.h index 121512d42a..8d2a2af294 100644 --- a/src/pipe/SkGPipePriv.h +++ b/src/pipe/SkGPipePriv.h @@ -46,6 +46,8 @@ enum DrawOps { kDrawClear_DrawOp, kDrawData_DrawOp, kDrawDRRect_DrawOp, + kDrawImage_DrawOp, + kDrawImageRect_DrawOp, kDrawOval_DrawOp, kDrawPaint_DrawOp, kDrawPatch_DrawOp, @@ -156,6 +158,10 @@ enum { // converted into and out of this flag to save space kDrawBitmap_Bleed_DrawOpFlag = 1 << 2, }; +enum { + kDrawImage_HasPaint_DrawOpFlag = 1 << 0, + kDrawImage_HasSrcRect_DrawOpFlag = 1 << 1, +}; enum { kClip_HasAntiAlias_DrawOpFlag = 1 << 0, }; diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 8cb0e34d0a..222dc99e1a 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -408,11 +408,11 @@ static void drawDRRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, static void drawPatch_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, SkGPipeState* state) { - + unsigned flags = DrawOp_unpackFlags(op32); - + const SkPoint* cubics = skip(reader, SkPatchUtils::kNumCtrlPts); - + const SkColor* colors = NULL; if (flags & kDrawVertices_HasColors_DrawOpFlag) { colors = skip(reader, SkPatchUtils::kNumCorners); @@ -651,6 +651,40 @@ static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, } } +static void drawImage_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, + SkGPipeState* state) { + bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpFlag); + // Balances call to ref() in SkGPipeWrite + SkAutoTUnref image (static_cast(reader->readPtr())); + + SkScalar left = reader->readScalar(); + SkScalar top = reader->readScalar(); + + if (state->shouldDraw()) { + canvas->drawImage(image, left, top, hasPaint ? &state->paint() : NULL); + } +} + +static void drawImageRect_rp(SkCanvas* canvas, SkReader32* reader, + uint32_t op32, SkGPipeState* state) { + unsigned flags = DrawOp_unpackFlags(op32); + bool hasPaint = SkToBool(flags & kDrawBitmap_HasPaint_DrawOpFlag); + bool hasSrc = SkToBool(flags & kDrawBitmap_HasSrcRect_DrawOpFlag); + // Balances call to ref() in SkGPipeWrite + SkAutoTUnref image (static_cast(reader->readPtr())); + + const SkRect* src; + if (hasSrc) { + src = skip(reader); + } else { + src = NULL; + } + const SkRect* dst = skip(reader); + if (state->shouldDraw()) { + canvas->drawImageRect(image, src, *dst, hasPaint ? &state->paint() : NULL); + } +} + /////////////////////////////////////////////////////////////////////////////// static void drawData_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32, @@ -831,6 +865,8 @@ static const ReadProc gReadTable[] = { drawClear_rp, drawData_rp, drawDRRect_rp, + drawImage_rp, + drawImageRect_rp, drawOval_rp, drawPaint_rp, drawPatch_rp, diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index 41b0234480..a1e7dc2872 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -250,6 +250,11 @@ public: const SkPaint*) SK_OVERRIDE; virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE; + virtual void drawImage(const SkImage* image, SkScalar left, SkScalar top, + const SkPaint* paint) SK_OVERRIDE; + virtual void drawImageRect(const SkImage* image, const SkRect* src, + const SkRect& dst, + const SkPaint* paint) SK_OVERRIDE; virtual void drawSprite(const SkBitmap&, int left, int top, const SkPaint*) SK_OVERRIDE; virtual void drawVertices(VertexMode, int vertexCount, @@ -359,6 +364,9 @@ private: bool commonDrawBitmap(const SkBitmap& bm, DrawOps op, unsigned flags, size_t opBytesNeeded, const SkPaint* paint); + bool commonDrawImage(const SkImage* image, DrawOps op, unsigned flags, + size_t opBytesNeeded, const SkPaint* paint); + SkPaint fPaint; void writePaint(const SkPaint&); @@ -471,6 +479,7 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, } } fFlattenableHeap.setBitmapStorage(fBitmapHeap); + this->doNotify(); } @@ -799,6 +808,79 @@ bool SkGPipeCanvas::commonDrawBitmap(const SkBitmap& bm, DrawOps op, return false; } +bool SkGPipeCanvas::commonDrawImage(const SkImage* image, DrawOps op, + unsigned flags, + size_t opBytesNeeded, + const SkPaint* paint) { + if (fDone) { + return false; + } + + if (paint != NULL) { + flags |= kDrawBitmap_HasPaint_DrawOpFlag; + this->writePaint(*paint); + } + + opBytesNeeded += sizeof (SkImage*); + + if (this->needOpBytes(opBytesNeeded)) { + this->writeOp(op, flags, 0); + + image->ref(); // The SkGPipeReader will have to call unref() + fWriter.writePtr(static_cast(const_cast(image))); + + return true; + } + return false; +} + +void SkGPipeCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top, + const SkPaint* paint) { + if (is_cross_process(fFlags)){ + // If the SkGPipe is cross-process, we will have to flatten the data in the SkImage, so + // fallback to the default implementation in SkCanvas (which calls SkImage::draw()) + // https://code.google.com//p/skia/issues/detail?id=2985 + this->INHERITED::drawImage(image, left, top, paint); + } else { + NOTIFY_SETUP(this); + size_t opBytesNeeded = sizeof(SkScalar) * 2; + + if (this->commonDrawImage(image, kDrawImage_DrawOp, 0, opBytesNeeded, paint)) { + fWriter.writeScalar(left); + fWriter.writeScalar(top); + } + } +} + +void SkGPipeCanvas::drawImageRect(const SkImage* image, const SkRect* src, + const SkRect& dst, + const SkPaint* paint) { + if (is_cross_process(fFlags)){ + // If the SkGPipe is cross-process, we will have to flatten the data in the SkImage, so + // fallback to the default implementation in SkCanvas (which calls SkImage::drawRect()) + // https://code.google.com//p/skia/issues/detail?id=2985 + this->INHERITED::drawImageRect(image, src, dst, paint); + } else { + NOTIFY_SETUP(this); + size_t opBytesNeeded = sizeof (SkRect); + bool hasSrc = src != NULL; + unsigned flags; + if (hasSrc) { + flags = kDrawImage_HasSrcRect_DrawOpFlag; + opBytesNeeded += sizeof (SkRect); + } else { + flags = 0; + } + + if (this->commonDrawImage(image, kDrawImageRect_DrawOp, flags, opBytesNeeded, paint)) { + if (hasSrc) { + fWriter.writeRect(*src); + } + fWriter.writeRect(dst); + } + } +} + void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top, const SkPaint* paint) { NOTIFY_SETUP(this); @@ -1090,7 +1172,7 @@ void SkGPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { NOTIFY_SETUP(this); - + size_t size = SkPatchUtils::kNumCtrlPts * sizeof(SkPoint); unsigned flags = 0; if (colors) { @@ -1108,21 +1190,21 @@ void SkGPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4 size += sizeof(int32_t); } } - + this->writePaint(paint); if (this->needOpBytes(size)) { this->writeOp(kDrawPatch_DrawOp, flags, 0); - + fWriter.write(cubics, SkPatchUtils::kNumCtrlPts * sizeof(SkPoint)); - + if (colors) { fWriter.write(colors, SkPatchUtils::kNumCorners * sizeof(SkColor)); } - + if (texCoords) { fWriter.write(texCoords, SkPatchUtils::kNumCorners * sizeof(SkPoint)); } - + if (flags & kDrawVertices_HasXfermode_DrawOpFlag) { SkXfermode::Mode mode = SkXfermode::kModulate_Mode; SkAssertResult(xmode->asMode(&mode)); diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index 06f7bb089a..c20aa62b00 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -866,6 +866,43 @@ void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap, this->recordedDrawCommand(); } +void SkDeferredCanvas::drawImage(const SkImage* image, SkScalar left, SkScalar top, + const SkPaint* paint) { + SkRect imageRect = SkRect::MakeXYWH(left, top, + SkIntToScalar(image->width()), SkIntToScalar(image->height())); + bool isImageOpaque = image->isOpaque(); + SkPaintBitmapOpacity pct = isImageOpaque + ? kOpaque_SkPaintBitmapOpacity : kUnknown_SkPaintBitmapOpacity; + + if (fDeferredDrawing && + this->isFullFrame(&imageRect, paint) && + (isImageOpaque ||isPaintOpaque(paint, pct))) { + this->getDeferredDevice()->skipPendingCommands(); + } + + AutoImmediateDrawIfNeeded autoDraw(*this, paint); + this->drawingCanvas()->drawImage(image, left, top, paint); + this->recordedDrawCommand(); +} + +void SkDeferredCanvas::drawImageRect(const SkImage* image, const SkRect* src, + const SkRect& dst, + const SkPaint* paint) { + bool isImageOpaque = image->isOpaque(); + SkPaintBitmapOpacity pct = isImageOpaque + ? kOpaque_SkPaintBitmapOpacity : kUnknown_SkPaintBitmapOpacity; + + if (fDeferredDrawing && + this->isFullFrame(&dst, paint) && + (isImageOpaque || isPaintOpaque(paint, pct))) { + this->getDeferredDevice()->skipPendingCommands(); + } + + AutoImmediateDrawIfNeeded autoDraw(*this, paint); + this->drawingCanvas()->drawImageRect(image, src, dst, paint); + this->recordedDrawCommand(); +} + void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { SkRect bitmapRect = SkRect::MakeXYWH(