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