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