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