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