OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2013 Google Inc. | 3 * Copyright 2013 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkDeferredCanvas.h" | 9 #include "SkDeferredCanvas.h" |
10 | 10 |
11 #include "SkChunkAlloc.h" | 11 #include "SkChunkAlloc.h" |
12 #include "SkColorFilter.h" | 12 #include "SkColorFilter.h" |
13 #include "SkDevice.h" | 13 #include "SkDevice.h" |
14 #include "SkDrawFilter.h" | 14 #include "SkDrawFilter.h" |
15 #include "SkGPipe.h" | 15 #include "SkGPipe.h" |
16 #include "SkPaint.h" | 16 #include "SkPaint.h" |
17 #include "SkPaintPriv.h" | 17 #include "SkPaintPriv.h" |
18 #include "SkRRect.h" | 18 #include "SkRRect.h" |
19 #include "SkShader.h" | 19 #include "SkShader.h" |
| 20 #include "SkSurface.h" |
20 | 21 |
21 enum { | 22 enum { |
22 // Deferred canvas will auto-flush when recording reaches this limit | 23 // Deferred canvas will auto-flush when recording reaches this limit |
23 kDefaultMaxRecordingStorageBytes = 64*1024*1024, | 24 kDefaultMaxRecordingStorageBytes = 64*1024*1024, |
24 kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature | 25 kDeferredCanvasBitmapSizeThreshold = ~0U, // Disables this feature |
25 }; | 26 }; |
26 | 27 |
27 enum PlaybackMode { | 28 enum PlaybackMode { |
28 kNormal_PlaybackMode, | 29 kNormal_PlaybackMode, |
29 kSilent_PlaybackMode, | 30 kSilent_PlaybackMode, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 132 |
132 // Release all allocated blocks | 133 // Release all allocated blocks |
133 fAllocator.reset(); | 134 fAllocator.reset(); |
134 } | 135 } |
135 | 136 |
136 //----------------------------------------------------------------------------- | 137 //----------------------------------------------------------------------------- |
137 // DeferredDevice | 138 // DeferredDevice |
138 //----------------------------------------------------------------------------- | 139 //----------------------------------------------------------------------------- |
139 class DeferredDevice : public SkDevice { | 140 class DeferredDevice : public SkDevice { |
140 public: | 141 public: |
141 DeferredDevice(SkDevice* immediateDevice, | 142 explicit DeferredDevice(SkDevice* immediateDevice); |
142 SkDeferredCanvas::NotificationClient* notificationClient = NULL); | 143 explicit DeferredDevice(SkSurface* surface); |
143 ~DeferredDevice(); | 144 ~DeferredDevice(); |
144 | 145 |
145 void setNotificationClient(SkDeferredCanvas::NotificationClient* notificatio
nClient); | 146 void setNotificationClient(SkDeferredCanvas::NotificationClient* notificatio
nClient); |
146 SkCanvas* recordingCanvas(); | 147 SkCanvas* recordingCanvas(); |
147 SkCanvas* immediateCanvas() const {return fImmediateCanvas;} | 148 SkCanvas* immediateCanvas() const {return fImmediateCanvas;} |
148 SkDevice* immediateDevice() const {return fImmediateDevice;} | 149 SkDevice* immediateDevice() const {return fImmediateDevice;} |
| 150 SkImage* newImageShapshot(); |
149 bool isFreshFrame(); | 151 bool isFreshFrame(); |
150 bool hasPendingCommands(); | 152 bool hasPendingCommands(); |
151 size_t storageAllocatedForRecording() const; | 153 size_t storageAllocatedForRecording() const; |
152 size_t freeMemoryIfPossible(size_t bytesToFree); | 154 size_t freeMemoryIfPossible(size_t bytesToFree); |
153 size_t getBitmapSizeThreshold() const; | 155 size_t getBitmapSizeThreshold() const; |
154 void setBitmapSizeThreshold(size_t sizeThreshold); | 156 void setBitmapSizeThreshold(size_t sizeThreshold); |
155 void flushPendingCommands(PlaybackMode); | 157 void flushPendingCommands(PlaybackMode); |
156 void skipPendingCommands(); | 158 void skipPendingCommands(); |
157 void setMaxRecordingStorage(size_t); | 159 void setMaxRecordingStorage(size_t); |
158 void recordedDrawCommand(); | 160 void recordedDrawCommand(); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 SkXfermode* xmode, const uint16_t indices[], | 232 SkXfermode* xmode, const uint16_t indices[], |
231 int indexCount, const SkPaint& paint) | 233 int indexCount, const SkPaint& paint) |
232 {SkASSERT(0);} | 234 {SkASSERT(0);} |
233 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, | 235 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y, |
234 const SkPaint&) | 236 const SkPaint&) |
235 {SkASSERT(0);} | 237 {SkASSERT(0);} |
236 private: | 238 private: |
237 virtual void flush(); | 239 virtual void flush(); |
238 | 240 |
239 void beginRecording(); | 241 void beginRecording(); |
| 242 void init(); |
240 | 243 |
241 DeferredPipeController fPipeController; | 244 DeferredPipeController fPipeController; |
242 SkGPipeWriter fPipeWriter; | 245 SkGPipeWriter fPipeWriter; |
243 SkDevice* fImmediateDevice; | 246 SkDevice* fImmediateDevice; |
244 SkCanvas* fImmediateCanvas; | 247 SkCanvas* fImmediateCanvas; |
245 SkCanvas* fRecordingCanvas; | 248 SkCanvas* fRecordingCanvas; |
| 249 SkSurface* fSurface; |
246 SkDeferredCanvas::NotificationClient* fNotificationClient; | 250 SkDeferredCanvas::NotificationClient* fNotificationClient; |
247 bool fFreshFrame; | 251 bool fFreshFrame; |
| 252 bool fNextFlushOverwritesContents; |
248 size_t fMaxRecordingStorageBytes; | 253 size_t fMaxRecordingStorageBytes; |
249 size_t fPreviousStorageAllocated; | 254 size_t fPreviousStorageAllocated; |
250 size_t fBitmapSizeThreshold; | 255 size_t fBitmapSizeThreshold; |
251 }; | 256 }; |
252 | 257 |
253 DeferredDevice::DeferredDevice( | 258 DeferredDevice::DeferredDevice(SkDevice* immediateDevice) |
254 SkDevice* immediateDevice, SkDeferredCanvas::NotificationClient* notificatio
nClient) : | 259 : SkDevice(SkBitmap::kNo_Config, |
255 SkDevice(SkBitmap::kNo_Config, | 260 immediateDevice->width(), immediateDevice->height(), |
256 immediateDevice->width(), immediateDevice->height(), | 261 immediateDevice->isOpaque(), |
257 immediateDevice->isOpaque(), | 262 immediateDevice->getDeviceProperties()) { |
258 immediateDevice->getDeviceProperties()) | 263 fSurface = NULL; |
259 , fRecordingCanvas(NULL) | 264 fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas |
260 , fFreshFrame(true) | 265 fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice)); |
261 , fPreviousStorageAllocated(0) | 266 this->init(); |
262 , fBitmapSizeThreshold(kDeferredCanvasBitmapSizeThreshold){ | 267 } |
263 | 268 |
| 269 DeferredDevice::DeferredDevice(SkSurface* surface) |
| 270 : SkDevice(SkBitmap::kNo_Config, |
| 271 surface->getCanvas()->getDevice()->width(), |
| 272 surface->getCanvas()->getDevice()->height(), |
| 273 surface->getCanvas()->getDevice()->isOpaque(), |
| 274 surface->getCanvas()->getDevice()->getDeviceProperties()) { |
264 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; | 275 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; |
265 fNotificationClient = notificationClient; | 276 fNotificationClient = NULL; |
266 fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas | 277 fImmediateCanvas = surface->getCanvas(); |
267 fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice)); | 278 SkSafeRef(fImmediateCanvas); |
| 279 fSurface = surface; |
| 280 SkSafeRef(fSurface); |
| 281 fImmediateDevice = fImmediateCanvas->getDevice(); // ref counted via fImmed
iateCanvas |
| 282 this->init(); |
| 283 } |
| 284 |
| 285 void DeferredDevice::init() { |
| 286 fRecordingCanvas = NULL; |
| 287 fFreshFrame = true; |
| 288 fPreviousStorageAllocated = 0; |
| 289 fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold; |
| 290 fNextFlushOverwritesContents = false; |
| 291 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes; |
| 292 fNotificationClient = NULL; |
268 fPipeController.setPlaybackCanvas(fImmediateCanvas); | 293 fPipeController.setPlaybackCanvas(fImmediateCanvas); |
269 this->beginRecording(); | 294 this->beginRecording(); |
270 } | 295 } |
271 | 296 |
272 DeferredDevice::~DeferredDevice() { | 297 DeferredDevice::~DeferredDevice() { |
273 this->flushPendingCommands(kSilent_PlaybackMode); | 298 this->flushPendingCommands(kSilent_PlaybackMode); |
274 SkSafeUnref(fImmediateCanvas); | 299 SkSafeUnref(fImmediateCanvas); |
| 300 SkSafeUnref(fSurface); |
275 } | 301 } |
276 | 302 |
277 void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) { | 303 void DeferredDevice::setMaxRecordingStorage(size_t maxStorage) { |
278 fMaxRecordingStorageBytes = maxStorage; | 304 fMaxRecordingStorageBytes = maxStorage; |
279 this->recordingCanvas(); // Accessing the recording canvas applies the new l
imit. | 305 this->recordingCanvas(); // Accessing the recording canvas applies the new l
imit. |
280 } | 306 } |
281 | 307 |
282 void DeferredDevice::beginRecording() { | 308 void DeferredDevice::beginRecording() { |
283 SkASSERT(NULL == fRecordingCanvas); | 309 SkASSERT(NULL == fRecordingCanvas); |
284 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0, | 310 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0, |
285 fImmediateDevice->width(), fImmediateDevice->height()); | 311 fImmediateDevice->width(), fImmediateDevice->height()); |
286 } | 312 } |
287 | 313 |
288 void DeferredDevice::setNotificationClient( | 314 void DeferredDevice::setNotificationClient( |
289 SkDeferredCanvas::NotificationClient* notificationClient) { | 315 SkDeferredCanvas::NotificationClient* notificationClient) { |
290 fNotificationClient = notificationClient; | 316 fNotificationClient = notificationClient; |
291 } | 317 } |
292 | 318 |
293 void DeferredDevice::skipPendingCommands() { | 319 void DeferredDevice::skipPendingCommands() { |
294 if (!fRecordingCanvas->isDrawingToLayer() && fPipeController.hasPendingComma
nds()) { | 320 if (!fRecordingCanvas->isDrawingToLayer() && fPipeController.hasPendingComma
nds()) { |
295 fFreshFrame = true; | 321 fFreshFrame = true; |
296 flushPendingCommands(kSilent_PlaybackMode); | 322 flushPendingCommands(kSilent_PlaybackMode); |
297 if (fNotificationClient) { | 323 if (fNotificationClient) { |
298 fNotificationClient->skippedPendingDrawCommands(); | 324 fNotificationClient->skippedPendingDrawCommands(); |
299 } | 325 } |
300 } | 326 } |
| 327 fNextFlushOverwritesContents = true; |
301 } | 328 } |
302 | 329 |
303 bool DeferredDevice::isFreshFrame() { | 330 bool DeferredDevice::isFreshFrame() { |
304 bool ret = fFreshFrame; | 331 bool ret = fFreshFrame; |
305 fFreshFrame = false; | 332 fFreshFrame = false; |
306 return ret; | 333 return ret; |
307 } | 334 } |
308 | 335 |
309 bool DeferredDevice::hasPendingCommands() { | 336 bool DeferredDevice::hasPendingCommands() { |
310 return fPipeController.hasPendingCommands(); | 337 return fPipeController.hasPendingCommands(); |
311 } | 338 } |
312 | 339 |
313 void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) { | 340 void DeferredDevice::flushPendingCommands(PlaybackMode playbackMode) { |
314 if (!fPipeController.hasPendingCommands()) { | 341 if (!fPipeController.hasPendingCommands()) { |
315 return; | 342 return; |
316 } | 343 } |
317 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { | 344 if (playbackMode == kNormal_PlaybackMode) { |
318 fNotificationClient->prepareForDraw(); | 345 if (NULL != fNotificationClient) { |
| 346 fNotificationClient->prepareForDraw(); |
| 347 } |
| 348 if (NULL != fSurface) { |
| 349 // Preempt SkCanvas::predrawNotify because we know something it does
n't |
| 350 fSurface->notifyContentChanged(fNextFlushOverwritesContents); |
| 351 } |
319 } | 352 } |
320 fPipeWriter.flushRecording(true); | 353 fPipeWriter.flushRecording(true); |
321 fPipeController.playback(kSilent_PlaybackMode == playbackMode); | 354 fPipeController.playback(kSilent_PlaybackMode == playbackMode); |
322 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { | 355 if (playbackMode == kNormal_PlaybackMode && fNotificationClient) { |
323 fNotificationClient->flushedDrawCommands(); | 356 fNotificationClient->flushedDrawCommands(); |
324 } | 357 } |
325 fPreviousStorageAllocated = storageAllocatedForRecording(); | 358 fPreviousStorageAllocated = storageAllocatedForRecording(); |
| 359 fNextFlushOverwritesContents = false; |
326 } | 360 } |
327 | 361 |
328 void DeferredDevice::flush() { | 362 void DeferredDevice::flush() { |
329 this->flushPendingCommands(kNormal_PlaybackMode); | 363 this->flushPendingCommands(kNormal_PlaybackMode); |
330 fImmediateCanvas->flush(); | 364 fImmediateCanvas->flush(); |
331 } | 365 } |
332 | 366 |
333 size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) { | 367 size_t DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) { |
334 size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree); | 368 size_t val = fPipeWriter.freeMemoryIfPossible(bytesToFree); |
335 fPreviousStorageAllocated = storageAllocatedForRecording(); | 369 fPreviousStorageAllocated = storageAllocatedForRecording(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 storageAllocated != fPreviousStorageAllocated) { | 403 storageAllocated != fPreviousStorageAllocated) { |
370 fPreviousStorageAllocated = storageAllocated; | 404 fPreviousStorageAllocated = storageAllocated; |
371 fNotificationClient->storageAllocatedForRecordingChanged(storageAllocate
d); | 405 fNotificationClient->storageAllocatedForRecordingChanged(storageAllocate
d); |
372 } | 406 } |
373 } | 407 } |
374 | 408 |
375 SkCanvas* DeferredDevice::recordingCanvas() { | 409 SkCanvas* DeferredDevice::recordingCanvas() { |
376 return fRecordingCanvas; | 410 return fRecordingCanvas; |
377 } | 411 } |
378 | 412 |
| 413 SkImage* DeferredDevice::newImageShapshot() { |
| 414 this->flush(); |
| 415 return fSurface ? fSurface->newImageShapshot() : NULL; |
| 416 } |
| 417 |
379 uint32_t DeferredDevice::getDeviceCapabilities() { | 418 uint32_t DeferredDevice::getDeviceCapabilities() { |
380 return fImmediateDevice->getDeviceCapabilities(); | 419 return fImmediateDevice->getDeviceCapabilities(); |
381 } | 420 } |
382 | 421 |
383 int DeferredDevice::width() const { | 422 int DeferredDevice::width() const { |
384 return fImmediateDevice->width(); | 423 return fImmediateDevice->width(); |
385 } | 424 } |
386 | 425 |
387 int DeferredDevice::height() const { | 426 int DeferredDevice::height() const { |
388 return fImmediateDevice->height(); | 427 return fImmediateDevice->height(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 SkDevice* DeferredDevice::onCreateCompatibleDevice( | 469 SkDevice* DeferredDevice::onCreateCompatibleDevice( |
431 SkBitmap::Config config, int width, int height, bool isOpaque, | 470 SkBitmap::Config config, int width, int height, bool isOpaque, |
432 Usage usage) { | 471 Usage usage) { |
433 | 472 |
434 // Save layer usage not supported, and not required by SkDeferredCanvas. | 473 // Save layer usage not supported, and not required by SkDeferredCanvas. |
435 SkASSERT(usage != kSaveLayer_Usage); | 474 SkASSERT(usage != kSaveLayer_Usage); |
436 // Create a compatible non-deferred device. | 475 // Create a compatible non-deferred device. |
437 SkAutoTUnref<SkDevice> compatibleDevice | 476 SkAutoTUnref<SkDevice> compatibleDevice |
438 (fImmediateDevice->createCompatibleDevice(config, width, height, | 477 (fImmediateDevice->createCompatibleDevice(config, width, height, |
439 isOpaque)); | 478 isOpaque)); |
440 return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fNotificationClient)); | 479 DeferredDevice* device = SkNEW_ARGS(DeferredDevice, (compatibleDevice)); |
| 480 device->setNotificationClient(fNotificationClient); |
| 481 return device; |
441 } | 482 } |
442 | 483 |
443 bool DeferredDevice::onReadPixels( | 484 bool DeferredDevice::onReadPixels( |
444 const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) { | 485 const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) { |
445 this->flushPendingCommands(kNormal_PlaybackMode); | 486 this->flushPendingCommands(kNormal_PlaybackMode); |
446 return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap), | 487 return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap), |
447 x, y, config8888); | 488 x, y, config8888); |
448 } | 489 } |
449 | 490 |
450 class AutoImmediateDrawIfNeeded { | 491 class AutoImmediateDrawIfNeeded { |
(...skipping 30 matching lines...) Expand all Loading... |
481 | 522 |
482 SkDeferredCanvas::SkDeferredCanvas() { | 523 SkDeferredCanvas::SkDeferredCanvas() { |
483 this->init(); | 524 this->init(); |
484 } | 525 } |
485 | 526 |
486 SkDeferredCanvas::SkDeferredCanvas(SkDevice* device) { | 527 SkDeferredCanvas::SkDeferredCanvas(SkDevice* device) { |
487 this->init(); | 528 this->init(); |
488 this->setDevice(device); | 529 this->setDevice(device); |
489 } | 530 } |
490 | 531 |
| 532 SkDeferredCanvas::SkDeferredCanvas(SkSurface* surface) { |
| 533 this->init(); |
| 534 this->INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (surface)))->unref(); |
| 535 } |
| 536 |
491 void SkDeferredCanvas::init() { | 537 void SkDeferredCanvas::init() { |
492 fDeferredDrawing = true; // On by default | 538 fDeferredDrawing = true; // On by default |
493 } | 539 } |
494 | 540 |
495 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) { | 541 void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) { |
496 this->validate(); | 542 this->validate(); |
497 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage); | 543 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage); |
498 } | 544 } |
499 | 545 |
500 size_t SkDeferredCanvas::storageAllocatedForRecording() const { | 546 size_t SkDeferredCanvas::storageAllocatedForRecording() const { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 NotificationClient* notificationClient) { | 623 NotificationClient* notificationClient) { |
578 | 624 |
579 DeferredDevice* deferredDevice = this->getDeferredDevice(); | 625 DeferredDevice* deferredDevice = this->getDeferredDevice(); |
580 SkASSERT(deferredDevice); | 626 SkASSERT(deferredDevice); |
581 if (deferredDevice) { | 627 if (deferredDevice) { |
582 deferredDevice->setNotificationClient(notificationClient); | 628 deferredDevice->setNotificationClient(notificationClient); |
583 } | 629 } |
584 return notificationClient; | 630 return notificationClient; |
585 } | 631 } |
586 | 632 |
| 633 SkImage* SkDeferredCanvas::newImageShapshot() { |
| 634 DeferredDevice* deferredDevice = this->getDeferredDevice(); |
| 635 SkASSERT(deferredDevice); |
| 636 return deferredDevice ? deferredDevice->newImageShapshot() : NULL; |
| 637 } |
| 638 |
587 bool SkDeferredCanvas::isFullFrame(const SkRect* rect, | 639 bool SkDeferredCanvas::isFullFrame(const SkRect* rect, |
588 const SkPaint* paint) const { | 640 const SkPaint* paint) const { |
589 SkCanvas* canvas = this->drawingCanvas(); | 641 SkCanvas* canvas = this->drawingCanvas(); |
590 SkISize canvasSize = this->getDeviceSize(); | 642 SkISize canvasSize = this->getDeviceSize(); |
591 if (rect) { | 643 if (rect) { |
592 if (!canvas->getTotalMatrix().rectStaysRect()) { | 644 if (!canvas->getTotalMatrix().rectStaysRect()) { |
593 return false; // conservative | 645 return false; // conservative |
594 } | 646 } |
595 | 647 |
596 SkRect transformedRect; | 648 SkRect transformedRect; |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) { | 967 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) { |
916 this->drawingCanvas()->setDrawFilter(filter); | 968 this->drawingCanvas()->setDrawFilter(filter); |
917 this->INHERITED::setDrawFilter(filter); | 969 this->INHERITED::setDrawFilter(filter); |
918 this->recordedDrawCommand(); | 970 this->recordedDrawCommand(); |
919 return filter; | 971 return filter; |
920 } | 972 } |
921 | 973 |
922 SkCanvas* SkDeferredCanvas::canvasForDrawIter() { | 974 SkCanvas* SkDeferredCanvas::canvasForDrawIter() { |
923 return this->drawingCanvas(); | 975 return this->drawingCanvas(); |
924 } | 976 } |
OLD | NEW |