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