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