blob: acac47cf06f9badb603ba2602fddd733873baa83 [file] [log] [blame]
junov@google.com4370aed2012-01-18 16:21:08 +00001
2/*
junov@chromium.org10f7f972012-07-31 21:01:51 +00003 * Copyright 2012 Google Inc.
junov@google.com4370aed2012-01-18 16:21:08 +00004 *
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 "SkPaint.h"
12#include "SkShader.h"
13#include "SkColorFilter.h"
14#include "SkDrawFilter.h"
15
reed@google.com563a3b42012-06-26 19:24:50 +000016SK_DEFINE_INST_COUNT(SkDeferredCanvas::DeviceContext)
17
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000018enum {
19 // Deferred canvas will auto-flush when recording reaches this limit
20 kDefaultMaxRecordingStorageBytes = 64*1024*1024,
21};
22
junov@google.com4370aed2012-01-18 16:21:08 +000023namespace {
junov@chromium.org10f7f972012-07-31 21:01:51 +000024bool shouldDrawImmediately(const SkBitmap* bitmap, const SkPaint* paint) {
25 if (bitmap && bitmap->getTexture() && !bitmap->isImmutable()) {
26 return true;
27 }
28 if (paint) {
29 SkShader* shader = paint->getShader();
30 // Here we detect the case where the shader is an SkBitmapProcShader
31 // with a gpu texture attached. Checking this without RTTI
32 // requires making the assumption that only gradient shaders
33 // and SkBitmapProcShader implement asABitmap(). The following
34 // code may need to be revised if that assumption is ever broken.
35 if (shader && !shader->asAGradient(NULL)) {
36 SkBitmap bm;
37 if (shader->asABitmap(&bm, NULL, NULL) &&
38 NULL != bm.getTexture()) {
39 return true;
40 }
41 }
42 }
43 return false;
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000044}
45}
46
47class AutoImmediateDrawIfNeeded {
48public:
junov@chromium.org10f7f972012-07-31 21:01:51 +000049 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkBitmap* bitmap,
50 const SkPaint* paint) {
51 this->init(canvas, bitmap, paint);
52 }
53
54 AutoImmediateDrawIfNeeded(SkDeferredCanvas& canvas, const SkPaint* paint) {
55 this->init(canvas, NULL, paint);
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000056 }
57
58 ~AutoImmediateDrawIfNeeded() {
59 if (fCanvas) {
60 fCanvas->setDeferredDrawing(true);
61 }
62 }
63private:
junov@chromium.org10f7f972012-07-31 21:01:51 +000064 void init(SkDeferredCanvas& canvas, const SkBitmap* bitmap, const SkPaint* paint)
65 {
66 if (canvas.isDeferredDrawing() && shouldDrawImmediately(bitmap, paint)) {
67 canvas.setDeferredDrawing(false);
68 fCanvas = &canvas;
69 } else {
70 fCanvas = NULL;
71 }
72 }
73
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000074 SkDeferredCanvas* fCanvas;
75};
76
77namespace {
junov@google.com4370aed2012-01-18 16:21:08 +000078
junov@chromium.orgc16ca922012-02-24 22:06:27 +000079bool isPaintOpaque(const SkPaint* paint,
80 const SkBitmap* bmpReplacesShader = NULL) {
junov@google.com4370aed2012-01-18 16:21:08 +000081 // TODO: SkXfermode should have a virtual isOpaque method, which would
82 // make it possible to test modes that do not have a Coeff representation.
junov@chromium.org87f982c2012-02-23 21:34:34 +000083
84 if (!paint) {
85 return bmpReplacesShader ? bmpReplacesShader->isOpaque() : true;
86 }
87
junov@google.com4370aed2012-01-18 16:21:08 +000088 SkXfermode::Coeff srcCoeff, dstCoeff;
junov@chromium.org87f982c2012-02-23 21:34:34 +000089 if (SkXfermode::AsCoeff(paint->getXfermode(), &srcCoeff, &dstCoeff)){
junov@google.com4370aed2012-01-18 16:21:08 +000090 switch (dstCoeff) {
91 case SkXfermode::kZero_Coeff:
92 return true;
93 case SkXfermode::kISA_Coeff:
junov@chromium.org87f982c2012-02-23 21:34:34 +000094 if (paint->getAlpha() != 255) {
junov@google.com4370aed2012-01-18 16:21:08 +000095 break;
96 }
97 if (bmpReplacesShader) {
98 if (!bmpReplacesShader->isOpaque()) {
99 break;
100 }
junov@chromium.org87f982c2012-02-23 21:34:34 +0000101 } else if (paint->getShader() && !paint->getShader()->isOpaque()) {
junov@google.com4370aed2012-01-18 16:21:08 +0000102 break;
103 }
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000104 if (paint->getColorFilter() &&
105 ((paint->getColorFilter()->getFlags() &
junov@google.com4370aed2012-01-18 16:21:08 +0000106 SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
107 break;
108 }
109 return true;
110 case SkXfermode::kSA_Coeff:
junov@chromium.org87f982c2012-02-23 21:34:34 +0000111 if (paint->getAlpha() != 0) {
junov@google.com4370aed2012-01-18 16:21:08 +0000112 break;
113 }
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000114 if (paint->getColorFilter() &&
115 ((paint->getColorFilter()->getFlags() &
junov@google.com4370aed2012-01-18 16:21:08 +0000116 SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
117 break;
118 }
119 return true;
120 case SkXfermode::kSC_Coeff:
junov@chromium.org87f982c2012-02-23 21:34:34 +0000121 if (paint->getColor() != 0) { // all components must be 0
junov@google.com4370aed2012-01-18 16:21:08 +0000122 break;
123 }
junov@chromium.org87f982c2012-02-23 21:34:34 +0000124 if (bmpReplacesShader || paint->getShader()) {
junov@google.com4370aed2012-01-18 16:21:08 +0000125 break;
126 }
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000127 if (paint->getColorFilter() && (
128 (paint->getColorFilter()->getFlags() &
junov@google.com4370aed2012-01-18 16:21:08 +0000129 SkColorFilter::kAlphaUnchanged_Flag) == 0)) {
130 break;
131 }
132 return true;
133 default:
134 break;
135 }
136 }
137 return false;
138}
139
140} // unnamed namespace
141
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000142SkDeferredCanvas::SkDeferredCanvas() {
junov@google.com4370aed2012-01-18 16:21:08 +0000143 init();
144}
145
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000146SkDeferredCanvas::SkDeferredCanvas(SkDevice* device) {
junov@google.com4370aed2012-01-18 16:21:08 +0000147 init();
148 setDevice(device);
149}
150
151SkDeferredCanvas::SkDeferredCanvas(SkDevice* device,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000152 DeviceContext* deviceContext) {
junov@google.com4370aed2012-01-18 16:21:08 +0000153 init();
154 setDevice(device);
155 setDeviceContext(deviceContext);
156}
157
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000158void SkDeferredCanvas::init() {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000159 fDeferredDrawing = true; // On by default
junov@google.com4370aed2012-01-18 16:21:08 +0000160}
161
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000162void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) {
163 validate();
164 this->getDeferredDevice()->setMaxRecordingStorage(maxStorage);
165}
166
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000167size_t SkDeferredCanvas::storageAllocatedForRecording() const {
168 return this->getDeferredDevice()->storageAllocatedForRecording();
169}
170
171size_t SkDeferredCanvas::freeMemoryIfPossible(size_t bytesToFree) {
172#if SK_DEFERRED_CANVAS_USES_GPIPE
173 return this->getDeferredDevice()->freeMemoryIfPossible(bytesToFree);
174#else
175 return 0;
176#endif
177}
178
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000179void SkDeferredCanvas::validate() const {
junov@google.com4370aed2012-01-18 16:21:08 +0000180 SkASSERT(getDevice());
junov@google.com4370aed2012-01-18 16:21:08 +0000181}
182
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000183SkCanvas* SkDeferredCanvas::drawingCanvas() const {
184 validate();
185 return fDeferredDrawing ? getDeferredDevice()->recordingCanvas() :
186 getDeferredDevice()->immediateCanvas();
187}
188
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000189SkDeferredCanvas::DeferredDevice* SkDeferredCanvas::getDeferredDevice() const {
junov@google.com4370aed2012-01-18 16:21:08 +0000190 return static_cast<SkDeferredCanvas::DeferredDevice*>(getDevice());
191}
192
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000193void SkDeferredCanvas::setDeferredDrawing(bool val) {
junov@google.com4370aed2012-01-18 16:21:08 +0000194 validate(); // Must set device before calling this method
junov@google.com4370aed2012-01-18 16:21:08 +0000195 if (val != fDeferredDrawing) {
196 if (fDeferredDrawing) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000197 // Going live.
junov@google.com4370aed2012-01-18 16:21:08 +0000198 getDeferredDevice()->flushPending();
199 }
200 fDeferredDrawing = val;
201 }
202}
203
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000204bool SkDeferredCanvas::isDeferredDrawing() {
205 return fDeferredDrawing;
206}
207
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000208SkDeferredCanvas::~SkDeferredCanvas() {
junov@google.com4370aed2012-01-18 16:21:08 +0000209}
210
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000211SkDevice* SkDeferredCanvas::setDevice(SkDevice* device) {
junov@google.com4370aed2012-01-18 16:21:08 +0000212 INHERITED::setDevice(SkNEW_ARGS(DeferredDevice, (device)))->unref();
213 return device;
214}
215
216SkDeferredCanvas::DeviceContext* SkDeferredCanvas::setDeviceContext(
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000217 DeviceContext* deviceContext) {
218
junov@google.com4370aed2012-01-18 16:21:08 +0000219 DeferredDevice* deferredDevice = getDeferredDevice();
220 SkASSERT(deferredDevice);
221 if (deferredDevice) {
222 deferredDevice->setDeviceContext(deviceContext);
223 }
224 return deviceContext;
225}
226
227bool SkDeferredCanvas::isFullFrame(const SkRect* rect,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000228 const SkPaint* paint) const {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000229 SkCanvas* canvas = drawingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000230 SkISize canvasSize = getDeviceSize();
231 if (rect) {
232 if (!canvas->getTotalMatrix().rectStaysRect()) {
233 return false; // conservative
234 }
235
236 SkRect transformedRect;
237 canvas->getTotalMatrix().mapRect(&transformedRect, *rect);
238
239 if (paint) {
240 SkPaint::Style paintStyle = paint->getStyle();
241 if (!(paintStyle == SkPaint::kFill_Style ||
242 paintStyle == SkPaint::kStrokeAndFill_Style)) {
243 return false;
244 }
245 if (paint->getMaskFilter() || paint->getLooper()
246 || paint->getPathEffect() || paint->getImageFilter()) {
247 return false; // conservative
248 }
249 }
250
251 // The following test holds with AA enabled, and is conservative
252 // by a 0.5 pixel margin with AA disabled
junov@chromium.orgb1e218e2012-02-13 22:27:58 +0000253 if (transformedRect.fLeft > SkIntToScalar(0) ||
254 transformedRect.fTop > SkIntToScalar(0) ||
255 transformedRect.fRight < SkIntToScalar(canvasSize.fWidth) ||
256 transformedRect.fBottom < SkIntToScalar(canvasSize.fHeight)) {
junov@google.com4370aed2012-01-18 16:21:08 +0000257 return false;
258 }
259 }
260
261 switch (canvas->getClipType()) {
262 case SkCanvas::kRect_ClipType :
263 {
264 SkIRect bounds;
265 canvas->getClipDeviceBounds(&bounds);
266 if (bounds.fLeft > 0 || bounds.fTop > 0 ||
267 bounds.fRight < canvasSize.fWidth ||
268 bounds.fBottom < canvasSize.fHeight)
269 return false;
270 }
271 break;
272 case SkCanvas::kComplex_ClipType :
273 return false; // conservative
274 case SkCanvas::kEmpty_ClipType:
275 default:
276 break;
277 };
278
279 return true;
280}
281
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000282int SkDeferredCanvas::save(SaveFlags flags) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000283 drawingCanvas()->save(flags);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000284 return this->INHERITED::save(flags);
junov@google.com4370aed2012-01-18 16:21:08 +0000285}
286
287int SkDeferredCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000288 SaveFlags flags) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000289 drawingCanvas()->saveLayer(bounds, paint, flags);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000290 int count = this->INHERITED::save(flags);
291 this->clipRectBounds(bounds, flags, NULL);
292 return count;
junov@google.com4370aed2012-01-18 16:21:08 +0000293}
294
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000295void SkDeferredCanvas::restore() {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000296 drawingCanvas()->restore();
junov@chromium.orga907ac32012-02-24 21:54:07 +0000297 this->INHERITED::restore();
junov@google.com4370aed2012-01-18 16:21:08 +0000298}
299
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000300bool SkDeferredCanvas::isDrawingToLayer() const {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000301 return drawingCanvas()->isDrawingToLayer();
junov@google.com4370aed2012-01-18 16:21:08 +0000302}
303
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000304bool SkDeferredCanvas::translate(SkScalar dx, SkScalar dy) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000305 drawingCanvas()->translate(dx, dy);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000306 return this->INHERITED::translate(dx, dy);
junov@google.com4370aed2012-01-18 16:21:08 +0000307}
308
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000309bool SkDeferredCanvas::scale(SkScalar sx, SkScalar sy) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000310 drawingCanvas()->scale(sx, sy);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000311 return this->INHERITED::scale(sx, sy);
junov@google.com4370aed2012-01-18 16:21:08 +0000312}
313
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000314bool SkDeferredCanvas::rotate(SkScalar degrees) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000315 drawingCanvas()->rotate(degrees);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000316 return this->INHERITED::rotate(degrees);
junov@google.com4370aed2012-01-18 16:21:08 +0000317}
318
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000319bool SkDeferredCanvas::skew(SkScalar sx, SkScalar sy) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000320 drawingCanvas()->skew(sx, sy);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000321 return this->INHERITED::skew(sx, sy);
junov@google.com4370aed2012-01-18 16:21:08 +0000322}
323
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000324bool SkDeferredCanvas::concat(const SkMatrix& matrix) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000325 drawingCanvas()->concat(matrix);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000326 return this->INHERITED::concat(matrix);
junov@google.com4370aed2012-01-18 16:21:08 +0000327}
328
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000329void SkDeferredCanvas::setMatrix(const SkMatrix& matrix) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000330 drawingCanvas()->setMatrix(matrix);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000331 this->INHERITED::setMatrix(matrix);
junov@google.com4370aed2012-01-18 16:21:08 +0000332}
333
334bool SkDeferredCanvas::clipRect(const SkRect& rect,
335 SkRegion::Op op,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000336 bool doAntiAlias) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000337 drawingCanvas()->clipRect(rect, op, doAntiAlias);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000338 return this->INHERITED::clipRect(rect, op, doAntiAlias);
junov@google.com4370aed2012-01-18 16:21:08 +0000339}
340
341bool SkDeferredCanvas::clipPath(const SkPath& path,
342 SkRegion::Op op,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000343 bool doAntiAlias) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000344 drawingCanvas()->clipPath(path, op, doAntiAlias);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000345 return this->INHERITED::clipPath(path, op, doAntiAlias);
junov@google.com4370aed2012-01-18 16:21:08 +0000346}
347
348bool SkDeferredCanvas::clipRegion(const SkRegion& deviceRgn,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000349 SkRegion::Op op) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000350 drawingCanvas()->clipRegion(deviceRgn, op);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000351 return this->INHERITED::clipRegion(deviceRgn, op);
junov@google.com4370aed2012-01-18 16:21:08 +0000352}
353
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000354void SkDeferredCanvas::clear(SkColor color) {
junov@google.com4370aed2012-01-18 16:21:08 +0000355 // purge pending commands
356 if (fDeferredDrawing) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000357 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000358 }
359
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000360 drawingCanvas()->clear(color);
junov@google.com4370aed2012-01-18 16:21:08 +0000361}
362
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000363void SkDeferredCanvas::drawPaint(const SkPaint& paint) {
364 if (fDeferredDrawing && isFullFrame(NULL, &paint) &&
365 isPaintOpaque(&paint)) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000366 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000367 }
junov@chromium.org10f7f972012-07-31 21:01:51 +0000368 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000369 drawingCanvas()->drawPaint(paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000370}
371
372void SkDeferredCanvas::drawPoints(PointMode mode, size_t count,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000373 const SkPoint pts[], const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000374 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000375 drawingCanvas()->drawPoints(mode, count, pts, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000376}
377
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000378void SkDeferredCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
379 if (fDeferredDrawing && isFullFrame(&rect, &paint) &&
380 isPaintOpaque(&paint)) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000381 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000382 }
383
junov@chromium.org10f7f972012-07-31 21:01:51 +0000384 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000385 drawingCanvas()->drawRect(rect, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000386}
387
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000388void SkDeferredCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000389 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000390 drawingCanvas()->drawPath(path, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000391}
392
393void SkDeferredCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000394 SkScalar top, const SkPaint* paint) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000395 SkRect bitmapRect = SkRect::MakeXYWH(left, top,
396 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
junov@google.com4370aed2012-01-18 16:21:08 +0000397 if (fDeferredDrawing &&
398 isFullFrame(&bitmapRect, paint) &&
junov@chromium.org87f982c2012-02-23 21:34:34 +0000399 isPaintOpaque(paint, &bitmap)) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000400 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000401 }
402
junov@chromium.org10f7f972012-07-31 21:01:51 +0000403 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000404 drawingCanvas()->drawBitmap(bitmap, left, top, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000405}
406
407void SkDeferredCanvas::drawBitmapRect(const SkBitmap& bitmap,
408 const SkIRect* src,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000409 const SkRect& dst,
410 const SkPaint* paint) {
junov@google.com4370aed2012-01-18 16:21:08 +0000411 if (fDeferredDrawing &&
412 isFullFrame(&dst, paint) &&
junov@chromium.org87f982c2012-02-23 21:34:34 +0000413 isPaintOpaque(paint, &bitmap)) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000414 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000415 }
416
junov@chromium.org10f7f972012-07-31 21:01:51 +0000417 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000418 drawingCanvas()->drawBitmapRect(bitmap, src,
junov@google.com4370aed2012-01-18 16:21:08 +0000419 dst, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000420}
421
422
423void SkDeferredCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
424 const SkMatrix& m,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000425 const SkPaint* paint) {
junov@google.com4370aed2012-01-18 16:21:08 +0000426 // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
427 // covers canvas entirely and transformed bitmap covers canvas entirely
junov@chromium.org10f7f972012-07-31 21:01:51 +0000428 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000429 drawingCanvas()->drawBitmapMatrix(bitmap, m, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000430}
431
432void SkDeferredCanvas::drawBitmapNine(const SkBitmap& bitmap,
433 const SkIRect& center, const SkRect& dst,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000434 const SkPaint* paint) {
junov@google.com4370aed2012-01-18 16:21:08 +0000435 // TODO: reset recording canvas if paint+bitmap is opaque and clip rect
436 // covers canvas entirely and dst covers canvas entirely
junov@chromium.org10f7f972012-07-31 21:01:51 +0000437 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000438 drawingCanvas()->drawBitmapNine(bitmap, center,
junov@google.com4370aed2012-01-18 16:21:08 +0000439 dst, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000440}
441
442void SkDeferredCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000443 const SkPaint* paint) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000444 SkRect bitmapRect = SkRect::MakeXYWH(
445 SkIntToScalar(left),
446 SkIntToScalar(top),
447 SkIntToScalar(bitmap.width()),
448 SkIntToScalar(bitmap.height()));
junov@google.com4370aed2012-01-18 16:21:08 +0000449 if (fDeferredDrawing &&
450 isFullFrame(&bitmapRect, paint) &&
junov@chromium.org87f982c2012-02-23 21:34:34 +0000451 isPaintOpaque(paint, &bitmap)) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000452 getDeferredDevice()->contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000453 }
454
junov@chromium.org10f7f972012-07-31 21:01:51 +0000455 AutoImmediateDrawIfNeeded autoDraw(*this, &bitmap, paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000456 drawingCanvas()->drawSprite(bitmap, left, top,
junov@google.com4370aed2012-01-18 16:21:08 +0000457 paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000458}
459
460void SkDeferredCanvas::drawText(const void* text, size_t byteLength,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000461 SkScalar x, SkScalar y, const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000462 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000463 drawingCanvas()->drawText(text, byteLength, x, y, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000464}
465
466void SkDeferredCanvas::drawPosText(const void* text, size_t byteLength,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000467 const SkPoint pos[], const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000468 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000469 drawingCanvas()->drawPosText(text, byteLength, pos, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000470}
471
472void SkDeferredCanvas::drawPosTextH(const void* text, size_t byteLength,
473 const SkScalar xpos[], SkScalar constY,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000474 const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000475 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000476 drawingCanvas()->drawPosTextH(text, byteLength, xpos, constY, paint);
junov@google.com4370aed2012-01-18 16:21:08 +0000477}
478
479void SkDeferredCanvas::drawTextOnPath(const void* text, size_t byteLength,
480 const SkPath& path,
481 const SkMatrix* matrix,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000482 const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000483 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000484 drawingCanvas()->drawTextOnPath(text, byteLength,
junov@google.com4370aed2012-01-18 16:21:08 +0000485 path, matrix,
486 paint);
487}
488
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000489void SkDeferredCanvas::drawPicture(SkPicture& picture) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000490 drawingCanvas()->drawPicture(picture);
junov@google.com4370aed2012-01-18 16:21:08 +0000491}
492
493void SkDeferredCanvas::drawVertices(VertexMode vmode, int vertexCount,
494 const SkPoint vertices[],
495 const SkPoint texs[],
496 const SkColor colors[], SkXfermode* xmode,
497 const uint16_t indices[], int indexCount,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000498 const SkPaint& paint) {
junov@chromium.org10f7f972012-07-31 21:01:51 +0000499 AutoImmediateDrawIfNeeded autoDraw(*this, &paint);
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000500 drawingCanvas()->drawVertices(vmode, vertexCount,
junov@google.com4370aed2012-01-18 16:21:08 +0000501 vertices, texs,
502 colors, xmode,
503 indices, indexCount,
504 paint);
505}
506
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000507SkBounder* SkDeferredCanvas::setBounder(SkBounder* bounder) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000508 drawingCanvas()->setBounder(bounder);
junov@chromium.orga907ac32012-02-24 21:54:07 +0000509 return INHERITED::setBounder(bounder);
junov@google.com4370aed2012-01-18 16:21:08 +0000510}
511
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000512SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000513 drawingCanvas()->setDrawFilter(filter);
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000514 return INHERITED::setDrawFilter(filter);
junov@google.com4370aed2012-01-18 16:21:08 +0000515}
516
517SkCanvas* SkDeferredCanvas::canvasForDrawIter() {
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000518 return drawingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000519}
520
junov@chromium.org77eec242012-07-18 17:54:45 +0000521#if SK_DEFERRED_CANVAS_USES_GPIPE
522
523// SkDeferredCanvas::DeferredPipeController
524//-------------------------------------------
525
526SkDeferredCanvas::DeferredPipeController::DeferredPipeController() :
527 fAllocator(kMinBlockSize) {
528 fBlock = NULL;
529 fBytesWritten = 0;
530}
531
532SkDeferredCanvas::DeferredPipeController::~DeferredPipeController() {
533 fAllocator.reset();
534}
535
536void SkDeferredCanvas::DeferredPipeController::setPlaybackCanvas(SkCanvas* canvas) {
537 fReader.setCanvas(canvas);
538}
539
540void* SkDeferredCanvas::DeferredPipeController::requestBlock(size_t minRequest, size_t *actual) {
541 if (fBlock) {
542 // Save the previous block for later
543 PipeBlock previousBloc(fBlock, fBytesWritten);
544 fBlockList.push(previousBloc);
545 }
546 int32_t blockSize = SkMax32(minRequest, kMinBlockSize);
547 fBlock = fAllocator.allocThrow(blockSize);
548 fBytesWritten = 0;
549 *actual = blockSize;
550 return fBlock;
551}
552
553void SkDeferredCanvas::DeferredPipeController::notifyWritten(size_t bytes) {
554 fBytesWritten += bytes;
555}
556
557void SkDeferredCanvas::DeferredPipeController::playback() {
558
559 for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
560 fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize);
561 }
562 fBlockList.reset();
563
564 if (fBlock) {
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000565 fReader.playback(fBlock, fBytesWritten);
junov@chromium.org77eec242012-07-18 17:54:45 +0000566 fBlock = NULL;
567 }
568
569 // Release all allocated blocks
570 fAllocator.reset();
571}
572
573void SkDeferredCanvas::DeferredPipeController::reset() {
574 fBlockList.reset();
575 fBlock = NULL;
576 fAllocator.reset();
577}
578
579#endif // SK_DEFERRED_CANVAS_USES_GPIPE
580
junov@google.com4370aed2012-01-18 16:21:08 +0000581// SkDeferredCanvas::DeferredDevice
582//------------------------------------
583
584SkDeferredCanvas::DeferredDevice::DeferredDevice(
585 SkDevice* immediateDevice, DeviceContext* deviceContext) :
586 SkDevice(SkBitmap::kNo_Config, immediateDevice->width(),
587 immediateDevice->height(), immediateDevice->isOpaque())
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000588 , fFreshFrame(true) {
589
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000590 fMaxRecordingStorageBytes = kDefaultMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000591 fDeviceContext = deviceContext;
592 SkSafeRef(fDeviceContext);
593 fImmediateDevice = immediateDevice; // ref counted via fImmediateCanvas
594 fImmediateCanvas = SkNEW_ARGS(SkCanvas, (fImmediateDevice));
junov@chromium.org77eec242012-07-18 17:54:45 +0000595#if SK_DEFERRED_CANVAS_USES_GPIPE
596 fPipeController.setPlaybackCanvas(fImmediateCanvas);
597#endif
598 beginRecording();
junov@google.com4370aed2012-01-18 16:21:08 +0000599}
600
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000601SkDeferredCanvas::DeferredDevice::~DeferredDevice() {
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000602 flushPending();
junov@google.com4370aed2012-01-18 16:21:08 +0000603 SkSafeUnref(fImmediateCanvas);
604 SkSafeUnref(fDeviceContext);
605}
junov@chromium.org77eec242012-07-18 17:54:45 +0000606
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000607void SkDeferredCanvas::DeferredDevice::setMaxRecordingStorage(size_t maxStorage) {
608 fMaxRecordingStorageBytes = maxStorage;
609 recordingCanvas(); // Accessing the recording canvas applies the new limit.
610}
junov@chromium.org77eec242012-07-18 17:54:45 +0000611
612void SkDeferredCanvas::DeferredDevice::endRecording() {
613#if SK_DEFERRED_CANVAS_USES_GPIPE
614 fPipeWriter.endRecording();
615 fPipeController.reset();
616#else
617 fPicture.endRecording();
618#endif
619 fRecordingCanvas = NULL;
620}
621
622void SkDeferredCanvas::DeferredDevice::beginRecording() {
623#if SK_DEFERRED_CANVAS_USES_GPIPE
624 fRecordingCanvas = fPipeWriter.startRecording(&fPipeController, 0);
625#else
626 fRecordingCanvas = fPicture.beginRecording(fImmediateDevice->width(),
djsollen@google.com7dade422012-07-27 15:58:23 +0000627 fImmediateDevice->height());
junov@chromium.org77eec242012-07-18 17:54:45 +0000628#endif
629}
junov@google.com4370aed2012-01-18 16:21:08 +0000630
631void SkDeferredCanvas::DeferredDevice::setDeviceContext(
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000632 DeviceContext* deviceContext) {
junov@google.com4370aed2012-01-18 16:21:08 +0000633 SkRefCnt_SafeAssign(fDeviceContext, deviceContext);
634}
635
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000636void SkDeferredCanvas::DeferredDevice::contentsCleared() {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000637 if (!fRecordingCanvas->isDrawingToLayer()) {
638 fFreshFrame = true;
junov@google.com4370aed2012-01-18 16:21:08 +0000639
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000640 // TODO: find a way to transfer the state stack and layers
641 // to the new recording canvas. For now, purging only works
642 // with an empty stack.
643 if (fRecordingCanvas->getSaveCount() == 0) {
junov@google.com4370aed2012-01-18 16:21:08 +0000644
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000645 // Save state that is trashed by the purge
646 SkDrawFilter* drawFilter = fRecordingCanvas->getDrawFilter();
647 SkSafeRef(drawFilter); // So that it survives the purge
648 SkMatrix matrix = fRecordingCanvas->getTotalMatrix();
649 SkRegion clipRegion = fRecordingCanvas->getTotalClip();
junov@google.com4370aed2012-01-18 16:21:08 +0000650
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000651 // beginRecording creates a new recording canvas and discards the
652 // old one, hence purging deferred draw ops.
junov@chromium.org77eec242012-07-18 17:54:45 +0000653 this->endRecording();
654 this->beginRecording();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000655
656 // Restore pre-purge state
657 if (!clipRegion.isEmpty()) {
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000658 fRecordingCanvas->clipRegion(clipRegion,
659 SkRegion::kReplace_Op);
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000660 }
661 if (!matrix.isIdentity()) {
662 fRecordingCanvas->setMatrix(matrix);
663 }
664 if (drawFilter) {
665 fRecordingCanvas->setDrawFilter(drawFilter)->unref();
666 }
667 }
junov@google.com4370aed2012-01-18 16:21:08 +0000668 }
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000669}
670
671bool SkDeferredCanvas::DeferredDevice::isFreshFrame() {
672 bool ret = fFreshFrame;
673 fFreshFrame = false;
674 return ret;
junov@google.com4370aed2012-01-18 16:21:08 +0000675}
676
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000677void SkDeferredCanvas::DeferredDevice::flushPending() {
junov@chromium.org77eec242012-07-18 17:54:45 +0000678#if SK_DEFERRED_CANVAS_USES_GPIPE
679 if (!fPipeController.hasRecorded()) {
680 return;
681 }
682#else
junov@chromium.org4866cc02012-06-01 21:23:07 +0000683 if (!fPicture.hasRecorded()) {
684 return;
685 }
junov@chromium.org77eec242012-07-18 17:54:45 +0000686#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000687 if (fDeviceContext) {
688 fDeviceContext->prepareForDraw();
689 }
junov@chromium.org77eec242012-07-18 17:54:45 +0000690
691#if SK_DEFERRED_CANVAS_USES_GPIPE
692 fPipeWriter.flushRecording(true);
693 fPipeController.playback();
694#else
junov@google.com4370aed2012-01-18 16:21:08 +0000695 fPicture.draw(fImmediateCanvas);
junov@chromium.org77eec242012-07-18 17:54:45 +0000696 this->beginRecording();
697#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000698}
699
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000700void SkDeferredCanvas::DeferredDevice::flush() {
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000701 this->flushPending();
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000702 fImmediateCanvas->flush();
junov@google.com4370aed2012-01-18 16:21:08 +0000703}
704
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000705#if SK_DEFERRED_CANVAS_USES_GPIPE
706size_t SkDeferredCanvas::DeferredDevice::freeMemoryIfPossible(size_t bytesToFree) {
707 return fPipeWriter.freeMemoryIfPossible(bytesToFree);
708}
709#endif
710
711size_t SkDeferredCanvas::DeferredDevice::storageAllocatedForRecording() const {
712#if SK_DEFERRED_CANVAS_USES_GPIPE
713 return (fPipeController.storageAllocatedForRecording()
714 + fPipeWriter.storageAllocatedForRecording());
715#else
716 return 0;
717#endif
718}
719
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000720SkCanvas* SkDeferredCanvas::DeferredDevice::recordingCanvas() {
721#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000722 size_t storageAllocated = this->storageAllocatedForRecording();
723 if (storageAllocated > fMaxRecordingStorageBytes) {
724 // First, attempt to reduce cache without flushing
725 size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
726 if (this->freeMemoryIfPossible(tryFree) < tryFree) {
727 // Flush is necessary to free more space.
728 this->flushPending();
729 // Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
730 // which could cause a high flushing frequency.
731 this->freeMemoryIfPossible(~0);
732 }
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000733 }
734#endif
735 return fRecordingCanvas;
736}
737
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000738uint32_t SkDeferredCanvas::DeferredDevice::getDeviceCapabilities() {
junov@google.com4370aed2012-01-18 16:21:08 +0000739 return fImmediateDevice->getDeviceCapabilities();
740}
741
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000742int SkDeferredCanvas::DeferredDevice::width() const {
junov@google.com4370aed2012-01-18 16:21:08 +0000743 return fImmediateDevice->width();
744}
745
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000746int SkDeferredCanvas::DeferredDevice::height() const {
junov@google.com4370aed2012-01-18 16:21:08 +0000747 return fImmediateDevice->height();
748}
749
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000750SkGpuRenderTarget* SkDeferredCanvas::DeferredDevice::accessRenderTarget() {
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000751 this->flushPending();
junov@google.com4370aed2012-01-18 16:21:08 +0000752 return fImmediateDevice->accessRenderTarget();
753}
754
755void SkDeferredCanvas::DeferredDevice::writePixels(const SkBitmap& bitmap,
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000756 int x, int y, SkCanvas::Config8888 config8888) {
757
junov@google.com4370aed2012-01-18 16:21:08 +0000758 if (x <= 0 && y <= 0 && (x + bitmap.width()) >= width() &&
759 (y + bitmap.height()) >= height()) {
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000760 contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000761 }
762
763 if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
764 SkCanvas::kNative_Premul_Config8888 != config8888 &&
765 kPMColorAlias != config8888) {
766 //Special case config: no deferral
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000767 this->flushPending();
junov@google.com4370aed2012-01-18 16:21:08 +0000768 fImmediateDevice->writePixels(bitmap, x, y, config8888);
junov@chromium.org09640d62012-07-25 20:09:37 +0000769 return;
junov@google.com4370aed2012-01-18 16:21:08 +0000770 }
771
772 SkPaint paint;
773 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
junov@chromium.org10f7f972012-07-31 21:01:51 +0000774 if (shouldDrawImmediately(&bitmap, NULL)) {
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000775 this->flushPending();
776 fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
777 } else {
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000778 recordingCanvas()->drawSprite(bitmap, x, y, &paint);
779 }
junov@google.com4370aed2012-01-18 16:21:08 +0000780}
781
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000782const SkBitmap& SkDeferredCanvas::DeferredDevice::onAccessBitmap(SkBitmap*) {
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000783 this->flushPending();
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000784 return fImmediateDevice->accessBitmap(false);
junov@google.com4370aed2012-01-18 16:21:08 +0000785}
786
787SkDevice* SkDeferredCanvas::DeferredDevice::onCreateCompatibleDevice(
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000788 SkBitmap::Config config, int width, int height, bool isOpaque,
789 Usage usage) {
790
junov@google.com4370aed2012-01-18 16:21:08 +0000791 // Save layer usage not supported, and not required by SkDeferredCanvas.
792 SkASSERT(usage != kSaveLayer_Usage);
793 // Create a compatible non-deferred device.
scroggo@google.comd7dbd422012-07-03 15:16:30 +0000794 SkAutoTUnref<SkDevice> compatibleDevice
795 (fImmediateDevice->createCompatibleDevice(config, width, height,
796 isOpaque));
junov@google.com4370aed2012-01-18 16:21:08 +0000797 return SkNEW_ARGS(DeferredDevice, (compatibleDevice, fDeviceContext));
798}
799
800bool SkDeferredCanvas::DeferredDevice::onReadPixels(
junov@chromium.orgc16ca922012-02-24 22:06:27 +0000801 const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000802 this->flushPending();
junov@google.com4370aed2012-01-18 16:21:08 +0000803 return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
804 x, y, config8888);
805}