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