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 
22 enum {
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 
30 enum PlaybackMode {
31     kNormal_PlaybackMode,
32     kSilent_PlaybackMode,
33 };
34 
image_area(const SkImage * image)35 static 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 //
should_draw_gpu_image_immediately(const SkImage * image)45 static bool should_draw_gpu_image_immediately(const SkImage* image) {
46     return image->getTexture() != NULL;
47 }
48 
should_draw_immediately(const SkBitmap * bitmap,const SkImage * image,const SkPaint * paint,size_t bitmapSizeThreshold)49 static 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 
82 class DeferredPipeController : public SkGPipeController {
83 public:
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);
hasPendingCommands() const90     bool hasPendingCommands() const { return fAllocator.totalUsed() != 0; }
storageAllocatedForRecording() const91     size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
92 private:
93     enum {
94         kMinBlockSize = 4096
95     };
96     struct PipeBlock {
PipeBlockDeferredPipeController::PipeBlock97         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 
DeferredPipeController()108 DeferredPipeController::DeferredPipeController() :
109     fAllocator(kMinBlockSize) {
110     fBlock = NULL;
111     fBytesWritten = 0;
112 }
113 
~DeferredPipeController()114 DeferredPipeController::~DeferredPipeController() {
115     fAllocator.reset();
116 }
117 
setPlaybackCanvas(SkCanvas * canvas)118 void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
119     fReader.setCanvas(canvas);
120 }
121 
requestBlock(size_t minRequest,size_t * actual)122 void* 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 
notifyWritten(size_t bytes)135 void DeferredPipeController::notifyWritten(size_t bytes) {
136     fBytesWritten += bytes;
137 }
138 
playback(bool silent)139 void 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 //-----------------------------------------------------------------------------
159 class SkDeferredDevice : public SkBaseDevice {
160 public:
161     explicit SkDeferredDevice(SkSurface* surface);
162     ~SkDeferredDevice();
163 
164     void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
165     SkCanvas* recordingCanvas();
immediateCanvas() const166     SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
immediateDevice() const167     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();
setIsDrawingToLayer(bool value)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 
188 protected:
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
drawPaint(const SkDraw &,const SkPaint & paint)195     void drawPaint(const SkDraw&, const SkPaint& paint) override
196         {SkASSERT(0);}
drawPoints(const SkDraw &,SkCanvas::PointMode mode,size_t count,const SkPoint[],const SkPaint & paint)197     void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
198                     size_t count, const SkPoint[],
199                     const SkPaint& paint) override
200         {SkASSERT(0);}
drawRect(const SkDraw &,const SkRect & r,const SkPaint & paint)201     void drawRect(const SkDraw&, const SkRect& r,
202                   const SkPaint& paint) override
203         {SkASSERT(0);}
drawOval(const SkDraw &,const SkRect &,const SkPaint &)204     void drawOval(const SkDraw&, const SkRect&, const SkPaint&) override
205         {SkASSERT(0);}
drawRRect(const SkDraw &,const SkRRect & rr,const SkPaint & paint)206     void drawRRect(const SkDraw&, const SkRRect& rr,
207                    const SkPaint& paint) override
208     {SkASSERT(0);}
drawPath(const SkDraw &,const SkPath & path,const SkPaint & paint,const SkMatrix * prePathMatrix=NULL,bool pathIsMutable=false)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);}
drawBitmap(const SkDraw &,const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint & paint)214     void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
215                     const SkMatrix& matrix, const SkPaint& paint) override
216         {SkASSERT(0);}
drawBitmapRect(const SkDraw &,const SkBitmap &,const SkRect *,const SkRect &,const SkPaint &,SkCanvas::DrawBitmapRectFlags)217     void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect*,
218                         const SkRect&, const SkPaint&,
219                         SkCanvas::DrawBitmapRectFlags) override
220         {SkASSERT(0);}
drawSprite(const SkDraw &,const SkBitmap & bitmap,int x,int y,const SkPaint & paint)221     void drawSprite(const SkDraw&, const SkBitmap& bitmap,
222                     int x, int y, const SkPaint& paint) override
223         {SkASSERT(0);}
drawImage(const SkDraw &,const SkImage *,SkScalar,SkScalar,const SkPaint &)224     void drawImage(const SkDraw&, const SkImage*, SkScalar, SkScalar, const SkPaint&) override
225         {SkASSERT(0);}
drawImageRect(const SkDraw &,const SkImage *,const SkRect *,const SkRect &,const SkPaint &)226     void drawImageRect(const SkDraw&, const SkImage*, const SkRect*, const SkRect&,
227                        const SkPaint&) override
228         {SkASSERT(0);}
drawText(const SkDraw &,const void * text,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)229     void drawText(const SkDraw&, const void* text, size_t len,
230                   SkScalar x, SkScalar y, const SkPaint& paint) override
231         {SkASSERT(0);}
drawPosText(const SkDraw &,const void * text,size_t len,const SkScalar pos[],int scalarsPerPos,const SkPoint & offset,const SkPaint & paint)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);}
drawTextOnPath(const SkDraw &,const void * text,size_t len,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)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);}
drawVertices(const SkDraw &,SkCanvas::VertexMode,int vertexCount,const SkPoint verts[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)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);}
drawPatch(const SkDraw &,const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)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);}
drawDevice(const SkDraw &,SkBaseDevice *,int x,int y,const SkPaint &)251     void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
252                     const SkPaint&) override
253         {SkASSERT(0);}
254 
lockPixels()255     void lockPixels() override {}
unlockPixels()256     void unlockPixels() override {}
257 
canHandleImageFilter(const SkImageFilter *)258     bool canHandleImageFilter(const SkImageFilter*) override {
259         return false;
260     }
filterImage(const SkImageFilter *,const SkBitmap &,const SkImageFilter::Context &,SkBitmap *,SkIPoint *)261     bool filterImage(const SkImageFilter*, const SkBitmap&,
262                      const SkImageFilter::Context&, SkBitmap*, SkIPoint*) override {
263         return false;
264     }
265 
266 private:
267     void flush() override;
replaceBitmapBackendForRasterSurface(const SkBitmap &)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 
SkDeferredDevice(SkSurface * surface)288 SkDeferredDevice::SkDeferredDevice(SkSurface* surface) {
289     fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
290     fNotificationClient = NULL;
291     fImmediateCanvas = NULL;
292     fSurface = NULL;
293     this->setSurface(surface);
294     this->init();
295 }
296 
setSurface(SkSurface * surface)297 void SkDeferredDevice::setSurface(SkSurface* surface) {
298     SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
299     SkRefCnt_SafeAssign(fSurface, surface);
300     fPipeController.setPlaybackCanvas(fImmediateCanvas);
301 }
302 
init()303 void 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 
~SkDeferredDevice()314 SkDeferredDevice::~SkDeferredDevice() {
315     this->flushPendingCommands(kSilent_PlaybackMode);
316     SkSafeUnref(fImmediateCanvas);
317     SkSafeUnref(fSurface);
318 }
319 
setMaxRecordingStorage(size_t maxStorage)320 void SkDeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
321     fMaxRecordingStorageBytes = maxStorage;
322     this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
323 }
324 
beginRecording()325 void SkDeferredDevice::beginRecording() {
326     SkASSERT(NULL == fRecordingCanvas);
327     fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
328         immediateDevice()->width(), immediateDevice()->height());
329 }
330 
setNotificationClient(SkDeferredCanvas::NotificationClient * notificationClient)331 void SkDeferredDevice::setNotificationClient(
332     SkDeferredCanvas::NotificationClient* notificationClient) {
333     fNotificationClient = notificationClient;
334 }
335 
skipPendingCommands()336 void SkDeferredDevice::skipPendingCommands() {
337     if (!fIsDrawingToLayer) {
338         fCanDiscardCanvasContents = true;
339         if (fPipeController.hasPendingCommands()) {
340             fFreshFrame = true;
341             flushPendingCommands(kSilent_PlaybackMode);
342         }
343     }
344 }
345 
isFreshFrame()346 bool SkDeferredDevice::isFreshFrame() {
347     bool ret = fFreshFrame;
348     fFreshFrame = false;
349     return ret;
350 }
351 
hasPendingCommands()352 bool SkDeferredDevice::hasPendingCommands() {
353     return fPipeController.hasPendingCommands();
354 }
355 
aboutToDraw()356 void 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 
flushPendingCommands(PlaybackMode playbackMode)369 void 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 
flush()389 void SkDeferredDevice::flush() {
390     this->flushPendingCommands(kNormal_PlaybackMode);
391     fImmediateCanvas->flush();
392 }
393 
freeMemoryIfPossible(size_t bytesToFree)394 size_t SkDeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
395     size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
396     fPreviousStorageAllocated = storageAllocatedForRecording();
397     return val;
398 }
399 
storageAllocatedForRecording() const400 size_t SkDeferredDevice::storageAllocatedForRecording() const {
401     return (fPipeController.storageAllocatedForRecording()
402             + fPipeWriter.storageAllocatedForRecording());
403 }
404 
recordedDrawCommand()405 void 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 
recordingCanvas()428 SkCanvas* SkDeferredDevice::recordingCanvas() {
429     return fRecordingCanvas;
430 }
431 
newImageSnapshot()432 SkImage* SkDeferredDevice::newImageSnapshot() {
433     this->flush();
434     return fSurface ? fSurface->newImageSnapshot() : NULL;
435 }
436 
imageInfo() const437 SkImageInfo SkDeferredDevice::imageInfo() const {
438     return immediateDevice()->imageInfo();
439 }
440 
accessRenderTarget()441 GrRenderTarget* SkDeferredDevice::accessRenderTarget() {
442     this->flushPendingCommands(kNormal_PlaybackMode);
443     return immediateDevice()->accessRenderTarget();
444 }
445 
prepareForImmediatePixelWrite()446 void 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 
onWritePixels(const SkImageInfo & info,const void * pixels,size_t rowBytes,int x,int y)463 bool 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 
onAccessBitmap()480 const SkBitmap& SkDeferredDevice::onAccessBitmap() {
481     this->flushPendingCommands(kNormal_PlaybackMode);
482     return immediateDevice()->accessBitmap(false);
483 }
484 
onCreateDevice(const CreateInfo & cinfo,const SkPaint * layerPaint)485 SkBaseDevice* 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 
newSurface(const SkImageInfo & info,const SkSurfaceProps & props)494 SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
495     return this->immediateDevice()->newSurface(info, props);
496 }
497 
onReadPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,int x,int y)498 bool 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 
504 class AutoImmediateDrawIfNeeded {
505 public:
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkBitmap * bitmap,const SkPaint * paint)506     AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
507                               const SkPaint* paint) {
508         this->init(canvas, bitmap, NULL, paint);
509     }
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkImage * image,const SkPaint * paint)510     AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkImage* image,
511                               const SkPaint* paint) {
512         this->init(canvas, NULL, image, paint);
513     }
514 
AutoImmediateDrawIfNeeded(SkDeferredCanvas & canvas,const SkPaint * paint)515     AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
516         this->init(canvas, NULL, NULL, paint);
517     }
518 
~AutoImmediateDrawIfNeeded()519     ~AutoImmediateDrawIfNeeded() {
520         if (fCanvas) {
521             fCanvas->setDeferredDrawing(true);
522         }
523     }
524 private:
init(SkDeferredCanvas & canvas,const SkBitmap * bitmap,const SkImage * image,const SkPaint * paint)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 
Create(SkSurface * surface)539 SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) {
540     SkAutoTUnref<SkDeferredDevice> deferredDevice(SkNEW_ARGS(SkDeferredDevice, (surface)));
541     return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
542 }
543 
SkDeferredCanvas(SkDeferredDevice * device)544 SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device) {
545     this->init();
546 }
547 
init()548 void 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 
setMaxRecordingStorage(size_t maxStorage)557 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
558     this->validate();
559     this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
560 }
561 
storageAllocatedForRecording() const562 size_t SkDeferredCanvas::storageAllocatedForRecording() const {
563     return this->getDeferredDevice()->storageAllocatedForRecording();
564 }
565 
freeMemoryIfPossible(size_t bytesToFree)566 size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
567     return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
568 }
569 
setBitmapSizeThreshold(size_t sizeThreshold)570 void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) {
571     fBitmapSizeThreshold = sizeThreshold;
572 }
573 
recordedDrawCommand()574 void SkDeferredCanvas::recordedDrawCommand() {
575     if (fDeferredDrawing) {
576         this->getDeferredDevice()->recordedDrawCommand();
577     }
578 }
579 
validate() const580 void SkDeferredCanvas::validate() const {
581     SkASSERT(this->getDevice());
582 }
583 
drawingCanvas() const584 SkCanvas* SkDeferredCanvas::drawingCanvas() const {
585     this->validate();
586     return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() :
587         this->getDeferredDevice()->immediateCanvas();
588 }
589 
immediateCanvas() const590 SkCanvas* SkDeferredCanvas::immediateCanvas() const {
591     this->validate();
592     return this->getDeferredDevice()->immediateCanvas();
593 }
594 
getDeferredDevice() const595 SkDeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
596     return static_cast<SkDeferredDevice*>(this->getDevice());
597 }
598 
setDeferredDrawing(bool val)599 void 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 
isDeferredDrawing() const610 bool SkDeferredCanvas::isDeferredDrawing() const {
611     return fDeferredDrawing;
612 }
613 
isFreshFrame() const614 bool SkDeferredCanvas::isFreshFrame() const {
615     return this->getDeferredDevice()->isFreshFrame();
616 }
617 
getCanvasSize() const618 SkISize SkDeferredCanvas::getCanvasSize() const {
619     if (fCachedCanvasSizeDirty) {
620         fCachedCanvasSize = this->getBaseLayerSize();
621         fCachedCanvasSizeDirty = false;
622     }
623     return fCachedCanvasSize;
624 }
625 
hasPendingCommands() const626 bool SkDeferredCanvas::hasPendingCommands() const {
627     return this->getDeferredDevice()->hasPendingCommands();
628 }
629 
silentFlush()630 void SkDeferredCanvas::silentFlush() {
631     if (fDeferredDrawing) {
632         this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode);
633     }
634 }
635 
~SkDeferredCanvas()636 SkDeferredCanvas::~SkDeferredCanvas() {
637 }
638 
setSurface(SkSurface * surface)639 SkSurface* 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 
setNotificationClient(NotificationClient * notificationClient)650 SkDeferredCanvas::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 
newImageSnapshot()661 SkImage* SkDeferredCanvas::newImageSnapshot() {
662     SkDeferredDevice* deferredDevice = this->getDeferredDevice();
663     SkASSERT(deferredDevice);
664     return deferredDevice ? deferredDevice->newImageSnapshot() : NULL;
665 }
666 
isFullFrame(const SkRect * rect,const SkPaint * paint) const667 bool 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 
willSave()705 void SkDeferredCanvas::willSave() {
706     fSaveLevel++;
707     this->drawingCanvas()->save();
708     this->recordedDrawCommand();
709     this->INHERITED::willSave();
710 }
711 
willSaveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags flags)712 SkCanvas::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 
willRestore()726 void 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 
didConcat(const SkMatrix & matrix)738 void SkDeferredCanvas::didConcat(const SkMatrix& matrix) {
739     this->drawingCanvas()->concat(matrix);
740     this->recordedDrawCommand();
741     this->INHERITED::didConcat(matrix);
742 }
743 
didSetMatrix(const SkMatrix & matrix)744 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
745     this->drawingCanvas()->setMatrix(matrix);
746     this->recordedDrawCommand();
747     this->INHERITED::didSetMatrix(matrix);
748 }
749 
onClipRect(const SkRect & rect,SkRegion::Op op,ClipEdgeStyle edgeStyle)750 void 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 
onClipRRect(const SkRRect & rrect,SkRegion::Op op,ClipEdgeStyle edgeStyle)758 void 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 
onClipPath(const SkPath & path,SkRegion::Op op,ClipEdgeStyle edgeStyle)766 void 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 
onClipRegion(const SkRegion & deviceRgn,SkRegion::Op op)774 void 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 
onDrawPaint(const SkPaint & paint)780 void 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 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)790 void 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 
onDrawOval(const SkRect & rect,const SkPaint & paint)797 void SkDeferredCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
798     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
799     this->drawingCanvas()->drawOval(rect, paint);
800     this->recordedDrawCommand();
801 }
802 
onDrawRect(const SkRect & rect,const SkPaint & paint)803 void 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 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)814 void 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 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)826 void 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 
onDrawPath(const SkPath & path,const SkPaint & paint)833 void SkDeferredCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
834     AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
835     this->drawingCanvas()->drawPath(path, paint);
836     this->recordedDrawCommand();
837 }
838 
onDrawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)839 void 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 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,DrawBitmapRectFlags flags)854 void 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 
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)869 void 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 }
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint)883 void 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 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)896 void 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 
onDrawSprite(const SkBitmap & bitmap,int left,int top,const SkPaint * paint)906 void 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 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)924 void 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 
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)931 void 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 
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)938 void 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 
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)945 void 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 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)952 void 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 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)959 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
960                                      const SkPaint* paint) {
961     this->drawingCanvas()->drawPicture(picture, matrix, paint);
962     this->recordedDrawCommand();
963 }
964 
onDrawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)965 void 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 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)977 void 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 
setDrawFilter(SkDrawFilter * filter)985 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
986     this->drawingCanvas()->setDrawFilter(filter);
987     this->INHERITED::setDrawFilter(filter);
988     this->recordedDrawCommand();
989     return filter;
990 }
991 
canvasForDrawIter()992 SkCanvas* SkDeferredCanvas::canvasForDrawIter() {
993     return this->drawingCanvas();
994 }
995