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