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