gfx/skia/trunk/src/utils/SkDeferredCanvas.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial