1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkDeferredCanvas.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1031 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2013 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "SkDeferredCanvas.h" 1.13 + 1.14 +#include "SkBitmapDevice.h" 1.15 +#include "SkChunkAlloc.h" 1.16 +#include "SkColorFilter.h" 1.17 +#include "SkDrawFilter.h" 1.18 +#include "SkGPipe.h" 1.19 +#include "SkPaint.h" 1.20 +#include "SkPaintPriv.h" 1.21 +#include "SkRRect.h" 1.22 +#include "SkShader.h" 1.23 +#include "SkSurface.h" 1.24 + 1.25 +enum { 1.26 + // Deferred canvas will auto-flush when recording reaches this limit 1.27 + kDefaultMaxRecordingStorageBytes = 64*1024*1024, 1.28 + kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature 1.29 +}; 1.30 + 1.31 +enum PlaybackMode { 1.32 + kNormal_PlaybackMode, 1.33 + kSilent_PlaybackMode, 1.34 +}; 1.35 + 1.36 +static bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint, 1.37 + size_t bitmapSizeThreshold) { 1.38 + if (bitmap && ((bitmap->getTexture() && !bitmap->isImmutable()) || 1.39 + (bitmap->getSize() > bitmapSizeThreshold))) { 1.40 + return true; 1.41 + } 1.42 + if (paint) { 1.43 + SkShader* shader = paint->getShader(); 1.44 + // Here we detect the case where the shader is an SkBitmapProcShader 1.45 + // with a gpu texture attached. Checking this without RTTI 1.46 + // requires making the assumption that only gradient shaders 1.47 + // and SkBitmapProcShader implement asABitmap(). The following 1.48 + // code may need to be revised if that assumption is ever broken. 1.49 + if (shader && !shader->asAGradient(NULL)) { 1.50 + SkBitmap bm; 1.51 + if (shader->asABitmap(&bm, NULL, NULL) && 1.52 + NULL != bm.getTexture()) { 1.53 + return true; 1.54 + } 1.55 + } 1.56 + } 1.57 + return false; 1.58 +} 1.59 + 1.60 +//----------------------------------------------------------------------------- 1.61 +// DeferredPipeController 1.62 +//----------------------------------------------------------------------------- 1.63 + 1.64 +class DeferredPipeController : public SkGPipeController { 1.65 +public: 1.66 + DeferredPipeController(); 1.67 + void setPlaybackCanvas(SkCanvas*); 1.68 + virtual ~DeferredPipeController(); 1.69 + virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE; 1.70 + virtual void notifyWritten(size_t bytes) SK_OVERRIDE; 1.71 + void playback(bool silent); 1.72 + bool hasPendingCommands() const { return fAllocator.blockCount() != 0; } 1.73 + size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); } 1.74 +private: 1.75 + enum { 1.76 + kMinBlockSize = 4096 1.77 + }; 1.78 + struct PipeBlock { 1.79 + PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; } 1.80 + void* fBlock; 1.81 + size_t fSize; 1.82 + }; 1.83 + void* fBlock; 1.84 + size_t fBytesWritten; 1.85 + SkChunkAlloc fAllocator; 1.86 + SkTDArray<PipeBlock> fBlockList; 1.87 + SkGPipeReader fReader; 1.88 +}; 1.89 + 1.90 +DeferredPipeController::DeferredPipeController() : 1.91 + fAllocator(kMinBlockSize) { 1.92 + fBlock = NULL; 1.93 + fBytesWritten = 0; 1.94 +} 1.95 + 1.96 +DeferredPipeController::~DeferredPipeController() { 1.97 + fAllocator.reset(); 1.98 +} 1.99 + 1.100 +void DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) { 1.101 + fReader.setCanvas(canvas); 1.102 +} 1.103 + 1.104 +void* DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) { 1.105 + if (fBlock) { 1.106 + // Save the previous block for later 1.107 + PipeBlock previousBloc(fBlock, fBytesWritten); 1.108 + fBlockList.push(previousBloc); 1.109 + } 1.110 + size_t blockSize = SkTMax<size_t>(minRequest, kMinBlockSize); 1.111 + fBlock = fAllocator.allocThrow(blockSize); 1.112 + fBytesWritten = 0; 1.113 + *actual = blockSize; 1.114 + return fBlock; 1.115 +} 1.116 + 1.117 +void DeferredPipeController::notifyWritten(size_t bytes) { 1.118 + fBytesWritten += bytes; 1.119 +} 1.120 + 1.121 +void DeferredPipeController::playback(bool silent) { 1.122 + uint32_t flags = silent ? SkGPipeReader::kSilent_PlaybackFlag : 0; 1.123 + for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) { 1.124 + fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize, 1.125 + flags); 1.126 + } 1.127 + fBlockList.reset(); 1.128 + 1.129 + if (fBlock) { 1.130 + fReader.playback(fBlock, fBytesWritten, flags); 1.131 + fBlock = NULL; 1.132 + } 1.133 + 1.134 + // Release all allocated blocks 1.135 + fAllocator.reset(); 1.136 +} 1.137 + 1.138 +//----------------------------------------------------------------------------- 1.139 +// SkDeferredDevice 1.140 +//----------------------------------------------------------------------------- 1.141 +class SkDeferredDevice : public SkBaseDevice { 1.142 +public: 1.143 + explicit SkDeferredDevice(SkSurface* surface); 1.144 + ~SkDeferredDevice(); 1.145 + 1.146 + void setNotificationClient(SkDeferredCanvas::NotificationClient* notificationClient); 1.147 + SkCanvas* recordingCanvas(); 1.148 + SkCanvas* immediateCanvas() const {return fImmediateCanvas;} 1.149 + SkBaseDevice* immediateDevice() const {return fImmediateCanvas->getTopDevice();} 1.150 + SkImage* newImageSnapshot(); 1.151 + void setSurface(SkSurface* surface); 1.152 + bool isFreshFrame(); 1.153 + bool hasPendingCommands(); 1.154 + size_t storageAllocatedForRecording() const; 1.155 + size_t freeMemoryIfPossible(size_t bytesToFree); 1.156 + size_t getBitmapSizeThreshold() const; 1.157 + void setBitmapSizeThreshold(size_t sizeThreshold); 1.158 + void flushPendingCommands(PlaybackMode); 1.159 + void skipPendingCommands(); 1.160 + void setMaxRecordingStorage(size_t); 1.161 + void recordedDrawCommand(); 1.162 + 1.163 + virtual int width() const SK_OVERRIDE; 1.164 + virtual int height() const SK_OVERRIDE; 1.165 + virtual SkBitmap::Config config() const SK_OVERRIDE; 1.166 + virtual bool isOpaque() const SK_OVERRIDE; 1.167 + virtual SkImageInfo imageInfo() const SK_OVERRIDE; 1.168 + 1.169 + virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE; 1.170 + 1.171 + virtual SkBaseDevice* onCreateDevice(const SkImageInfo&, Usage) SK_OVERRIDE; 1.172 + 1.173 +#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG 1.174 + virtual void writePixels(const SkBitmap& bitmap, int x, int y, 1.175 + SkCanvas::Config8888 config8888) SK_OVERRIDE; 1.176 +#endif 1.177 + virtual SkSurface* newSurface(const SkImageInfo&) SK_OVERRIDE; 1.178 + 1.179 +protected: 1.180 + virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE; 1.181 + virtual bool onReadPixels(const SkBitmap& bitmap, 1.182 + int x, int y, 1.183 + SkCanvas::Config8888 config8888) SK_OVERRIDE; 1.184 + virtual bool onWritePixels(const SkImageInfo&, const void*, size_t, int x, int y) SK_OVERRIDE; 1.185 + 1.186 + // The following methods are no-ops on a deferred device 1.187 + virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE { 1.188 + return false; 1.189 + } 1.190 + 1.191 + // None of the following drawing methods should ever get called on the 1.192 + // deferred device 1.193 + virtual void clear(SkColor color) SK_OVERRIDE 1.194 + {SkASSERT(0);} 1.195 + virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE 1.196 + {SkASSERT(0);} 1.197 + virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, 1.198 + size_t count, const SkPoint[], 1.199 + const SkPaint& paint) SK_OVERRIDE 1.200 + {SkASSERT(0);} 1.201 + virtual void drawRect(const SkDraw&, const SkRect& r, 1.202 + const SkPaint& paint) SK_OVERRIDE 1.203 + {SkASSERT(0);} 1.204 + virtual void drawOval(const SkDraw&, const SkRect&, const SkPaint&) SK_OVERRIDE 1.205 + {SkASSERT(0);} 1.206 + virtual void drawRRect(const SkDraw&, const SkRRect& rr, 1.207 + const SkPaint& paint) SK_OVERRIDE 1.208 + {SkASSERT(0);} 1.209 + virtual void drawPath(const SkDraw&, const SkPath& path, 1.210 + const SkPaint& paint, 1.211 + const SkMatrix* prePathMatrix = NULL, 1.212 + bool pathIsMutable = false) SK_OVERRIDE 1.213 + {SkASSERT(0);} 1.214 + virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap, 1.215 + const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE 1.216 + {SkASSERT(0);} 1.217 + virtual void drawBitmapRect(const SkDraw&, const SkBitmap&, const SkRect*, 1.218 + const SkRect&, const SkPaint&, 1.219 + SkCanvas::DrawBitmapRectFlags) SK_OVERRIDE 1.220 + {SkASSERT(0);} 1.221 + virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, 1.222 + int x, int y, const SkPaint& paint) SK_OVERRIDE 1.223 + {SkASSERT(0);} 1.224 + virtual void drawText(const SkDraw&, const void* text, size_t len, 1.225 + SkScalar x, SkScalar y, const SkPaint& paint) SK_OVERRIDE 1.226 + {SkASSERT(0);} 1.227 + virtual void drawPosText(const SkDraw&, const void* text, size_t len, 1.228 + const SkScalar pos[], SkScalar constY, 1.229 + int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE 1.230 + {SkASSERT(0);} 1.231 + virtual void drawTextOnPath(const SkDraw&, const void* text, 1.232 + size_t len, const SkPath& path, 1.233 + const SkMatrix* matrix, 1.234 + const SkPaint& paint) SK_OVERRIDE 1.235 + {SkASSERT(0);} 1.236 + virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, 1.237 + int vertexCount, const SkPoint verts[], 1.238 + const SkPoint texs[], const SkColor colors[], 1.239 + SkXfermode* xmode, const uint16_t indices[], 1.240 + int indexCount, const SkPaint& paint) SK_OVERRIDE 1.241 + {SkASSERT(0);} 1.242 + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, 1.243 + const SkPaint&) SK_OVERRIDE 1.244 + {SkASSERT(0);} 1.245 + 1.246 + virtual void lockPixels() SK_OVERRIDE {} 1.247 + virtual void unlockPixels() SK_OVERRIDE {} 1.248 + 1.249 + virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { 1.250 + return false; 1.251 + } 1.252 + virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { 1.253 + return false; 1.254 + } 1.255 + virtual bool filterImage(const SkImageFilter*, const SkBitmap&, 1.256 + const SkImageFilter::Context&, SkBitmap*, SkIPoint*) SK_OVERRIDE { 1.257 + return false; 1.258 + } 1.259 + 1.260 +private: 1.261 + virtual void flush() SK_OVERRIDE; 1.262 + virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {} 1.263 + 1.264 + void beginRecording(); 1.265 + void init(); 1.266 + void aboutToDraw(); 1.267 + void prepareForImmediatePixelWrite(); 1.268 + 1.269 + DeferredPipeController fPipeController; 1.270 + SkGPipeWriter fPipeWriter; 1.271 + SkCanvas* fImmediateCanvas; 1.272 + SkCanvas* fRecordingCanvas; 1.273 + SkSurface* fSurface; 1.274 + SkDeferredCanvas::NotificationClient* fNotificationClient; 1.275 + bool fFreshFrame; 1.276 + bool fCanDiscardCanvasContents; 1.277 + size_t fMaxRecordingStorageBytes; 1.278 + size_t fPreviousStorageAllocated; 1.279 + size_t fBitmapSizeThreshold; 1.280 +}; 1.281 + 1.282 +SkDeferredDevice::SkDeferredDevice(SkSurface* surface) { 1.283 + fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; 1.284 + fNotificationClient = NULL; 1.285 + fImmediateCanvas = NULL; 1.286 + fSurface = NULL; 1.287 + this->setSurface(surface); 1.288 + this->init(); 1.289 +} 1.290 + 1.291 +void SkDeferredDevice::setSurface(SkSurface* surface) { 1.292 + SkRefCnt_SafeAssign(fImmediateCanvas, surface->getCanvas()); 1.293 + SkRefCnt_SafeAssign(fSurface, surface); 1.294 + fPipeController.setPlaybackCanvas(fImmediateCanvas); 1.295 +} 1.296 + 1.297 +void SkDeferredDevice::init() { 1.298 + fRecordingCanvas = NULL; 1.299 + fFreshFrame = true; 1.300 + fCanDiscardCanvasContents = false; 1.301 + fPreviousStorageAllocated = 0; 1.302 + fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold; 1.303 + fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; 1.304 + fNotificationClient = NULL; 1.305 + this->beginRecording(); 1.306 +} 1.307 + 1.308 +SkDeferredDevice::~SkDeferredDevice() { 1.309 + this->flushPendingCommands(kSilent_PlaybackMode); 1.310 + SkSafeUnref(fImmediateCanvas); 1.311 + SkSafeUnref(fSurface); 1.312 +} 1.313 + 1.314 +void SkDeferredDevice::setMaxRecordingStorage(size_t maxStorage) { 1.315 + fMaxRecordingStorageBytes = maxStorage; 1.316 + this->recordingCanvas(); // Accessing the recording canvas applies the new limit. 1.317 +} 1.318 + 1.319 +void SkDeferredDevice::beginRecording() { 1.320 + SkASSERT(NULL == fRecordingCanvas); 1.321 + fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0, 1.322 + immediateDevice()->width(), immediateDevice()->height()); 1.323 +} 1.324 + 1.325 +void SkDeferredDevice::setNotificationClient( 1.326 + SkDeferredCanvas::NotificationClient* notificationClient) { 1.327 + fNotificationClient = notificationClient; 1.328 +} 1.329 + 1.330 +void SkDeferredDevice::skipPendingCommands() { 1.331 + if (!fRecordingCanvas->isDrawingToLayer()) { 1.332 + fCanDiscardCanvasContents = true; 1.333 + if (fPipeController.hasPendingCommands()) { 1.334 + fFreshFrame = true; 1.335 + flushPendingCommands(kSilent_PlaybackMode); 1.336 + if (fNotificationClient) { 1.337 + fNotificationClient->skippedPendingDrawCommands(); 1.338 + } 1.339 + } 1.340 + } 1.341 +} 1.342 + 1.343 +bool SkDeferredDevice::isFreshFrame() { 1.344 + bool ret = fFreshFrame; 1.345 + fFreshFrame = false; 1.346 + return ret; 1.347 +} 1.348 + 1.349 +bool SkDeferredDevice::hasPendingCommands() { 1.350 + return fPipeController.hasPendingCommands(); 1.351 +} 1.352 + 1.353 +void SkDeferredDevice::aboutToDraw() 1.354 +{ 1.355 + if (NULL != fNotificationClient) { 1.356 + fNotificationClient->prepareForDraw(); 1.357 + } 1.358 + if (fCanDiscardCanvasContents) { 1.359 + if (NULL != fSurface) { 1.360 + fSurface->notifyContentWillChange(SkSurface::kDiscard_ContentChangeMode); 1.361 + } 1.362 + fCanDiscardCanvasContents = false; 1.363 + } 1.364 +} 1.365 + 1.366 +void SkDeferredDevice::flushPendingCommands(PlaybackMode playbackMode) { 1.367 + if (!fPipeController.hasPendingCommands()) { 1.368 + return; 1.369 + } 1.370 + if (playbackMode == kNormal_PlaybackMode) { 1.371 + aboutToDraw(); 1.372 + } 1.373 + fPipeWriter.flushRecording(true); 1.374 + fPipeController.playback(kSilent_PlaybackMode == playbackMode); 1.375 + if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { 1.376 + fNotificationClient->flushedDrawCommands(); 1.377 + } 1.378 + fPreviousStorageAllocated = storageAllocatedForRecording(); 1.379 +} 1.380 + 1.381 +void SkDeferredDevice::flush() { 1.382 + this->flushPendingCommands(kNormal_PlaybackMode); 1.383 + fImmediateCanvas->flush(); 1.384 +} 1.385 + 1.386 +size_t SkDeferredDevice::freeMemoryIfPossible(size_t bytesToFree) { 1.387 + size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree); 1.388 + fPreviousStorageAllocated = storageAllocatedForRecording(); 1.389 + return val; 1.390 +} 1.391 + 1.392 +size_t SkDeferredDevice::getBitmapSizeThreshold() const { 1.393 + return fBitmapSizeThreshold; 1.394 +} 1.395 + 1.396 +void SkDeferredDevice::setBitmapSizeThreshold(size_t sizeThreshold) { 1.397 + fBitmapSizeThreshold = sizeThreshold; 1.398 +} 1.399 + 1.400 +size_t SkDeferredDevice::storageAllocatedForRecording() const { 1.401 + return (fPipeController.storageAllocatedForRecording() 1.402 + + fPipeWriter.storageAllocatedForRecording()); 1.403 +} 1.404 + 1.405 +void SkDeferredDevice::recordedDrawCommand() { 1.406 + size_t storageAllocated = this->storageAllocatedForRecording(); 1.407 + 1.408 + if (storageAllocated > fMaxRecordingStorageBytes) { 1.409 + // First, attempt to reduce cache without flushing 1.410 + size_t tryFree = storageAllocated - fMaxRecordingStorageBytes; 1.411 + if (this->freeMemoryIfPossible(tryFree) < tryFree) { 1.412 + // Flush is necessary to free more space. 1.413 + this->flushPendingCommands(kNormal_PlaybackMode); 1.414 + // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes 1.415 + // which could cause a high flushing frequency. 1.416 + this->freeMemoryIfPossible(~0U); 1.417 + } 1.418 + storageAllocated = this->storageAllocatedForRecording(); 1.419 + } 1.420 + 1.421 + if (fNotificationClient && 1.422 + storageAllocated != fPreviousStorageAllocated) { 1.423 + fPreviousStorageAllocated = storageAllocated; 1.424 + fNotificationClient->storageAllocatedForRecordingChanged(storageAllocated); 1.425 + } 1.426 +} 1.427 + 1.428 +SkCanvas* SkDeferredDevice::recordingCanvas() { 1.429 + return fRecordingCanvas; 1.430 +} 1.431 + 1.432 +SkImage* SkDeferredDevice::newImageSnapshot() { 1.433 + this->flush(); 1.434 + return fSurface ? fSurface->newImageSnapshot() : NULL; 1.435 +} 1.436 + 1.437 +int SkDeferredDevice::width() const { 1.438 + return immediateDevice()->width(); 1.439 +} 1.440 + 1.441 +int SkDeferredDevice::height() const { 1.442 + return immediateDevice()->height(); 1.443 +} 1.444 + 1.445 +SkBitmap::Config SkDeferredDevice::config() const { 1.446 + return immediateDevice()->config(); 1.447 +} 1.448 + 1.449 +bool SkDeferredDevice::isOpaque() const { 1.450 + return immediateDevice()->isOpaque(); 1.451 +} 1.452 + 1.453 +SkImageInfo SkDeferredDevice::imageInfo() const { 1.454 + return immediateDevice()->imageInfo(); 1.455 +} 1.456 + 1.457 +GrRenderTarget* SkDeferredDevice::accessRenderTarget() { 1.458 + this->flushPendingCommands(kNormal_PlaybackMode); 1.459 + return immediateDevice()->accessRenderTarget(); 1.460 +} 1.461 + 1.462 +void SkDeferredDevice::prepareForImmediatePixelWrite() { 1.463 + // The purpose of the following code is to make sure commands are flushed, that 1.464 + // aboutToDraw() is called and that notifyContentWillChange is called, without 1.465 + // calling anything redundantly. 1.466 + if (fPipeController.hasPendingCommands()) { 1.467 + this->flushPendingCommands(kNormal_PlaybackMode); 1.468 + } else { 1.469 + bool mustNotifyDirectly = !fCanDiscardCanvasContents; 1.470 + this->aboutToDraw(); 1.471 + if (mustNotifyDirectly) { 1.472 + fSurface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode); 1.473 + } 1.474 + } 1.475 + 1.476 + fImmediateCanvas->flush(); 1.477 +} 1.478 + 1.479 +#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG 1.480 +void SkDeferredDevice::writePixels(const SkBitmap& bitmap, int x, int y, 1.481 + SkCanvas::Config8888 config8888) { 1.482 + 1.483 + if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() && 1.484 + (y + bitmap.height()) >= height()) { 1.485 + this->skipPendingCommands(); 1.486 + } 1.487 + 1.488 + if (SkBitmap::kARGB_8888_Config == bitmap.config() && 1.489 + SkCanvas::kNative_Premul_Config8888 != config8888 && 1.490 + kPMColorAlias != config8888) { 1.491 + //Special case config: no deferral 1.492 + prepareForImmediatePixelWrite(); 1.493 + immediateDevice()->writePixels(bitmap, x, y, config8888); 1.494 + return; 1.495 + } 1.496 + 1.497 + SkPaint paint; 1.498 + paint.setXfermodeMode(SkXfermode::kSrc_Mode); 1.499 + if (shouldDrawImmediately(&bitmap, NULL, getBitmapSizeThreshold())) { 1.500 + prepareForImmediatePixelWrite(); 1.501 + fImmediateCanvas->drawSprite(bitmap, x, y, &paint); 1.502 + } else { 1.503 + this->recordingCanvas()->drawSprite(bitmap, x, y, &paint); 1.504 + this->recordedDrawCommand(); 1.505 + 1.506 + } 1.507 +} 1.508 +#endif 1.509 + 1.510 +bool SkDeferredDevice::onWritePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, 1.511 + int x, int y) { 1.512 + SkASSERT(x >= 0 && y >= 0); 1.513 + SkASSERT(x + info.width() <= width()); 1.514 + SkASSERT(y + info.height() <= height()); 1.515 + 1.516 + this->flushPendingCommands(kNormal_PlaybackMode); 1.517 + 1.518 + const SkImageInfo deviceInfo = this->imageInfo(); 1.519 + if (info.width() == deviceInfo.width() && info.height() == deviceInfo.height()) { 1.520 + this->skipPendingCommands(); 1.521 + } 1.522 + 1.523 + this->prepareForImmediatePixelWrite(); 1.524 + return immediateDevice()->onWritePixels(info, pixels, rowBytes, x, y); 1.525 +} 1.526 + 1.527 +const SkBitmap& SkDeferredDevice::onAccessBitmap() { 1.528 + this->flushPendingCommands(kNormal_PlaybackMode); 1.529 + return immediateDevice()->accessBitmap(false); 1.530 +} 1.531 + 1.532 +SkBaseDevice* SkDeferredDevice::onCreateDevice(const SkImageInfo& info, Usage usage) { 1.533 + // Save layer usage not supported, and not required by SkDeferredCanvas. 1.534 + SkASSERT(usage != kSaveLayer_Usage); 1.535 + // Create a compatible non-deferred device. 1.536 + // We do not create a deferred device because we know the new device 1.537 + // will not be used with a deferred canvas (there is no API for that). 1.538 + // And connecting a SkDeferredDevice to non-deferred canvas can result 1.539 + // in unpredictable behavior. 1.540 + return immediateDevice()->createCompatibleDevice(info); 1.541 +} 1.542 + 1.543 +SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info) { 1.544 + return this->immediateDevice()->newSurface(info); 1.545 +} 1.546 + 1.547 +bool SkDeferredDevice::onReadPixels( 1.548 + const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) { 1.549 + this->flushPendingCommands(kNormal_PlaybackMode); 1.550 + return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap), 1.551 + x, y, config8888); 1.552 +} 1.553 + 1.554 +class AutoImmediateDrawIfNeeded { 1.555 +public: 1.556 + AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap, 1.557 + const SkPaint* paint) { 1.558 + this->init(canvas, bitmap, paint); 1.559 + } 1.560 + 1.561 + AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) { 1.562 + this->init(canvas, NULL, paint); 1.563 + } 1.564 + 1.565 + ~AutoImmediateDrawIfNeeded() { 1.566 + if (fCanvas) { 1.567 + fCanvas->setDeferredDrawing(true); 1.568 + } 1.569 + } 1.570 +private: 1.571 + void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint) 1.572 + { 1.573 + SkDeferredDevice* device = static_cast<SkDeferredDevice*>(canvas.getDevice()); 1.574 + if (canvas.isDeferredDrawing() && (NULL != device) && 1.575 + shouldDrawImmediately(bitmap, paint, device->getBitmapSizeThreshold())) { 1.576 + canvas.setDeferredDrawing(false); 1.577 + fCanvas = &canvas; 1.578 + } else { 1.579 + fCanvas = NULL; 1.580 + } 1.581 + } 1.582 + 1.583 + SkDeferredCanvas* fCanvas; 1.584 +}; 1.585 + 1.586 +SkDeferredCanvas* SkDeferredCanvas::Create(SkSurface* surface) { 1.587 + SkAutoTUnref<SkDeferredDevice> deferredDevice(SkNEW_ARGS(SkDeferredDevice, (surface))); 1.588 + return SkNEW_ARGS(SkDeferredCanvas, (deferredDevice)); 1.589 +} 1.590 + 1.591 +SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device) { 1.592 + this->init(); 1.593 +} 1.594 + 1.595 +void SkDeferredCanvas::init() { 1.596 + fDeferredDrawing = true; // On by default 1.597 +} 1.598 + 1.599 +void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) { 1.600 + this->validate(); 1.601 + this->getDeferredDevice()->setMaxRecordingStorage(maxStorage); 1.602 +} 1.603 + 1.604 +size_t SkDeferredCanvas::storageAllocatedForRecording() const { 1.605 + return this->getDeferredDevice()->storageAllocatedForRecording(); 1.606 +} 1.607 + 1.608 +size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) { 1.609 + return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree); 1.610 +} 1.611 + 1.612 +void SkDeferredCanvas::setBitmapSizeThreshold(size_t sizeThreshold) { 1.613 + SkDeferredDevice* deferredDevice = this->getDeferredDevice(); 1.614 + SkASSERT(deferredDevice); 1.615 + deferredDevice->setBitmapSizeThreshold(sizeThreshold); 1.616 +} 1.617 + 1.618 +void SkDeferredCanvas::recordedDrawCommand() { 1.619 + if (fDeferredDrawing) { 1.620 + this->getDeferredDevice()->recordedDrawCommand(); 1.621 + } 1.622 +} 1.623 + 1.624 +void SkDeferredCanvas::validate() const { 1.625 + SkASSERT(this->getDevice()); 1.626 +} 1.627 + 1.628 +SkCanvas* SkDeferredCanvas::drawingCanvas() const { 1.629 + this->validate(); 1.630 + return fDeferredDrawing ? this->getDeferredDevice()->recordingCanvas() : 1.631 + this->getDeferredDevice()->immediateCanvas(); 1.632 +} 1.633 + 1.634 +SkCanvas* SkDeferredCanvas::immediateCanvas() const { 1.635 + this->validate(); 1.636 + return this->getDeferredDevice()->immediateCanvas(); 1.637 +} 1.638 + 1.639 +SkDeferredDevice* SkDeferredCanvas::getDeferredDevice() const { 1.640 + return static_cast<SkDeferredDevice*>(this->getDevice()); 1.641 +} 1.642 + 1.643 +void SkDeferredCanvas::setDeferredDrawing(bool val) { 1.644 + this->validate(); // Must set device before calling this method 1.645 + if (val != fDeferredDrawing) { 1.646 + if (fDeferredDrawing) { 1.647 + // Going live. 1.648 + this->getDeferredDevice()->flushPendingCommands(kNormal_PlaybackMode); 1.649 + } 1.650 + fDeferredDrawing = val; 1.651 + } 1.652 +} 1.653 + 1.654 +bool SkDeferredCanvas::isDeferredDrawing() const { 1.655 + return fDeferredDrawing; 1.656 +} 1.657 + 1.658 +bool SkDeferredCanvas::isFreshFrame() const { 1.659 + return this->getDeferredDevice()->isFreshFrame(); 1.660 +} 1.661 + 1.662 +bool SkDeferredCanvas::hasPendingCommands() const { 1.663 + return this->getDeferredDevice()->hasPendingCommands(); 1.664 +} 1.665 + 1.666 +void SkDeferredCanvas::silentFlush() { 1.667 + if (fDeferredDrawing) { 1.668 + this->getDeferredDevice()->flushPendingCommands(kSilent_PlaybackMode); 1.669 + } 1.670 +} 1.671 + 1.672 +SkDeferredCanvas::~SkDeferredCanvas() { 1.673 +} 1.674 + 1.675 +SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) { 1.676 + SkDeferredDevice* deferredDevice = this->getDeferredDevice(); 1.677 + SkASSERT(NULL != deferredDevice); 1.678 + // By swapping the surface into the existing device, we preserve 1.679 + // all pending commands, which can help to seamlessly recover from 1.680 + // a lost accelerated graphics context. 1.681 + deferredDevice->setSurface(surface); 1.682 + return surface; 1.683 +} 1.684 + 1.685 +SkDeferredCanvas::NotificationClient* SkDeferredCanvas::setNotificationClient( 1.686 + NotificationClient* notificationClient) { 1.687 + 1.688 + SkDeferredDevice* deferredDevice = this->getDeferredDevice(); 1.689 + SkASSERT(deferredDevice); 1.690 + if (deferredDevice) { 1.691 + deferredDevice->setNotificationClient(notificationClient); 1.692 + } 1.693 + return notificationClient; 1.694 +} 1.695 + 1.696 +SkImage* SkDeferredCanvas::newImageSnapshot() { 1.697 + SkDeferredDevice* deferredDevice = this->getDeferredDevice(); 1.698 + SkASSERT(deferredDevice); 1.699 + return deferredDevice ? deferredDevice->newImageSnapshot() : NULL; 1.700 +} 1.701 + 1.702 +bool SkDeferredCanvas::isFullFrame(const SkRect* rect, 1.703 + const SkPaint* paint) const { 1.704 + SkCanvas* canvas = this->drawingCanvas(); 1.705 + SkISize canvasSize = this->getDeviceSize(); 1.706 + if (rect) { 1.707 + if (!canvas->getTotalMatrix().rectStaysRect()) { 1.708 + return false; // conservative 1.709 + } 1.710 + 1.711 + SkRect transformedRect; 1.712 + canvas->getTotalMatrix().mapRect(&transformedRect, *rect); 1.713 + 1.714 + if (paint) { 1.715 + SkPaint::Style paintStyle = paint->getStyle(); 1.716 + if (!(paintStyle == SkPaint::kFill_Style || 1.717 + paintStyle == SkPaint::kStrokeAndFill_Style)) { 1.718 + return false; 1.719 + } 1.720 + if (paint->getMaskFilter() || paint->getLooper() 1.721 + || paint->getPathEffect() || paint->getImageFilter()) { 1.722 + return false; // conservative 1.723 + } 1.724 + } 1.725 + 1.726 + // The following test holds with AA enabled, and is conservative 1.727 + // by a 0.5 pixel margin with AA disabled 1.728 + if (transformedRect.fLeft > SkIntToScalar(0) || 1.729 + transformedRect.fTop > SkIntToScalar(0) || 1.730 + transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) || 1.731 + transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) { 1.732 + return false; 1.733 + } 1.734 + } 1.735 + 1.736 + return this->getClipStack()->quickContains(SkRect::MakeXYWH(0, 0, 1.737 + SkIntToScalar(canvasSize.fWidth), SkIntToScalar(canvasSize.fHeight))); 1.738 +} 1.739 + 1.740 +void SkDeferredCanvas::willSave(SaveFlags flags) { 1.741 + this->drawingCanvas()->save(flags); 1.742 + this->recordedDrawCommand(); 1.743 + this->INHERITED::willSave(flags); 1.744 +} 1.745 + 1.746 +SkCanvas::SaveLayerStrategy SkDeferredCanvas::willSaveLayer(const SkRect* bounds, 1.747 + const SkPaint* paint, SaveFlags flags) { 1.748 + this->drawingCanvas()->saveLayer(bounds, paint, flags); 1.749 + this->recordedDrawCommand(); 1.750 + this->INHERITED::willSaveLayer(bounds, paint, flags); 1.751 + // No need for a full layer. 1.752 + return kNoLayer_SaveLayerStrategy; 1.753 +} 1.754 + 1.755 +void SkDeferredCanvas::willRestore() { 1.756 + this->drawingCanvas()->restore(); 1.757 + this->recordedDrawCommand(); 1.758 + this->INHERITED::willRestore(); 1.759 +} 1.760 + 1.761 +bool SkDeferredCanvas::isDrawingToLayer() const { 1.762 + return this->drawingCanvas()->isDrawingToLayer(); 1.763 +} 1.764 + 1.765 +void SkDeferredCanvas::didTranslate(SkScalar dx, SkScalar dy) { 1.766 + this->drawingCanvas()->translate(dx, dy); 1.767 + this->recordedDrawCommand(); 1.768 + this->INHERITED::didTranslate(dx, dy); 1.769 +} 1.770 + 1.771 +void SkDeferredCanvas::didScale(SkScalar sx, SkScalar sy) { 1.772 + this->drawingCanvas()->scale(sx, sy); 1.773 + this->recordedDrawCommand(); 1.774 + this->INHERITED::didScale(sx, sy); 1.775 +} 1.776 + 1.777 +void SkDeferredCanvas::didRotate(SkScalar degrees) { 1.778 + this->drawingCanvas()->rotate(degrees); 1.779 + this->recordedDrawCommand(); 1.780 + this->INHERITED::didRotate(degrees); 1.781 +} 1.782 + 1.783 +void SkDeferredCanvas::didSkew(SkScalar sx, SkScalar sy) { 1.784 + this->drawingCanvas()->skew(sx, sy); 1.785 + this->recordedDrawCommand(); 1.786 + this->INHERITED::didSkew(sx, sy); 1.787 +} 1.788 + 1.789 +void SkDeferredCanvas::didConcat(const SkMatrix& matrix) { 1.790 + this->drawingCanvas()->concat(matrix); 1.791 + this->recordedDrawCommand(); 1.792 + this->INHERITED::didConcat(matrix); 1.793 +} 1.794 + 1.795 +void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) { 1.796 + this->drawingCanvas()->setMatrix(matrix); 1.797 + this->recordedDrawCommand(); 1.798 + this->INHERITED::didSetMatrix(matrix); 1.799 +} 1.800 + 1.801 +void SkDeferredCanvas::onClipRect(const SkRect& rect, 1.802 + SkRegion::Op op, 1.803 + ClipEdgeStyle edgeStyle) { 1.804 + this->drawingCanvas()->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle); 1.805 + this->INHERITED::onClipRect(rect, op, edgeStyle); 1.806 + this->recordedDrawCommand(); 1.807 +} 1.808 + 1.809 +void SkDeferredCanvas::onClipRRect(const SkRRect& rrect, 1.810 + SkRegion::Op op, 1.811 + ClipEdgeStyle edgeStyle) { 1.812 + this->drawingCanvas()->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle); 1.813 + this->INHERITED::onClipRRect(rrect, op, edgeStyle); 1.814 + this->recordedDrawCommand(); 1.815 +} 1.816 + 1.817 +void SkDeferredCanvas::onClipPath(const SkPath& path, 1.818 + SkRegion::Op op, 1.819 + ClipEdgeStyle edgeStyle) { 1.820 + this->drawingCanvas()->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle); 1.821 + this->INHERITED::onClipPath(path, op, edgeStyle); 1.822 + this->recordedDrawCommand(); 1.823 +} 1.824 + 1.825 +void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { 1.826 + this->drawingCanvas()->clipRegion(deviceRgn, op); 1.827 + this->INHERITED::onClipRegion(deviceRgn, op); 1.828 + this->recordedDrawCommand(); 1.829 +} 1.830 + 1.831 +void SkDeferredCanvas::clear(SkColor color) { 1.832 + // purge pending commands 1.833 + if (fDeferredDrawing) { 1.834 + this->getDeferredDevice()->skipPendingCommands(); 1.835 + } 1.836 + 1.837 + this->drawingCanvas()->clear(color); 1.838 + this->recordedDrawCommand(); 1.839 +} 1.840 + 1.841 +void SkDeferredCanvas::drawPaint(const SkPaint& paint) { 1.842 + if (fDeferredDrawing && this->isFullFrame(NULL, &paint) && 1.843 + isPaintOpaque(&paint)) { 1.844 + this->getDeferredDevice()->skipPendingCommands(); 1.845 + } 1.846 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.847 + this->drawingCanvas()->drawPaint(paint); 1.848 + this->recordedDrawCommand(); 1.849 +} 1.850 + 1.851 +void SkDeferredCanvas::drawPoints(PointMode mode, size_t count, 1.852 + const SkPoint pts[], const SkPaint& paint) { 1.853 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.854 + this->drawingCanvas()->drawPoints(mode, count, pts, paint); 1.855 + this->recordedDrawCommand(); 1.856 +} 1.857 + 1.858 +void SkDeferredCanvas::drawOval(const SkRect& rect, const SkPaint& paint) { 1.859 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.860 + this->drawingCanvas()->drawOval(rect, paint); 1.861 + this->recordedDrawCommand(); 1.862 +} 1.863 + 1.864 +void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 1.865 + if (fDeferredDrawing && this->isFullFrame(&rect, &paint) && 1.866 + isPaintOpaque(&paint)) { 1.867 + this->getDeferredDevice()->skipPendingCommands(); 1.868 + } 1.869 + 1.870 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.871 + this->drawingCanvas()->drawRect(rect, paint); 1.872 + this->recordedDrawCommand(); 1.873 +} 1.874 + 1.875 +void SkDeferredCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1.876 + if (rrect.isRect()) { 1.877 + this->SkDeferredCanvas::drawRect(rrect.getBounds(), paint); 1.878 + } else if (rrect.isOval()) { 1.879 + this->SkDeferredCanvas::drawOval(rrect.getBounds(), paint); 1.880 + } else { 1.881 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.882 + this->drawingCanvas()->drawRRect(rrect, paint); 1.883 + this->recordedDrawCommand(); 1.884 + } 1.885 +} 1.886 + 1.887 +void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1.888 + const SkPaint& paint) { 1.889 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.890 + this->drawingCanvas()->drawDRRect(outer, inner, paint); 1.891 + this->recordedDrawCommand(); 1.892 +} 1.893 + 1.894 +void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1.895 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.896 + this->drawingCanvas()->drawPath(path, paint); 1.897 + this->recordedDrawCommand(); 1.898 +} 1.899 + 1.900 +void SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left, 1.901 + SkScalar top, const SkPaint* paint) { 1.902 + SkRect bitmapRect = SkRect::MakeXYWH(left, top, 1.903 + SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 1.904 + if (fDeferredDrawing && 1.905 + this->isFullFrame(&bitmapRect, paint) && 1.906 + isPaintOpaque(paint, &bitmap)) { 1.907 + this->getDeferredDevice()->skipPendingCommands(); 1.908 + } 1.909 + 1.910 + AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 1.911 + this->drawingCanvas()->drawBitmap(bitmap, left, top, paint); 1.912 + this->recordedDrawCommand(); 1.913 +} 1.914 + 1.915 +void SkDeferredCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, 1.916 + const SkRect* src, 1.917 + const SkRect& dst, 1.918 + const SkPaint* paint, 1.919 + DrawBitmapRectFlags flags) { 1.920 + if (fDeferredDrawing && 1.921 + this->isFullFrame(&dst, paint) && 1.922 + isPaintOpaque(paint, &bitmap)) { 1.923 + this->getDeferredDevice()->skipPendingCommands(); 1.924 + } 1.925 + 1.926 + AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 1.927 + this->drawingCanvas()->drawBitmapRectToRect(bitmap, src, dst, paint, flags); 1.928 + this->recordedDrawCommand(); 1.929 +} 1.930 + 1.931 + 1.932 +void SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap, 1.933 + const SkMatrix& m, 1.934 + const SkPaint* paint) { 1.935 + // TODO: reset recording canvas if paint+bitmap is opaque and clip rect 1.936 + // covers canvas entirely and transformed bitmap covers canvas entirely 1.937 + AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 1.938 + this->drawingCanvas()->drawBitmapMatrix(bitmap, m, paint); 1.939 + this->recordedDrawCommand(); 1.940 +} 1.941 + 1.942 +void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap, 1.943 + const SkIRect& center, const SkRect& dst, 1.944 + const SkPaint* paint) { 1.945 + // TODO: reset recording canvas if paint+bitmap is opaque and clip rect 1.946 + // covers canvas entirely and dst covers canvas entirely 1.947 + AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 1.948 + this->drawingCanvas()->drawBitmapNine(bitmap, center, dst, paint); 1.949 + this->recordedDrawCommand(); 1.950 +} 1.951 + 1.952 +void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, 1.953 + const SkPaint* paint) { 1.954 + SkRect bitmapRect = SkRect::MakeXYWH( 1.955 + SkIntToScalar(left), 1.956 + SkIntToScalar(top), 1.957 + SkIntToScalar(bitmap.width()), 1.958 + SkIntToScalar(bitmap.height())); 1.959 + if (fDeferredDrawing && 1.960 + this->isFullFrame(&bitmapRect, paint) && 1.961 + isPaintOpaque(paint, &bitmap)) { 1.962 + this->getDeferredDevice()->skipPendingCommands(); 1.963 + } 1.964 + 1.965 + AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint); 1.966 + this->drawingCanvas()->drawSprite(bitmap, left, top, paint); 1.967 + this->recordedDrawCommand(); 1.968 +} 1.969 + 1.970 +void SkDeferredCanvas::drawText(const void* text, size_t byteLength, 1.971 + SkScalar x, SkScalar y, const SkPaint& paint) { 1.972 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.973 + this->drawingCanvas()->drawText(text, byteLength, x, y, paint); 1.974 + this->recordedDrawCommand(); 1.975 +} 1.976 + 1.977 +void SkDeferredCanvas::drawPosText(const void* text, size_t byteLength, 1.978 + const SkPoint pos[], const SkPaint& paint) { 1.979 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.980 + this->drawingCanvas()->drawPosText(text, byteLength, pos, paint); 1.981 + this->recordedDrawCommand(); 1.982 +} 1.983 + 1.984 +void SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength, 1.985 + const SkScalar xpos[], SkScalar constY, 1.986 + const SkPaint& paint) { 1.987 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.988 + this->drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint); 1.989 + this->recordedDrawCommand(); 1.990 +} 1.991 + 1.992 +void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength, 1.993 + const SkPath& path, 1.994 + const SkMatrix* matrix, 1.995 + const SkPaint& paint) { 1.996 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.997 + this->drawingCanvas()->drawTextOnPath(text, byteLength, path, matrix, paint); 1.998 + this->recordedDrawCommand(); 1.999 +} 1.1000 + 1.1001 +void SkDeferredCanvas::drawPicture(SkPicture& picture) { 1.1002 + this->drawingCanvas()->drawPicture(picture); 1.1003 + this->recordedDrawCommand(); 1.1004 +} 1.1005 + 1.1006 +void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount, 1.1007 + const SkPoint vertices[], 1.1008 + const SkPoint texs[], 1.1009 + const SkColor colors[], SkXfermode* xmode, 1.1010 + const uint16_t indices[], int indexCount, 1.1011 + const SkPaint& paint) { 1.1012 + AutoImmediateDrawIfNeeded autoDraw(*this, &paint); 1.1013 + this->drawingCanvas()->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1.1014 + indices, indexCount, paint); 1.1015 + this->recordedDrawCommand(); 1.1016 +} 1.1017 + 1.1018 +SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) { 1.1019 + this->drawingCanvas()->setBounder(bounder); 1.1020 + this->INHERITED::setBounder(bounder); 1.1021 + this->recordedDrawCommand(); 1.1022 + return bounder; 1.1023 +} 1.1024 + 1.1025 +SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) { 1.1026 + this->drawingCanvas()->setDrawFilter(filter); 1.1027 + this->INHERITED::setDrawFilter(filter); 1.1028 + this->recordedDrawCommand(); 1.1029 + return filter; 1.1030 +} 1.1031 + 1.1032 +SkCanvas* SkDeferredCanvas::canvasForDrawIter() { 1.1033 + return this->drawingCanvas(); 1.1034 +}