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