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