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