1
2 /*
3 * Copyright 2013 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "SkDeferredCanvas.h"
10
11 #include "SkBitmapDevice.h"
12 #include "SkChunkAlloc.h"
13 #include "SkColorFilter.h"
14 #include "SkDrawFilter.h"
15 #include "SkGPipe.h"
16 #include "SkPaint.h"
17 #include "SkPaintPriv.h"
18 #include "SkRRect.h"
19 #include "SkShader.h"
20 #include "SkSurface.h"
21
22 enum {
23 // Deferred canvas will auto-flush when recording reaches this limit
24 kDefaultMaxRecordingStorageBytes = 64*1024*1024,
25 kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature
26
27 kNoSaveLayerIndex = -1,
28 };
29
30 enum PlaybackMode {
31 kNormal_PlaybackMode,
32 kSilent_PlaybackMode,
33 };
34
image_area(const SkImage * image)35 static uint64_t image_area(const SkImage* image) {
36 return sk_64_mul(image->width(), image->height());
37 }
38
39 // HACK -- see crbug.com/485243
40 //
41 // Work around case where Blink gives us an image, but will "mutate" it (by changing its contents
42 // directly using webgl). Until that is fixed at the call-site, we treat gpu-backed-images as
43 // mutable for now (at least for the purposes of deferred canvas)
44 //
should_draw_gpu_image_immediately(const SkImage * image)45 static bool should_draw_gpu_image_immediately(const SkImage* image) {
46 return image->getTexture() != NULL;
47 }
48
should_draw_immediately(const SkBitmap * bitmap,const SkImage * image,const SkPaint * paint,size_t bitmapSizeThreshold)49 static bool should_draw_immediately(const SkBitmap* bitmap, const SkImage* image,
50 const SkPaint* paint, size_t bitmapSizeThreshold) {
51 if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) ||
52 (bitmap->getSize() > bitmapSizeThreshold))) {
53 return true;
54 }
55 if (image) {
56 if (should_draw_gpu_image_immediately(image) || image_area(image) > bitmapSizeThreshold) {
57 return true;
58 }
59 }
60 if (paint) {
61 SkShader* shader = paint->getShader();
62 // Here we detect the case where the shader is an SkBitmapProcShader
63 // with a gpu texture attached. Checking this without RTTI
64 // requires making the assumption that only gradient shaders
65 // and SkBitmapProcShader implement asABitmap(). The following
66 // code may need to be revised if that assumption is ever broken.
67 if (shader && !shader->asAGradient(NULL)) {
68 SkBitmap bm;
69 if (shader->asABitmap(&bm, NULL, NULL) &&
70 bm.getTexture()) {
71 return true;
72 }
73 }
74 }
75 return false;
76 }
77
78 //-----------------------------------------------------------------------------
79 // DeferredPipeController
80 //-----------------------------------------------------------------------------
81
82 class DeferredPipeController : public SkGPipeController {
83 public:
84 DeferredPipeController();
85 void setPlaybackCanvas(SkCanvas*);
86 virtual ~DeferredPipeController();
87 void* requestBlock(size_t minRequest, size_t* actual) override;
88 void notifyWritten(size_t bytes) override;
89 void playback(bool silent);
hasPendingCommands() const90 bool hasPendingCommands() const { return fAllocator.totalUsed() != 0; }
storageAllocatedForRecording() const91 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
92 private:
93 enum {
94 kMinBlockSize = 4096
95 };
96 struct PipeBlock {
PipeBlockDeferredPipeController::PipeBlock97 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
98 void* fBlock;
99 size_t fSize;
100 };
101 void* fBlock;
102 size_t fBytesWritten;
103 SkChunkAlloc fAllocator;
104 SkTDArray<PipeBlock> fBlockList;
105 SkGPipeReader fReader;
106 };
107
DeferredPipeController()108 DeferredPipeController::DeferredPipeController() :
109 fAllocator(kMinBlockSize) {
110 fBlock = NULL;
111 fBytesWritten = 0;
112 }
113
~DeferredPipeController()114 DeferredPipeController::~DeferredPipeController() {
115 fAllocator.reset();
116 }
117
setPlaybackCanvas(SkCanvas * canvas)118 void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
119 fReader.setCanvas(canvas);
120 }
121
requestBlock(size_t minRequest,size_t * actual)122 void* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) {
123 if (fBlock) {
124 // Save the previous block for later
125 PipeBlock previousBloc(fBlock, fBytesWritten);
126 fBlockList.push(previousBloc);
127 }
128 size_t blockSize = SkTMax<size_t>(minRequest, kMinBlockSize);
129 fBlock = fAllocator.allocThrow(blockSize);
130 fBytesWritten = 0;
131 *actual = blockSize;
132 return fBlock;
133 }
134
notifyWritten(size_t bytes)135 void DeferredPipeController::notifyWritten(size_t bytes) {
136 fBytesWritten += bytes;
137 }
138
playback(bool silent)139 void DeferredPipeController::playback(bool silent) {
140 uint32_t flags = silent ? SkGPipeReader::kSilent_PlaybackFlag : 0;
141 for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
142 fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize,
143 flags);
144 }
145 fBlockList.reset();
146
147 if (fBlock) {
148 fReader.playback(fBlock, fBytesWritten, flags);
149 fBlock = NULL;
150 }
151
152 // Release all allocated blocks
153 fAllocator.reset();
154 }
155
156 //-----------------------------------------------------------------------------
157 // SkDeferredDevice
158 //-----------------------------------------------------------------------------
159 class SkDeferredDevice : public SkBaseDevice {
160 public:
161 explicit SkDeferredDevice(SkSurface* surface);
162 ~SkDeferredDevice();
163
164 void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
165 SkCanvas* recordingCanvas();
immediateCanvas() const166 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
immediateDevice() const167 SkBaseDevice* immediateDevice() const {return fImmediateCanvas->getTopDevice();}
168 SkImage* newImageSnapshot();
169 void setSurface(SkSurface* surface);
170 bool isFreshFrame();
171 bool hasPendingCommands();
172 size_t storageAllocatedForRecording() const;
173 size_t freeMemoryIfPossible(size_t bytesToFree);
174 void flushPendingCommands(PlaybackMode);
175 void skipPendingCommands();
176 void setMaxRecordingStorage(size_t);
177 void recordedDrawCommand();
setIsDrawingToLayer(bool value)178 void setIsDrawingToLayer(bool value) {fIsDrawingToLayer = value;}
179
180 SkImageInfo imageInfo() const override;
181
182 GrRenderTarget* accessRenderTarget() override;
183
184 SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
185
186 SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) override;
187
188 protected:
189 const SkBitmap& onAccessBitmap() override;
190 bool onReadPixels(const SkImageInfo&, void*, size_t, int x, int y) override;
191 bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y) override;
192
193 // None of the following drawing methods should ever get called on the
194 // deferred device
drawPaint(const SkDraw &,const SkPaint & paint)195 void drawPaint(const SkDraw&, const SkPaint& paint) override
196 {SkASSERT(0);}
drawPoints(const SkDraw &,SkCanvas::PointMode mode,size_t count,const SkPoint[],const SkPaint & paint)197 void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
198 size_t count, const SkPoint[],
199 const SkPaint& paint) override
200 {SkASSERT(0);}
drawRect(const SkDraw &,const SkRect & r,const SkPaint & paint)201 void drawRect(const SkDraw&, const SkRect& r,
202 const SkPaint& paint) override
203 {SkASSERT(0);}
drawOval(const SkDraw &,const SkRect &,const SkPaint &)204 void drawOval(const SkDraw&, const SkRect&, const SkPaint&) override
205 {SkASSERT(0);}
drawRRect(const SkDraw &,const SkRRect & rr,const SkPaint & paint)206 void drawRRect(const SkDraw&, const SkRRect& rr,
207 const SkPaint& paint) override
208 {SkASSERT(0);}
drawPath(const SkDraw &,const SkPath & path,const SkPaint & paint,const SkMatrix * prePathMatrix=NULL,bool pathIsMutable=false)209 void drawPath(const SkDraw&, const SkPath& path,
210 const SkPaint& paint,
211 const SkMatrix* prePathMatrix = NULL,
212 bool pathIsMutable = false) override
213 {SkASSERT(0);}
drawBitmap(const SkDraw &,const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint & paint)214 void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
215 const SkMatrix& matrix, const SkPaint& paint) override
216 {SkASSERT(0);}
drawBitmapRect(const SkDraw &,const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::DrawBitmapRectFlags)217 void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect*,
218 const SkRect&, const SkPaint&,
219 SkCanvas::DrawBitmapRectFlags) override
220 {SkASSERT(0);}
drawSprite(const SkDraw &,const SkBitmap & bitmap,int x,int y,const SkPaint & paint)221 void drawSprite(const SkDraw&, const SkBitmap& bitmap,
222 int x, int y, const SkPaint& paint) override
223 {SkASSERT(0);}
drawImage(const SkDraw &,const SkImage *,SkScalar,SkScalar,const SkPaint &)224 void drawImage(const SkDraw&, const SkImage*, SkScalar, SkScalar, const SkPaint&) override
225 {SkASSERT(0);}
drawImageRect(const SkDraw &,const SkImage *,const SkRect *,const SkRect &,const SkPaint &)226 void drawImageRect(const SkDraw&, const SkImage*, const SkRect*, const SkRect&,
227 const SkPaint&) override
228 {SkASSERT(0);}
drawText(const SkDraw &,const void * text,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)229 void drawText(const SkDraw&, const void* text, size_t len,
230 SkScalar x, SkScalar y, const SkPaint& paint) override
231 {SkASSERT(0);}
drawPosText(const SkDraw &,const void * text,size_t len,const SkScalar pos[],int scalarsPerPos,const SkPoint & offset,const SkPaint & paint)232 void drawPosText(const SkDraw&, const void* text, size_t len,
233 const SkScalar pos[], int scalarsPerPos,
234 const SkPoint& offset, const SkPaint& paint) override
235 {SkASSERT(0);}
drawTextOnPath(const SkDraw &,const void * text,size_t len,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)236 void drawTextOnPath(const SkDraw&, const void* text,
237 size_t len, const SkPath& path,
238 const SkMatrix* matrix,
239 const SkPaint& paint) override
240 {SkASSERT(0);}
drawVertices(const SkDraw &,SkCanvas::VertexMode,int vertexCount,const SkPoint verts[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)241 void drawVertices(const SkDraw&, SkCanvas::VertexMode,
242 int vertexCount, const SkPoint verts[],
243 const SkPoint texs[], const SkColor colors[],
244 SkXfermode* xmode, const uint16_t indices[],
245 int indexCount, const SkPaint& paint) override
246 {SkASSERT(0);}
drawPatch(const SkDraw &,const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)247 void drawPatch(const SkDraw&, const SkPoint cubics[12], const SkColor colors[4],
248 const SkPoint texCoords[4], SkXfermode* xmode,
249 const SkPaint& paint) override
250 {SkASSERT(0);}
drawDevice(const SkDraw &,SkBaseDevice *,int x,int y,const SkPaint &)251 void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
252 const SkPaint&) override
253 {SkASSERT(0);}
254
lockPixels()255 void lockPixels() override {}
unlockPixels()256 void unlockPixels() override {}
257
canHandleImageFilter(const SkImageFilter *)258 bool canHandleImageFilter(const SkImageFilter*) override {
259 return false;
260 }
filterImage(const SkImageFilter *,const SkBitmap &,const SkImageFilter::Context &,SkBitmap *,SkIPoint *)261 bool filterImage(const SkImageFilter*, const SkBitmap&,
262 const SkImageFilter::Context&, SkBitmap*, SkIPoint*) override {
263 return false;
264 }
265
266 private:
267 void flush() override;
replaceBitmapBackendForRasterSurface(const SkBitmap &)268 void replaceBitmapBackendForRasterSurface(const SkBitmap&) override {}
269
270 void beginRecording();
271 void init();
272 void aboutToDraw();
273 void prepareForImmediatePixelWrite();
274
275 DeferredPipeController fPipeController;
276 SkGPipeWriter fPipeWriter;
277 SkCanvas* fImmediateCanvas;
278 SkCanvas* fRecordingCanvas;
279 SkSurface* fSurface;
280 SkDeferredCanvas::NotificationClient* fNotificationClient;
281 bool fFreshFrame;
282 bool fCanDiscardCanvasContents;
283 bool fIsDrawingToLayer;
284 size_t fMaxRecordingStorageBytes;
285 size_t fPreviousStorageAllocated;
286 };
287
SkDeferredDevice(SkSurface * surface)288 SkDeferredDevice::SkDeferredDevice(SkSurface* surface) {
289 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
290 fNotificationClient = NULL;
291 fImmediateCanvas = NULL;
292 fSurface = NULL;
293 this->setSurface(surface);
294 this->init();
295 }
296
setSurface(SkSurface * surface)297 void SkDeferredDevice::setSurface(SkSurface* surface) {
298 SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
299 SkRefCnt_SafeAssign(fSurface, surface);
300 fPipeController.setPlaybackCanvas(fImmediateCanvas);
301 }
302
init()303 void SkDeferredDevice::init() {
304 fRecordingCanvas = NULL;
305 fFreshFrame = true;
306 fIsDrawingToLayer = false;
307 fCanDiscardCanvasContents = false;
308 fPreviousStorageAllocated = 0;
309 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
310 fNotificationClient = NULL;
311 this->beginRecording();
312 }
313
~SkDeferredDevice()314 SkDeferredDevice::~SkDeferredDevice() {
315 this->flushPendingCommands(kSilent_PlaybackMode);
316 SkSafeUnref(fImmediateCanvas);
317 SkSafeUnref(fSurface);
318 }
319
setMaxRecordingStorage(size_t maxStorage)320 void SkDeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
321 fMaxRecordingStorageBytes = maxStorage;
322 this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
323 }
324
beginRecording()325 void SkDeferredDevice::beginRecording() {
326 SkASSERT(NULL == fRecordingCanvas);
327 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
328 immediateDevice()->width(), immediateDevice()->height());
329 }
330
setNotificationClient(SkDeferredCanvas::NotificationClient * notificationClient)331 void SkDeferredDevice::setNotificationClient(
332 SkDeferredCanvas::NotificationClient* notificationClient) {
333 fNotificationClient = notificationClient;
334 }
335
skipPendingCommands()336 void SkDeferredDevice::skipPendingCommands() {
337 if (!fIsDrawingToLayer) {
338 fCanDiscardCanvasContents = true;
339 if (fPipeController.hasPendingCommands()) {
340 fFreshFrame = true;
341 flushPendingCommands(kSilent_PlaybackMode);
342 }
343 }
344 }
345
isFreshFrame()346 bool SkDeferredDevice::isFreshFrame() {
347 bool ret = fFreshFrame;
348 fFreshFrame = false;
349 return ret;
350 }
351
hasPendingCommands()352 bool SkDeferredDevice::hasPendingCommands() {
353 return fPipeController.hasPendingCommands();
354 }
355
aboutToDraw()356 void SkDeferredDevice::aboutToDraw()
357 {
358 if (fNotificationClient) {
359 fNotificationClient->prepareForDraw();
360 }
361 if (fCanDiscardCanvasContents) {
362 if (fSurface) {
363 fSurface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
364 }
365 fCanDiscardCanvasContents = false;
366 }
367 }
368
flushPendingCommands(PlaybackMode playbackMode)369 void SkDeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
370 if (!fPipeController.hasPendingCommands()) {
371 return;
372 }
373 if (playbackMode == kNormal_PlaybackMode) {
374 aboutToDraw();
375 }
376 fPipeWriter.flushRecording(true);
377 fPipeController.playback(kSilent_PlaybackMode == playbackMode);
378 if (fNotificationClient) {
379 if (playbackMode == kSilent_PlaybackMode) {
380 fNotificationClient->skippedPendingDrawCommands();
381 } else {
382 fNotificationClient->flushedDrawCommands();
383 }
384 }
385
386 fPreviousStorageAllocated = storageAllocatedForRecording();
387 }
388
flush()389 void SkDeferredDevice::flush() {
390 this->flushPendingCommands(kNormal_PlaybackMode);
391 fImmediateCanvas->flush();
392 }
393
freeMemoryIfPossible(size_t bytesToFree)394 size_t SkDeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
395 size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
396 fPreviousStorageAllocated = storageAllocatedForRecording();
397 return val;
398 }
399
storageAllocatedForRecording() const400 size_t SkDeferredDevice::storageAllocatedForRecording() const {
401 return (fPipeController.storageAllocatedForRecording()
402 + fPipeWriter.storageAllocatedForRecording());
403 }
404
recordedDrawCommand()405 void SkDeferredDevice::recordedDrawCommand() {
406 size_t storageAllocated = this->storageAllocatedForRecording();
407
408 if (storageAllocated > fMaxRecordingStorageBytes) {
409 // First, attempt to reduce cache without flushing
410 size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
411 if (this->freeMemoryIfPossible(tryFree) < tryFree) {
412 // Flush is necessary to free more space.
413 this->flushPendingCommands(kNormal_PlaybackMode);
414 // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
415 // which could cause a high flushing frequency.
416 this->freeMemoryIfPossible(~0U);
417 }
418 storageAllocated = this->storageAllocatedForRecording();
419 }
420
421 if (fNotificationClient &&
422 storageAllocated != fPreviousStorageAllocated) {
423 fPreviousStorageAllocated = storageAllocated;
424 fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated);
425 }
426 }
427
recordingCanvas()428 SkCanvas* SkDeferredDevice::recordingCanvas() {
429 return fRecordingCanvas;
430 }
431
newImageSnapshot()432 SkImage* SkDeferredDevice::newImageSnapshot() {
433 this->flush();
434 return fSurface ? fSurface->newImageSnapshot() : NULL;
435 }
436
imageInfo() const437 SkImageInfo SkDeferredDevice::imageInfo() const {
438 return immediateDevice()->imageInfo();
439 }
440
accessRenderTarget()441 GrRenderTarget* SkDeferredDevice::accessRenderTarget() {
442 this->flushPendingCommands(kNormal_PlaybackMode);
443 return immediateDevice()->accessRenderTarget();
444 }
445
prepareForImmediatePixelWrite()446 void SkDeferredDevice::prepareForImmediatePixelWrite() {
447 // The purpose of the following code is to make sure commands are flushed, that
448 // aboutToDraw() is called and that notifyContentWillChange is called, without
449 // calling anything redundantly.
450 if (fPipeController.hasPendingCommands()) {
451 this->flushPendingCommands(kNormal_PlaybackMode);
452 } else {
453 bool mustNotifyDirectly = !fCanDiscardCanvasContents;
454 this->aboutToDraw();
455 if (mustNotifyDirectly) {
456 fSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
457 }
458 }
459
460 fImmediateCanvas->flush();
461 }
462
onWritePixels(const SkImageInfo & info,const void * pixels,size_t rowBytes,int x,int y)463 bool SkDeferredDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes,
464 int x, int y) {
465 SkASSERT(x >= 0 && y >= 0);
466 SkASSERT(x + info.width() <= width());
467 SkASSERT(y + info.height() <= height());
468
469 const SkImageInfo deviceInfo = this->imageInfo();
470 if (info.width() == deviceInfo.width() && info.height() == deviceInfo.height()) {
471 this->skipPendingCommands();
472 } else {
473 this->flushPendingCommands(kNormal_PlaybackMode);
474 }
475
476 this->prepareForImmediatePixelWrite();
477 return immediateDevice()->onWritePixels(info, pixels, rowBytes, x, y);
478 }
479
onAccessBitmap()480 const SkBitmap& SkDeferredDevice::onAccessBitmap() {
481 this->flushPendingCommands(kNormal_PlaybackMode);
482 return immediateDevice()->accessBitmap(false);
483 }
484
onCreateDevice(const CreateInfo & cinfo,const SkPaint * layerPaint)485 SkBaseDevice* SkDeferredDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
486 // Create a compatible non-deferred device.
487 // We do not create a deferred device because we know the new device
488 // will not be used with a deferred canvas (there is no API for that).
489 // And connecting a SkDeferredDevice to non-deferred canvas can result
490 // in unpredictable behavior.
491 return immediateDevice()->onCreateDevice(cinfo, layerPaint);
492 }
493
newSurface(const SkImageInfo & info,const SkSurfaceProps & props)494 SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
495 return this->immediateDevice()->newSurface(info, props);
496 }
497
onReadPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,int x,int y)498 bool SkDeferredDevice::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
499 int x, int y) {
500 this->flushPendingCommands(kNormal_PlaybackMode);
501 return fImmediateCanvas->readPixels(info, pixels, rowBytes, x, y);
502 }
503
504 class AutoImmediateDrawIfNeeded {
505 public:
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkBitmap * bitmap,const SkPaint * paint)506 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
507 const SkPaint* paint) {
508 this->init(canvas, bitmap, NULL, paint);
509 }
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkImage * image,const SkPaint * paint)510 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkImage* image,
511 const SkPaint* paint) {
512 this->init(canvas, NULL, image, paint);
513 }
514
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkPaint * paint)515 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
516 this->init(canvas, NULL, NULL, paint);
517 }
518
~AutoImmediateDrawIfNeeded()519 ~AutoImmediateDrawIfNeeded() {
520 if (fCanvas) {
521 fCanvas->setDeferredDrawing(true);
522 }
523 }
524 private:
init(SkDeferredCanvas & canvas,const SkBitmap * bitmap,const SkImage * image,const SkPaint * paint)525 void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkImage* image,
526 const SkPaint* paint) {
527 if (canvas.isDeferredDrawing() &&
528 should_draw_immediately(bitmap, image, paint, canvas.getBitmapSizeThreshold())) {
529 canvas.setDeferredDrawing(false);
530 fCanvas = &canvas;
531 } else {
532 fCanvas = NULL;
533 }
534 }
535
536 SkDeferredCanvas* fCanvas;
537 };
538
Create(SkSurface * surface)539 SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) {
540 SkAutoTUnref<SkDeferredDevice> deferredDevice(SkNEW_ARGS(SkDeferredDevice, (surface)));
541 return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
542 }
543
SkDeferredCanvas(SkDeferredDevice * device)544 SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device) {
545 this->init();
546 }
547
init()548 void SkDeferredCanvas::init() {
549 fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
550 fDeferredDrawing = true; // On by default
551 fCachedCanvasSize.setEmpty();
552 fCachedCanvasSizeDirty = true;
553 fSaveLevel = 0;
554 fFirstSaveLayerIndex = kNoSaveLayerIndex;
555 }
556
setMaxRecordingStorage(size_t maxStorage)557 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
558 this->validate();
559 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
560 }
561
storageAllocatedForRecording() const562 size_t SkDeferredCanvas::storageAllocatedForRecording() const {
563 return this->getDeferredDevice()->storageAllocatedForRecording();
564 }
565
freeMemoryIfPossible(size_t bytesToFree)566 size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
567 return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
568 }
569
setBitmapSizeThreshold(size_t sizeThreshold)570 void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) {
571 fBitmapSizeThreshold = sizeThreshold;
572 }
573
recordedDrawCommand()574 void SkDeferredCanvas::recordedDrawCommand() {
575 if (fDeferredDrawing) {
576 this->getDeferredDevice()->recordedDrawCommand();
577 }
578 }
579
validate() const580 void SkDeferredCanvas::validate() const {
581 SkASSERT(this->getDevice());
582 }
583
drawingCanvas() const584 SkCanvas* SkDeferredCanvas::drawingCanvas() const {
585 this->validate();
586 return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() :
587 this->getDeferredDevice()->immediateCanvas();
588 }
589
immediateCanvas() const590 SkCanvas* SkDeferredCanvas::immediateCanvas() const {
591 this->validate();
592 return this->getDeferredDevice()->immediateCanvas();
593 }
594
getDeferredDevice() const595 SkDeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
596 return static_cast<SkDeferredDevice*>(this->getDevice());
597 }
598
setDeferredDrawing(bool val)599 void SkDeferredCanvas::setDeferredDrawing(bool val) {
600 this->validate(); // Must set device before calling this method
601 if (val != fDeferredDrawing) {
602 if (fDeferredDrawing) {
603 // Going live.
604 this->getDeferredDevice()->flushPendingCommands(kNormal_PlaybackMode);
605 }
606 fDeferredDrawing = val;
607 }
608 }
609
isDeferredDrawing() const610 bool SkDeferredCanvas::isDeferredDrawing() const {
611 return fDeferredDrawing;
612 }
613
isFreshFrame() const614 bool SkDeferredCanvas::isFreshFrame() const {
615 return this->getDeferredDevice()->isFreshFrame();
616 }
617
getCanvasSize() const618 SkISize SkDeferredCanvas::getCanvasSize() const {
619 if (fCachedCanvasSizeDirty) {
620 fCachedCanvasSize = this->getBaseLayerSize();
621 fCachedCanvasSizeDirty = false;
622 }
623 return fCachedCanvasSize;
624 }
625
hasPendingCommands() const626 bool SkDeferredCanvas::hasPendingCommands() const {
627 return this->getDeferredDevice()->hasPendingCommands();
628 }
629
silentFlush()630 void SkDeferredCanvas::silentFlush() {
631 if (fDeferredDrawing) {
632 this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode);
633 }
634 }
635
~SkDeferredCanvas()636 SkDeferredCanvas::~SkDeferredCanvas() {
637 }
638
setSurface(SkSurface * surface)639 SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) {
640 SkDeferredDevice* deferredDevice = this->getDeferredDevice();
641 SkASSERT(deferredDevice);
642 // By swapping the surface into the existing device, we preserve
643 // all pending commands, which can help to seamlessly recover from
644 // a lost accelerated graphics context.
645 deferredDevice->setSurface(surface);
646 fCachedCanvasSizeDirty = true;
647 return surface;
648 }
649
setNotificationClient(NotificationClient * notificationClient)650 SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
651 NotificationClient* notificationClient) {
652
653 SkDeferredDevice* deferredDevice = this->getDeferredDevice();
654 SkASSERT(deferredDevice);
655 if (deferredDevice) {
656 deferredDevice->setNotificationClient(notificationClient);
657 }
658 return notificationClient;
659 }
660
newImageSnapshot()661 SkImage* SkDeferredCanvas::newImageSnapshot() {
662 SkDeferredDevice* deferredDevice = this->getDeferredDevice();
663 SkASSERT(deferredDevice);
664 return deferredDevice ? deferredDevice->newImageSnapshot() : NULL;
665 }
666
isFullFrame(const SkRect * rect,const SkPaint * paint) const667 bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
668 const SkPaint* paint) const {
669 SkCanvas* canvas = this->drawingCanvas();
670 SkISize canvasSize = this->getCanvasSize();
671 if (rect) {
672 if (!canvas->getTotalMatrix().rectStaysRect()) {
673 return false; // conservative
674 }
675
676 SkRect transformedRect;
677 canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
678
679 if (paint) {
680 SkPaint::Style paintStyle = paint->getStyle();
681 if (!(paintStyle == SkPaint::kFill_Style ||
682 paintStyle == SkPaint::kStrokeAndFill_Style)) {
683 return false;
684 }
685 if (paint->getMaskFilter() || paint->getLooper()
686 || paint->getPathEffect() || paint->getImageFilter()) {
687 return false; // conservative
688 }
689 }
690
691 // The following test holds with AA enabled, and is conservative
692 // by a 0.5 pixel margin with AA disabled
693 if (transformedRect.fLeft > SkIntToScalar(0) ||
694 transformedRect.fTop > SkIntToScalar(0) ||
695 transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
696 transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
697 return false;
698 }
699 }
700
701 return this->getClipStack()->quickContains(SkRect::MakeXYWH(0, 0,
702 SkIntToScalar(canvasSize.fWidth), SkIntToScalar(canvasSize.fHeight)));
703 }
704
willSave()705 void SkDeferredCanvas::willSave() {
706 fSaveLevel++;
707 this->drawingCanvas()->save();
708 this->recordedDrawCommand();
709 this->INHERITED::willSave();
710 }
711
willSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)712 SkCanvas::SaveLayerStrategy SkDeferredCanvas::willSaveLayer(const SkRect* bounds,
713 const SkPaint* paint, SaveFlags flags) {
714 fSaveLevel++;
715 if (fFirstSaveLayerIndex == kNoSaveLayerIndex) {
716 fFirstSaveLayerIndex = fSaveLevel;
717 this->getDeferredDevice()->setIsDrawingToLayer(true);
718 }
719 this->drawingCanvas()->saveLayer(bounds, paint, flags);
720 this->recordedDrawCommand();
721 this->INHERITED::willSaveLayer(bounds, paint, flags);
722 // No need for a full layer.
723 return kNoLayer_SaveLayerStrategy;
724 }
725
willRestore()726 void SkDeferredCanvas::willRestore() {
727 SkASSERT(fFirstSaveLayerIndex == kNoSaveLayerIndex || fFirstSaveLayerIndex <= fSaveLevel);
728 if (fFirstSaveLayerIndex == fSaveLevel) {
729 fFirstSaveLayerIndex = kNoSaveLayerIndex;
730 this->getDeferredDevice()->setIsDrawingToLayer(false);
731 }
732 fSaveLevel--;
733 this->drawingCanvas()->restore();
734 this->recordedDrawCommand();
735 this->INHERITED::willRestore();
736 }
737
didConcat(const SkMatrix & matrix)738 void SkDeferredCanvas::didConcat(const SkMatrix& matrix) {
739 this->drawingCanvas()->concat(matrix);
740 this->recordedDrawCommand();
741 this->INHERITED::didConcat(matrix);
742 }
743
didSetMatrix(const SkMatrix & matrix)744 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
745 this->drawingCanvas()->setMatrix(matrix);
746 this->recordedDrawCommand();
747 this->INHERITED::didSetMatrix(matrix);
748 }
749
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edgeStyle)750 void SkDeferredCanvas::onClipRect(const SkRect& rect,
751 SkRegion::Op op,
752 ClipEdgeStyle edgeStyle) {
753 this->drawingCanvas()->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
754 this->INHERITED::onClipRect(rect, op, edgeStyle);
755 this->recordedDrawCommand();
756 }
757
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edgeStyle)758 void SkDeferredCanvas::onClipRRect(const SkRRect& rrect,
759 SkRegion::Op op,
760 ClipEdgeStyle edgeStyle) {
761 this->drawingCanvas()->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
762 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
763 this->recordedDrawCommand();
764 }
765
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edgeStyle)766 void SkDeferredCanvas::onClipPath(const SkPath& path,
767 SkRegion::Op op,
768 ClipEdgeStyle edgeStyle) {
769 this->drawingCanvas()->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
770 this->INHERITED::onClipPath(path, op, edgeStyle);
771 this->recordedDrawCommand();
772 }
773
onClipRegion(const SkRegion & deviceRgn,SkRegion::Op op)774 void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
775 this->drawingCanvas()->clipRegion(deviceRgn, op);
776 this->INHERITED::onClipRegion(deviceRgn, op);
777 this->recordedDrawCommand();
778 }
779
onDrawPaint(const SkPaint & paint)780 void SkDeferredCanvas::onDrawPaint(const SkPaint& paint) {
781 if (fDeferredDrawing && this->isFullFrame(NULL, &paint) &&
782 isPaintOpaque(&paint)) {
783 this->getDeferredDevice()->skipPendingCommands();
784 }
785 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
786 this->drawingCanvas()->drawPaint(paint);
787 this->recordedDrawCommand();
788 }
789
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)790 void SkDeferredCanvas::onDrawPoints(PointMode mode, size_t count,
791 const SkPoint pts[], const SkPaint& paint) {
792 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
793 this->drawingCanvas()->drawPoints(mode, count, pts, paint);
794 this->recordedDrawCommand();
795 }
796
onDrawOval(const SkRect & rect,const SkPaint & paint)797 void SkDeferredCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
798 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
799 this->drawingCanvas()->drawOval(rect, paint);
800 this->recordedDrawCommand();
801 }
802
onDrawRect(const SkRect & rect,const SkPaint & paint)803 void SkDeferredCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
804 if (fDeferredDrawing && this->isFullFrame(&rect, &paint) &&
805 isPaintOpaque(&paint)) {
806 this->getDeferredDevice()->skipPendingCommands();
807 }
808
809 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
810 this->drawingCanvas()->drawRect(rect, paint);
811 this->recordedDrawCommand();
812 }
813
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)814 void SkDeferredCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
815 if (rrect.isRect()) {
816 this->SkDeferredCanvas::drawRect(rrect.getBounds(), paint);
817 } else if (rrect.isOval()) {
818 this->SkDeferredCanvas::drawOval(rrect.getBounds(), paint);
819 } else {
820 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
821 this->drawingCanvas()->drawRRect(rrect, paint);
822 this->recordedDrawCommand();
823 }
824 }
825
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)826 void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
827 const SkPaint& paint) {
828 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
829 this->drawingCanvas()->drawDRRect(outer, inner, paint);
830 this->recordedDrawCommand();
831 }
832
onDrawPath(const SkPath & path,const SkPaint & paint)833 void SkDeferredCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
834 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
835 this->drawingCanvas()->drawPath(path, paint);
836 this->recordedDrawCommand();
837 }
838
onDrawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)839 void SkDeferredCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
840 SkScalar top, const SkPaint* paint) {
841 SkRect bitmapRect = SkRect::MakeXYWH(left, top,
842 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
843 if (fDeferredDrawing &&
844 this->isFullFrame(&bitmapRect, paint) &&
845 isPaintOpaque(paint, &bitmap)) {
846 this->getDeferredDevice()->skipPendingCommands();
847 }
848
849 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
850 this->drawingCanvas()->drawBitmap(bitmap, left, top, paint);
851 this->recordedDrawCommand();
852 }
853
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)854 void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
855 const SkRect& dst,
856 const SkPaint* paint, DrawBitmapRectFlags flags) {
857 if (fDeferredDrawing &&
858 this->isFullFrame(&dst, paint) &&
859 isPaintOpaque(paint, &bitmap)) {
860 this->getDeferredDevice()->skipPendingCommands();
861 }
862
863 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
864 this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
865 this->recordedDrawCommand();
866 }
867
868
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)869 void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
870 const SkPaint* paint) {
871 SkRect bounds = SkRect::MakeXYWH(x, y,
872 SkIntToScalar(image->width()), SkIntToScalar(image->height()));
873 if (fDeferredDrawing &&
874 this->isFullFrame(&bounds, paint) &&
875 isPaintOpaque(paint, image)) {
876 this->getDeferredDevice()->skipPendingCommands();
877 }
878
879 AutoImmediateDrawIfNeeded autoDraw(*this, image, paint);
880 this->drawingCanvas()->drawImage(image, x, y, paint);
881 this->recordedDrawCommand();
882 }
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint)883 void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
884 const SkPaint* paint) {
885 if (fDeferredDrawing &&
886 this->isFullFrame(&dst, paint) &&
887 isPaintOpaque(paint, image)) {
888 this->getDeferredDevice()->skipPendingCommands();
889 }
890
891 AutoImmediateDrawIfNeeded autoDraw(*this, image, paint);
892 this->drawingCanvas()->drawImageRect(image, src, dst, paint);
893 this->recordedDrawCommand();
894 }
895
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)896 void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
897 const SkIRect& center, const SkRect& dst,
898 const SkPaint* paint) {
899 // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
900 // covers canvas entirely and dst covers canvas entirely
901 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
902 this->drawingCanvas()->drawBitmapNine(bitmap, center, dst, paint);
903 this->recordedDrawCommand();
904 }
905
onDrawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint)906 void SkDeferredCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top,
907 const SkPaint* paint) {
908 SkRect bitmapRect = SkRect::MakeXYWH(
909 SkIntToScalar(left),
910 SkIntToScalar(top),
911 SkIntToScalar(bitmap.width()),
912 SkIntToScalar(bitmap.height()));
913 if (fDeferredDrawing &&
914 this->isFullFrame(&bitmapRect, paint) &&
915 isPaintOpaque(paint, &bitmap)) {
916 this->getDeferredDevice()->skipPendingCommands();
917 }
918
919 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
920 this->drawingCanvas()->drawSprite(bitmap, left, top, paint);
921 this->recordedDrawCommand();
922 }
923
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)924 void SkDeferredCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
925 const SkPaint& paint) {
926 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
927 this->drawingCanvas()->drawText(text, byteLength, x, y, paint);
928 this->recordedDrawCommand();
929 }
930
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)931 void SkDeferredCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
932 const SkPaint& paint) {
933 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
934 this->drawingCanvas()->drawPosText(text, byteLength, pos, paint);
935 this->recordedDrawCommand();
936 }
937
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)938 void SkDeferredCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
939 SkScalar constY, const SkPaint& paint) {
940 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
941 this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
942 this->recordedDrawCommand();
943 }
944
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)945 void SkDeferredCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
946 const SkMatrix* matrix, const SkPaint& paint) {
947 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
948 this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint);
949 this->recordedDrawCommand();
950 }
951
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)952 void SkDeferredCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
953 const SkPaint& paint) {
954 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
955 this->drawingCanvas()->drawTextBlob(blob, x, y, paint);
956 this->recordedDrawCommand();
957 }
958
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)959 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
960 const SkPaint* paint) {
961 this->drawingCanvas()->drawPicture(picture, matrix, paint);
962 this->recordedDrawCommand();
963 }
964
onDrawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)965 void SkDeferredCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
966 const SkPoint vertices[],
967 const SkPoint texs[],
968 const SkColor colors[], SkXfermode* xmode,
969 const uint16_t indices[], int indexCount,
970 const SkPaint& paint) {
971 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
972 this->drawingCanvas()->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
973 indices, indexCount, paint);
974 this->recordedDrawCommand();
975 }
976
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)977 void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
978 const SkPoint texCoords[4], SkXfermode* xmode,
979 const SkPaint& paint) {
980 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
981 this->drawingCanvas()->drawPatch(cubics, colors, texCoords, xmode, paint);
982 this->recordedDrawCommand();
983 }
984
setDrawFilter(SkDrawFilter * filter)985 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
986 this->drawingCanvas()->setDrawFilter(filter);
987 this->INHERITED::setDrawFilter(filter);
988 this->recordedDrawCommand();
989 return filter;
990 }
991
canvasForDrawIter()992 SkCanvas* SkDeferredCanvas::canvasForDrawIter() {
993 return this->drawingCanvas();
994 }
995