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