3 * Copyright 2013 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
9 #include "SkDeferredCanvas.h"
11 #include "SkBitmapDevice.h"
12 #include "SkChunkAlloc.h"
13 #include "SkColorFilter.h"
14 #include "SkDrawFilter.h"
17 #include "SkPaintPriv.h"
20 #include "SkSurface.h"
23 // Deferred canvas will auto-flush when recording reaches this limit
24 kDefaultMaxRecordingStorageBytes = 64*1024*1024,
25 kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature
34 bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint,
35 size_t bitmapSizeThreshold) {
36 if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) ||
37 (bitmap->getSize() > bitmapSizeThreshold))) {
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)) {
49 if (shader->asABitmap(&bm, NULL, NULL) &&
50 NULL != bm.getTexture()) {
59 //-----------------------------------------------------------------------------
60 // DeferredPipeController
61 //-----------------------------------------------------------------------------
63 class DeferredPipeController : public SkGPipeController {
65 DeferredPipeController();
66 void setPlaybackCanvas(SkCanvas*);
67 virtual ~DeferredPipeController();
68 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
69 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
70 void playback(bool silent);
71 bool hasPendingCommands() const { return fAllocator.blockCount() != 0; }
72 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
78 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
84 SkChunkAlloc fAllocator;
85 SkTDArray<PipeBlock> fBlockList;
86 SkGPipeReader fReader;
89 DeferredPipeController::DeferredPipeController() :
90 fAllocator(kMinBlockSize) {
95 DeferredPipeController::~DeferredPipeController() {
99 void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
100 fReader.setCanvas(canvas);
103 void* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) {
105 // Save the previous block for later
106 PipeBlock previousBloc(fBlock, fBytesWritten);
107 fBlockList.push(previousBloc);
109 size_t blockSize = SkTMax<size_t>(minRequest, kMinBlockSize);
110 fBlock = fAllocator.allocThrow(blockSize);
116 void DeferredPipeController::notifyWritten(size_t bytes) {
117 fBytesWritten += bytes;
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,
129 fReader.playback(fBlock, fBytesWritten, flags);
133 // Release all allocated blocks
137 //-----------------------------------------------------------------------------
139 //-----------------------------------------------------------------------------
140 // FIXME: Derive from SkBaseDevice.
141 class DeferredDevice : public SkBitmapDevice {
143 explicit DeferredDevice(SkBaseDevice* immediateDevice);
144 explicit DeferredDevice(SkSurface* surface);
147 void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient);
148 SkCanvas* recordingCanvas();
149 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
150 SkBaseDevice* immediateDevice() const {return fImmediateCanvas->getTopDevice();}
151 SkImage* newImageSnapshot();
152 void setSurface(SkSurface* surface);
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();
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;
169 virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config config,
170 int width, int height,
172 Usage usage) SK_OVERRIDE;
174 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
175 SkCanvas::Config8888 config8888) SK_OVERRIDE;
178 virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE;
179 virtual bool onReadPixels(const SkBitmap& bitmap,
181 SkCanvas::Config8888 config8888) SK_OVERRIDE;
183 // The following methods are no-ops on a deferred device
184 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
188 // None of the following drawing methods should ever get called on the
190 virtual void clear(SkColor color) SK_OVERRIDE
192 virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE
194 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
195 size_t count, const SkPoint[],
196 const SkPaint& paint) SK_OVERRIDE
198 virtual void drawRect(const SkDraw&, const SkRect& r,
199 const SkPaint& paint) SK_OVERRIDE
201 virtual void drawRRect(const SkDraw&, const SkRRect& rr,
202 const SkPaint& paint) SK_OVERRIDE
204 virtual void drawPath(const SkDraw&, const SkPath& path,
205 const SkPaint& paint,
206 const SkMatrix* prePathMatrix = NULL,
207 bool pathIsMutable = false) SK_OVERRIDE
209 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
210 const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE
212 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
213 int x, int y, const SkPaint& paint) SK_OVERRIDE
215 virtual void drawText(const SkDraw&, const void* text, size_t len,
216 SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE
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
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
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
233 virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
234 const SkPaint&) SK_OVERRIDE
237 virtual void flush() SK_OVERRIDE;
239 void beginRecording();
242 void prepareForImmediatePixelWrite();
244 DeferredPipeController fPipeController;
245 SkGPipeWriter fPipeWriter;
246 SkCanvas* fImmediateCanvas;
247 SkCanvas* fRecordingCanvas;
249 SkDeferredCanvas::NotificationClient* fNotificationClient;
251 bool fCanDiscardCanvasContents;
252 size_t fMaxRecordingStorageBytes;
253 size_t fPreviousStorageAllocated;
254 size_t fBitmapSizeThreshold;
257 DeferredDevice::DeferredDevice(SkBaseDevice* immediateDevice)
258 : SkBitmapDevice(SkBitmap::kNo_Config,
259 immediateDevice->width(), immediateDevice->height(),
260 immediateDevice->isOpaque(),
261 immediateDevice->getDeviceProperties()) {
263 fImmediateCanvas = SkNEW_ARGS(SkCanvas, (immediateDevice));
264 fPipeController.setPlaybackCanvas(fImmediateCanvas);
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;
278 this->setSurface(surface);
282 void DeferredDevice::setSurface(SkSurface* surface) {
283 SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas());
284 SkRefCnt_SafeAssign(fSurface, surface);
285 fPipeController.setPlaybackCanvas(fImmediateCanvas);
288 void DeferredDevice::init() {
289 fRecordingCanvas = NULL;
291 fCanDiscardCanvasContents = false;
292 fPreviousStorageAllocated = 0;
293 fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold;
294 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
295 fNotificationClient = NULL;
296 this->beginRecording();
299 DeferredDevice::~DeferredDevice() {
300 this->flushPendingCommands(kSilent_PlaybackMode);
301 SkSafeUnref(fImmediateCanvas);
302 SkSafeUnref(fSurface);
305 void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
306 fMaxRecordingStorageBytes = maxStorage;
307 this->recordingCanvas(); // Accessing the recording canvas applies the new limit.
310 void DeferredDevice::beginRecording() {
311 SkASSERT(NULL == fRecordingCanvas);
312 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0,
313 immediateDevice()->width(), immediateDevice()->height());
316 void DeferredDevice::setNotificationClient(
317 SkDeferredCanvas::NotificationClient* notificationClient) {
318 fNotificationClient = notificationClient;
321 void DeferredDevice::skipPendingCommands() {
322 if (!fRecordingCanvas->isDrawingToLayer()) {
323 fCanDiscardCanvasContents = true;
324 if (fPipeController.hasPendingCommands()) {
326 flushPendingCommands(kSilent_PlaybackMode);
327 if (fNotificationClient) {
328 fNotificationClient->skippedPendingDrawCommands();
334 bool DeferredDevice::isFreshFrame() {
335 bool ret = fFreshFrame;
340 bool DeferredDevice::hasPendingCommands() {
341 return fPipeController.hasPendingCommands();
344 void DeferredDevice::aboutToDraw()
346 if (NULL != fNotificationClient) {
347 fNotificationClient->prepareForDraw();
349 if (fCanDiscardCanvasContents) {
350 if (NULL != fSurface) {
351 fSurface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode);
353 fCanDiscardCanvasContents = false;
357 void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) {
358 if (!fPipeController.hasPendingCommands()) {
361 if (playbackMode == kNormal_PlaybackMode) {
364 fPipeWriter.flushRecording(true);
365 fPipeController.playback(kSilent_PlaybackMode == playbackMode);
366 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) {
367 fNotificationClient->flushedDrawCommands();
369 fPreviousStorageAllocated = storageAllocatedForRecording();
372 void DeferredDevice::flush() {
373 this->flushPendingCommands(kNormal_PlaybackMode);
374 fImmediateCanvas->flush();
377 size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
378 size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree);
379 fPreviousStorageAllocated = storageAllocatedForRecording();
383 size_t DeferredDevice::getBitmapSizeThreshold() const {
384 return fBitmapSizeThreshold;
387 void DeferredDevice::setBitmapSizeThreshold(size_t sizeThreshold) {
388 fBitmapSizeThreshold = sizeThreshold;
391 size_t DeferredDevice::storageAllocatedForRecording() const {
392 return (fPipeController.storageAllocatedForRecording()
393 + fPipeWriter.storageAllocatedForRecording());
396 void DeferredDevice::recordedDrawCommand() {
397 size_t storageAllocated = this->storageAllocatedForRecording();
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);
409 storageAllocated = this->storageAllocatedForRecording();
412 if (fNotificationClient &&
413 storageAllocated != fPreviousStorageAllocated) {
414 fPreviousStorageAllocated = storageAllocated;
415 fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated);
419 SkCanvas* DeferredDevice::recordingCanvas() {
420 return fRecordingCanvas;
423 SkImage* DeferredDevice::newImageSnapshot() {
425 return fSurface ? fSurface->newImageSnapshot() : NULL;
428 uint32_t DeferredDevice::getDeviceCapabilities() {
429 return immediateDevice()->getDeviceCapabilities();
432 int DeferredDevice::width() const {
433 return immediateDevice()->width();
436 int DeferredDevice::height() const {
437 return immediateDevice()->height();
440 GrRenderTarget* DeferredDevice::accessRenderTarget() {
441 this->flushPendingCommands(kNormal_PlaybackMode);
442 return immediateDevice()->accessRenderTarget();
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);
452 bool mustNotifyDirectly = !fCanDiscardCanvasContents;
454 if (mustNotifyDirectly) {
455 fSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
459 fImmediateCanvas->flush();
462 void DeferredDevice::writePixels(const SkBitmap& bitmap,
463 int x, int y, SkCanvas::Config8888 config8888) {
465 if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
466 (y + bitmap.height()) >= height()) {
467 this->skipPendingCommands();
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);
480 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
481 if (shouldDrawImmediately(&bitmap, NULL, getBitmapSizeThreshold())) {
482 prepareForImmediatePixelWrite();
483 fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
485 this->recordingCanvas()->drawSprite(bitmap, x, y, &paint);
486 this->recordedDrawCommand();
491 const SkBitmap& DeferredDevice::onAccessBitmap() {
492 this->flushPendingCommands(kNormal_PlaybackMode);
493 return immediateDevice()->accessBitmap(false);
496 SkBaseDevice* DeferredDevice::onCreateCompatibleDevice(
497 SkBitmap::Config config, int width, int height, bool isOpaque,
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);
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),
517 class AutoImmediateDrawIfNeeded {
519 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
520 const SkPaint* paint) {
521 this->init(canvas, bitmap, paint);
524 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
525 this->init(canvas, NULL, paint);
528 ~AutoImmediateDrawIfNeeded() {
530 fCanvas->setDeferredDrawing(true);
534 void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint)
536 DeferredDevice* device = static_cast<DeferredDevice*>(canvas.getDevice());
537 if (canvas.isDeferredDrawing() && (NULL != device) &&
538 shouldDrawImmediately(bitmap, paint, device->getBitmapSizeThreshold())) {
539 canvas.setDeferredDrawing(false);
546 SkDeferredCanvas* fCanvas;
549 SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) {
550 SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (surface)));
551 return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
554 SkDeferredCanvas* SkDeferredCanvas::Create(SkBaseDevice* device) {
555 SkAutoTUnref<DeferredDevice> deferredDevice(SkNEW_ARGS(DeferredDevice, (device)));
556 return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice));
559 SkDeferredCanvas::SkDeferredCanvas(DeferredDevice* device) : SkCanvas (device) {
563 void SkDeferredCanvas::init() {
564 fDeferredDrawing = true; // On by default
567 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
569 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
572 size_t SkDeferredCanvas::storageAllocatedForRecording() const {
573 return this->getDeferredDevice()->storageAllocatedForRecording();
576 size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
577 return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
580 void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) {
581 DeferredDevice* deferredDevice = this->getDeferredDevice();
582 SkASSERT(deferredDevice);
583 deferredDevice->setBitmapSizeThreshold(sizeThreshold);
586 void SkDeferredCanvas::recordedDrawCommand() {
587 if (fDeferredDrawing) {
588 this->getDeferredDevice()->recordedDrawCommand();
592 void SkDeferredCanvas::validate() const {
593 SkASSERT(this->getDevice());
596 SkCanvas* SkDeferredCanvas::drawingCanvas() const {
598 return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() :
599 this->getDeferredDevice()->immediateCanvas();
602 SkCanvas* SkDeferredCanvas::immediateCanvas() const {
604 return this->getDeferredDevice()->immediateCanvas();
607 DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
608 return static_cast<DeferredDevice*>(this->getDevice());
611 void SkDeferredCanvas::setDeferredDrawing(bool val) {
612 this->validate(); // Must set device before calling this method
613 if (val != fDeferredDrawing) {
614 if (fDeferredDrawing) {
616 this->getDeferredDevice()->flushPendingCommands(kNormal_PlaybackMode);
618 fDeferredDrawing = val;
622 bool SkDeferredCanvas::isDeferredDrawing() const {
623 return fDeferredDrawing;
626 bool SkDeferredCanvas::isFreshFrame() const {
627 return this->getDeferredDevice()->isFreshFrame();
630 bool SkDeferredCanvas::hasPendingCommands() const {
631 return this->getDeferredDevice()->hasPendingCommands();
634 void SkDeferredCanvas::silentFlush() {
635 if (fDeferredDrawing) {
636 this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode);
640 SkDeferredCanvas::~SkDeferredCanvas() {
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);
653 SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient(
654 NotificationClient* notificationClient) {
656 DeferredDevice* deferredDevice = this->getDeferredDevice();
657 SkASSERT(deferredDevice);
658 if (deferredDevice) {
659 deferredDevice->setNotificationClient(notificationClient);
661 return notificationClient;
664 SkImage* SkDeferredCanvas::newImageSnapshot() {
665 DeferredDevice* deferredDevice = this->getDeferredDevice();
666 SkASSERT(deferredDevice);
667 return deferredDevice ? deferredDevice->newImageSnapshot() : NULL;
670 bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
671 const SkPaint* paint) const {
672 SkCanvas* canvas = this->drawingCanvas();
673 SkISize canvasSize = this->getDeviceSize();
675 if (!canvas->getTotalMatrix().rectStaysRect()) {
676 return false; // conservative
679 SkRect transformedRect;
680 canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
683 SkPaint::Style paintStyle = paint->getStyle();
684 if (!(paintStyle == SkPaint::kFill_Style ||
685 paintStyle == SkPaint::kStrokeAndFill_Style)) {
688 if (paint->getMaskFilter() || paint->getLooper()
689 || paint->getPathEffect() || paint->getImageFilter()) {
690 return false; // conservative
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)) {
704 return this->getClipStack()->quickContains(SkRect::MakeXYWH(0, 0,
705 SkIntToScalar(canvasSize.fWidth), SkIntToScalar(canvasSize.fHeight)));
708 int SkDeferredCanvas::save(SaveFlags flags) {
709 this->drawingCanvas()->save(flags);
710 int val = this->INHERITED::save(flags);
711 this->recordedDrawCommand();
716 int SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
718 this->drawingCanvas()->saveLayer(bounds, paint, flags);
719 int count = this->INHERITED::save(flags);
720 this->clipRectBounds(bounds, flags, NULL);
721 this->recordedDrawCommand();
726 void SkDeferredCanvas::restore() {
727 this->drawingCanvas()->restore();
728 this->INHERITED::restore();
729 this->recordedDrawCommand();
732 bool SkDeferredCanvas::isDrawingToLayer() const {
733 return this->drawingCanvas()->isDrawingToLayer();
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();
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();
750 bool SkDeferredCanvas::rotate(SkScalar degrees) {
751 this->drawingCanvas()->rotate(degrees);
752 bool val = this->INHERITED::rotate(degrees);
753 this->recordedDrawCommand();
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();
764 bool SkDeferredCanvas::concat(const SkMatrix& matrix) {
765 this->drawingCanvas()->concat(matrix);
766 bool val = this->INHERITED::concat(matrix);
767 this->recordedDrawCommand();
771 void SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
772 this->drawingCanvas()->setMatrix(matrix);
773 this->INHERITED::setMatrix(matrix);
774 this->recordedDrawCommand();
777 bool SkDeferredCanvas::clipRect(const SkRect& rect,
780 this->drawingCanvas()->clipRect(rect, op, doAntiAlias);
781 bool val = this->INHERITED::clipRect(rect, op, doAntiAlias);
782 this->recordedDrawCommand();
786 bool SkDeferredCanvas::clipRRect(const SkRRect& rrect,
789 this->drawingCanvas()->clipRRect(rrect, op, doAntiAlias);
790 bool val = this->INHERITED::clipRRect(rrect, op, doAntiAlias);
791 this->recordedDrawCommand();
795 bool SkDeferredCanvas::clipPath(const SkPath& path,
798 this->drawingCanvas()->clipPath(path, op, doAntiAlias);
799 bool val = this->INHERITED::clipPath(path, op, doAntiAlias);
800 this->recordedDrawCommand();
804 bool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
806 this->drawingCanvas()->clipRegion(deviceRgn, op);
807 bool val = this->INHERITED::clipRegion(deviceRgn, op);
808 this->recordedDrawCommand();
812 void SkDeferredCanvas::clear(SkColor color) {
813 // purge pending commands
814 if (fDeferredDrawing) {
815 this->getDeferredDevice()->skipPendingCommands();
818 this->drawingCanvas()->clear(color);
819 this->recordedDrawCommand();
822 void SkDeferredCanvas::drawPaint(const SkPaint& paint) {
823 if (fDeferredDrawing && this->isFullFrame(NULL, &paint) &&
824 isPaintOpaque(&paint)) {
825 this->getDeferredDevice()->skipPendingCommands();
827 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
828 this->drawingCanvas()->drawPaint(paint);
829 this->recordedDrawCommand();
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();
839 void SkDeferredCanvas::drawOval(const SkRect& rect, const SkPaint& paint) {
840 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
841 this->drawingCanvas()->drawOval(rect, paint);
842 this->recordedDrawCommand();
845 void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
846 if (fDeferredDrawing && this->isFullFrame(&rect, &paint) &&
847 isPaintOpaque(&paint)) {
848 this->getDeferredDevice()->skipPendingCommands();
851 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
852 this->drawingCanvas()->drawRect(rect, paint);
853 this->recordedDrawCommand();
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);
862 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
863 this->drawingCanvas()->drawRRect(rrect, paint);
864 this->recordedDrawCommand();
868 void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
869 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
870 this->drawingCanvas()->drawPath(path, paint);
871 this->recordedDrawCommand();
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();
884 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
885 this->drawingCanvas()->drawBitmap(bitmap, left, top, paint);
886 this->recordedDrawCommand();
889 void SkDeferredCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
892 const SkPaint* paint,
893 DrawBitmapRectFlags flags) {
894 if (fDeferredDrawing &&
895 this->isFullFrame(&dst, paint) &&
896 isPaintOpaque(paint, &bitmap)) {
897 this->getDeferredDevice()->skipPendingCommands();
900 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
901 this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint, flags);
902 this->recordedDrawCommand();
906 void SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
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();
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();
926 void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
927 const SkPaint* paint) {
928 SkRect bitmapRect = SkRect::MakeXYWH(
931 SkIntToScalar(bitmap.width()),
932 SkIntToScalar(bitmap.height()));
933 if (fDeferredDrawing &&
934 this->isFullFrame(&bitmapRect, paint) &&
935 isPaintOpaque(paint, &bitmap)) {
936 this->getDeferredDevice()->skipPendingCommands();
939 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
940 this->drawingCanvas()->drawSprite(bitmap, left, top, paint);
941 this->recordedDrawCommand();
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();
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();
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();
966 void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
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();
975 void SkDeferredCanvas::drawPicture(SkPicture& picture) {
976 this->drawingCanvas()->drawPicture(picture);
977 this->recordedDrawCommand();
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();
992 SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
993 this->drawingCanvas()->setBounder(bounder);
994 this->INHERITED::setBounder(bounder);
995 this->recordedDrawCommand();
999 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
1000 this->drawingCanvas()->setDrawFilter(filter);
1001 this->INHERITED::setDrawFilter(filter);
1002 this->recordedDrawCommand();
1006 SkCanvas* SkDeferredCanvas::canvasForDrawIter() {
1007 return this->drawingCanvas();