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