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