Index: src/utils/SkDeferredCanvas.cpp |
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp |
index d5cf97bd04df38287faa639f08bd9f7aa4a7c245..7d0a8e8593b5e51a2a4421318751cd7c2f9740b0 100644 |
--- a/src/utils/SkDeferredCanvas.cpp |
+++ b/src/utils/SkDeferredCanvas.cpp |
@@ -32,12 +32,31 @@ enum PlaybackMode { |
kSilent_PlaybackMode, |
}; |
-static bool should_draw_immediately(const SkBitmap* bitmap, const SkPaint* paint, |
- size_t bitmapSizeThreshold) { |
+static uint64_t image_area(const SkImage* image) { |
+ return sk_64_mul(image->width(), image->height()); |
+} |
+ |
+// HACK -- see crbug.com/485243 |
+// |
+// Work around case where Blink gives us an image, but will "mutate" it (by changing its contents |
+// directly using webgl). Until that is fixed at the call-site, we treat gpu-backed-images as |
+// mutable for now (at least for the purposes of deferred canvas) |
+// |
+static bool should_draw_gpu_image_immediately(const SkImage* image) { |
+ return image->getTexture() != NULL; |
+} |
+ |
+static bool should_draw_immediately(const SkBitmap* bitmap, const SkImage* image, |
+ const SkPaint* paint, size_t bitmapSizeThreshold) { |
if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) || |
- (bitmap->getSize() > bitmapSizeThreshold))) { |
+ (bitmap->getSize() > bitmapSizeThreshold))) { |
return true; |
} |
+ if (image) { |
+ if (should_draw_gpu_image_immediately(image) || image_area(image) > bitmapSizeThreshold) { |
+ return true; |
+ } |
+ } |
if (paint) { |
SkShader* shader = paint->getShader(); |
// Here we detect the case where the shader is an SkBitmapProcShader |
@@ -202,6 +221,11 @@ protected: |
void drawSprite(const SkDraw&, const SkBitmap& bitmap, |
int x, int y, const SkPaint& paint) override |
{SkASSERT(0);} |
+ void drawImage(const SkDraw&, const SkImage*, SkScalar, SkScalar, const SkPaint&) override |
+ {SkASSERT(0);} |
+ void drawImageRect(const SkDraw&, const SkImage*, const SkRect*, const SkRect&, |
+ const SkPaint&) override |
+ {SkASSERT(0);} |
void drawText(const SkDraw&, const void* text, size_t len, |
SkScalar x, SkScalar y, const SkPaint& paint) override |
{SkASSERT(0);} |
@@ -481,11 +505,15 @@ class AutoImmediateDrawIfNeeded { |
public: |
AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap, |
const SkPaint* paint) { |
- this->init(canvas, bitmap, paint); |
+ this->init(canvas, bitmap, NULL, paint); |
+ } |
+ AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkImage* image, |
+ const SkPaint* paint) { |
+ this->init(canvas, NULL, image, paint); |
} |
AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) { |
- this->init(canvas, NULL, paint); |
+ this->init(canvas, NULL, NULL, paint); |
} |
~AutoImmediateDrawIfNeeded() { |
@@ -494,9 +522,10 @@ public: |
} |
} |
private: |
- void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint) { |
+ void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkImage* image, |
+ const SkPaint* paint) { |
if (canvas.isDeferredDrawing() && |
- should_draw_immediately(bitmap, paint, canvas.getBitmapSizeThreshold())) { |
+ should_draw_immediately(bitmap, image, paint, canvas.getBitmapSizeThreshold())) { |
canvas.setDeferredDrawing(false); |
fCanvas = &canvas; |
} else { |
@@ -836,6 +865,34 @@ void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* sr |
this->recordedDrawCommand(); |
} |
+ |
+void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, |
+ const SkPaint* paint) { |
+ SkRect bounds = SkRect::MakeXYWH(x, y, |
+ SkIntToScalar(image->width()), SkIntToScalar(image->height())); |
+ if (fDeferredDrawing && |
+ this->isFullFrame(&bounds, paint) && |
+ isPaintOpaque(paint, image)) { |
+ this->getDeferredDevice()->skipPendingCommands(); |
+ } |
+ |
+ AutoImmediateDrawIfNeeded autoDraw(*this, image, paint); |
+ this->drawingCanvas()->drawImage(image, x, y, paint); |
+ this->recordedDrawCommand(); |
+} |
+void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, |
+ const SkPaint* paint) { |
+ if (fDeferredDrawing && |
+ this->isFullFrame(&dst, paint) && |
+ isPaintOpaque(paint, image)) { |
+ this->getDeferredDevice()->skipPendingCommands(); |
+ } |
+ |
+ AutoImmediateDrawIfNeeded autoDraw(*this, image, paint); |
+ this->drawingCanvas()->drawImageRect(image, src, dst, paint); |
+ this->recordedDrawCommand(); |
+} |
+ |
void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap, |
const SkIRect& center, const SkRect& dst, |
const SkPaint* paint) { |