blob: 9adc3320de73210726ffaeca843e867f45eec627 [file] [log] [blame]
junov@google.com4370aed2012-01-18 16:21:08 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkDeferredCanvas_DEFINED
9#define SkDeferredCanvas_DEFINED
10
junov@chromium.org77eec242012-07-18 17:54:45 +000011#ifndef SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org8e1678f2012-07-20 18:32:39 +000012#define SK_DEFERRED_CANVAS_USES_GPIPE 0
junov@chromium.org77eec242012-07-18 17:54:45 +000013#endif
14
junov@google.com4370aed2012-01-18 16:21:08 +000015#include "SkCanvas.h"
16#include "SkDevice.h"
junov@google.com4370aed2012-01-18 16:21:08 +000017#include "SkPixelRef.h"
18
junov@chromium.org77eec242012-07-18 17:54:45 +000019#if SK_DEFERRED_CANVAS_USES_GPIPE
20#include "SkGPipe.h"
21#include "SkChunkAlloc.h"
22#else
23#include "SkPicture.h"
24#endif
25
junov@google.com4370aed2012-01-18 16:21:08 +000026/** \class SkDeferredCanvas
junov@chromium.org77eec242012-07-18 17:54:45 +000027 Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred
28 drawing. The main difference between this class and SkPictureRecord (the
29 canvas provided by SkPicture) is that this is a full drop-in replacement
30 for SkCanvas, while SkPictureRecord only supports draw operations.
junov@google.com4370aed2012-01-18 16:21:08 +000031 SkDeferredCanvas will transparently trigger the flushing of deferred
vandebo@chromium.org74b46192012-01-28 01:45:11 +000032 draw operations when an attempt is made to access the pixel data.
junov@google.com4370aed2012-01-18 16:21:08 +000033*/
34class SK_API SkDeferredCanvas : public SkCanvas {
35public:
36 class DeviceContext;
37
38 SkDeferredCanvas();
39
40 /** Construct a canvas with the specified device to draw into.
41 Equivalent to calling default constructor, then setDevice.
42 @param device Specifies a device for the canvas to draw into.
43 */
44 explicit SkDeferredCanvas(SkDevice* device);
45
46 /** Construct a canvas with the specified device to draw into, and
47 * a device context. Equivalent to calling default constructor, then
48 * setDevice.
49 * @param device Specifies a device for the canvas to draw into.
50 * @param deviceContext interface for the device's the graphics context
51 */
52 explicit SkDeferredCanvas(SkDevice* device, DeviceContext* deviceContext);
53
54 virtual ~SkDeferredCanvas();
55
56 /**
57 * Specify a device to be used by this canvas. Calling setDevice will
58 * release the previously set device, if any.
59 *
60 * @param device The device that the canvas will raw into
61 * @return The device argument, for convenience.
62 */
63 virtual SkDevice* setDevice(SkDevice* device);
64
65 /**
vandebo@chromium.org74b46192012-01-28 01:45:11 +000066 * Specify a deviceContext to be used by this canvas. Calling
junov@google.com4370aed2012-01-18 16:21:08 +000067 * setDeviceContext will release the previously set deviceContext, if any.
68 * A deviceContext must be specified if the device uses a graphics context
vandebo@chromium.org74b46192012-01-28 01:45:11 +000069 * that requires some form of state initialization prior to drawing
junov@google.com4370aed2012-01-18 16:21:08 +000070 * and/or explicit flushing to synchronize the execution of rendering
vandebo@chromium.org74b46192012-01-28 01:45:11 +000071 * operations.
junov@google.com4370aed2012-01-18 16:21:08 +000072 * Note: Must be called after the device is set with setDevice.
73 *
74 * @deviceContext interface for the device's the graphics context
75 * @return The deviceContext argument, for convenience.
76 */
77 DeviceContext* setDeviceContext(DeviceContext* deviceContext);
78
79 /**
80 * Enable or disable deferred drawing. When deferral is disabled,
81 * pending draw operations are immediately flushed and from then on,
82 * the SkDeferredCanvas behaves just like a regular SkCanvas.
83 * This method must not be called while the save/restore stack is in use.
84 * @param deferred true/false
85 */
86 void setDeferredDrawing(bool deferred);
87
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000088 /**
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000089 * Returns true if deferred drawing is currenlty enabled.
90 */
91 bool isDeferredDrawing();
92
93 /**
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000094 * Specify the maximum number of bytes to be allocated for the purpose
95 * of recording draw commands to this canvas. The default limit, is
96 * 64MB.
97 * @param maxStorage The maximum number of bytes to be allocated.
98 */
99 void setMaxRecordingStorage(size_t maxStorage);
100
junov@google.com4370aed2012-01-18 16:21:08 +0000101 // Overrides of the SkCanvas interface
102 virtual int save(SaveFlags flags) SK_OVERRIDE;
103 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
104 SaveFlags flags) SK_OVERRIDE;
105 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000106 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000107 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
108 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
109 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
110 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
111 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
112 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000113 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
114 bool doAntiAlias) SK_OVERRIDE;
115 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
116 bool doAntiAlias) SK_OVERRIDE;
117 virtual bool clipRegion(const SkRegion& deviceRgn,
118 SkRegion::Op op) SK_OVERRIDE;
119 virtual void clear(SkColor) SK_OVERRIDE;
120 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
121 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
122 const SkPaint& paint) SK_OVERRIDE;
123 virtual void drawRect(const SkRect& rect, const SkPaint& paint)
124 SK_OVERRIDE;
125 virtual void drawPath(const SkPath& path, const SkPaint& paint)
126 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000127 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000128 SkScalar top, const SkPaint* paint)
129 SK_OVERRIDE;
130 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
131 const SkRect& dst, const SkPaint* paint)
132 SK_OVERRIDE;
133
134 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
135 const SkPaint* paint) SK_OVERRIDE;
136 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
137 const SkRect& dst, const SkPaint* paint)
138 SK_OVERRIDE;
139 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
140 const SkPaint* paint) SK_OVERRIDE;
141 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
142 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
143 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000144 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000145 SK_OVERRIDE;
146 virtual void drawPosTextH(const void* text, size_t byteLength,
147 const SkScalar xpos[], SkScalar constY,
148 const SkPaint& paint) SK_OVERRIDE;
149 virtual void drawTextOnPath(const void* text, size_t byteLength,
150 const SkPath& path, const SkMatrix* matrix,
151 const SkPaint& paint) SK_OVERRIDE;
152 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
153 virtual void drawVertices(VertexMode vmode, int vertexCount,
154 const SkPoint vertices[], const SkPoint texs[],
155 const SkColor colors[], SkXfermode* xmode,
156 const uint16_t indices[], int indexCount,
157 const SkPaint& paint) SK_OVERRIDE;
158 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
159 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
160
junov@google.com4370aed2012-01-18 16:21:08 +0000161public:
162 class DeviceContext : public SkRefCnt {
163 public:
reed@google.com563a3b42012-06-26 19:24:50 +0000164 SK_DECLARE_INST_COUNT(DeviceContext)
165
junov@google.com4370aed2012-01-18 16:21:08 +0000166 virtual void prepareForDraw() {}
reed@google.com563a3b42012-06-26 19:24:50 +0000167
168 private:
169 typedef SkRefCnt INHERITED;
junov@google.com4370aed2012-01-18 16:21:08 +0000170 };
171
junov@chromium.org77eec242012-07-18 17:54:45 +0000172#if SK_DEFERRED_CANVAS_USES_GPIPE
173protected:
174 class DeferredPipeController : public SkGPipeController {
175 public:
176 DeferredPipeController();
177 void setPlaybackCanvas(SkCanvas*);
178 virtual ~DeferredPipeController();
179 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
180 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
181 void playback();
182 void reset();
junov@chromium.org8317e172012-07-23 14:17:45 +0000183 bool hasRecorded() const { return fAllocator.blockCount() != 0; }
184 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
junov@chromium.org77eec242012-07-18 17:54:45 +0000185 private:
186 enum {
187 kMinBlockSize = 4096
188 };
189 struct PipeBlock {
190 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
191 void* fBlock;
192 size_t fSize;
193 };
194 void* fBlock;
195 size_t fBytesWritten;
196 SkChunkAlloc fAllocator;
197 SkTDArray<PipeBlock> fBlockList;
198 SkGPipeReader fReader;
199 };
200#endif
201
junov@google.com4370aed2012-01-18 16:21:08 +0000202public:
203 class DeferredDevice : public SkDevice {
204 public:
205 /**
206 * Constructor
207 * @param immediateDevice device to be drawn to when flushing
208 * deferred operations
209 * @param deviceContext callback interface for managing graphics
210 * context state, can be NULL.
211 */
212 DeferredDevice(SkDevice* immediateDevice,
213 DeviceContext* deviceContext = NULL);
214 ~DeferredDevice();
215
216 /**
217 * Sets the device context to be use with the device.
218 * @param deviceContext callback interface for managing graphics
219 * context state, can be NULL.
220 */
221 void setDeviceContext(DeviceContext* deviceContext);
222
223 /**
224 * Returns the recording canvas.
225 */
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000226 SkCanvas* recordingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000227
228 /**
229 * Returns the immediate (non deferred) canvas.
230 */
231 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
232
233 /**
234 * Returns the immediate (non deferred) device.
235 */
236 SkDevice* immediateDevice() const {return fImmediateDevice;}
237
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000238 /**
239 * Returns true if an opaque draw operation covering the entire canvas
240 * was performed since the last call to isFreshFrame().
241 */
242 bool isFreshFrame();
243
junov@google.com4370aed2012-01-18 16:21:08 +0000244 void flushPending();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000245 void contentsCleared();
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000246 void setMaxRecordingStorage(size_t);
junov@google.com4370aed2012-01-18 16:21:08 +0000247
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000248 // FIXME: Temporary solution for tracking memory usage, pending
249 // resolution of http://code.google.com/p/skia/issues/detail?id=738
250#if SK_DEFERRED_CANVAS_USES_GPIPE
251 void accountForTempBitmapStorage(const SkBitmap& bitmap);
252#endif
253
junov@google.com4370aed2012-01-18 16:21:08 +0000254 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
255 virtual int width() const SK_OVERRIDE;
256 virtual int height() const SK_OVERRIDE;
257 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
258
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000259 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
260 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000261 bool isOpaque,
262 Usage usage) SK_OVERRIDE;
263
264 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
265 SkCanvas::Config8888 config8888) SK_OVERRIDE;
266
267 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000268 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000269 virtual bool onReadPixels(const SkBitmap& bitmap,
270 int x, int y,
271 SkCanvas::Config8888 config8888) SK_OVERRIDE;
272
273 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000274 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000275 SK_OVERRIDE
276 {return false;}
277 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
278 const SkClipStack&) SK_OVERRIDE
279 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000280
281 // None of the following drawing methods should ever get called on the
282 // deferred device
283 virtual void clear(SkColor color)
284 {SkASSERT(0);}
285 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
286 {SkASSERT(0);}
287 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
288 size_t count, const SkPoint[],
289 const SkPaint& paint)
290 {SkASSERT(0);}
291 virtual void drawRect(const SkDraw&, const SkRect& r,
292 const SkPaint& paint)
293 {SkASSERT(0);}
294 virtual void drawPath(const SkDraw&, const SkPath& path,
295 const SkPaint& paint,
296 const SkMatrix* prePathMatrix = NULL,
297 bool pathIsMutable = false)
298 {SkASSERT(0);}
299 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
300 const SkIRect* srcRectOrNull,
301 const SkMatrix& matrix, const SkPaint& paint)
302 {SkASSERT(0);}
303 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
304 int x, int y, const SkPaint& paint)
305 {SkASSERT(0);}
306 virtual void drawText(const SkDraw&, const void* text, size_t len,
307 SkScalar x, SkScalar y, const SkPaint& paint)
308 {SkASSERT(0);}
309 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
310 const SkScalar pos[], SkScalar constY,
311 int scalarsPerPos, const SkPaint& paint)
312 {SkASSERT(0);}
313 virtual void drawTextOnPath(const SkDraw&, const void* text,
314 size_t len, const SkPath& path,
315 const SkMatrix* matrix,
316 const SkPaint& paint)
317 {SkASSERT(0);}
318 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
319 size_t len, const SkPoint pos[],
320 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000321 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000322 const SkMatrix* matrix)
323 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000324 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000325 int vertexCount, const SkPoint verts[],
326 const SkPoint texs[], const SkColor colors[],
327 SkXfermode* xmode, const uint16_t indices[],
328 int indexCount, const SkPaint& paint)
329 {SkASSERT(0);}
330 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
331 const SkPaint&)
332 {SkASSERT(0);}
333 private:
334 virtual void flush();
335
junov@chromium.org77eec242012-07-18 17:54:45 +0000336 void endRecording();
337 void beginRecording();
338
339#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org77eec242012-07-18 17:54:45 +0000340 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000341 SkGPipeWriter fPipeWriter;
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000342 // FIXME: Temporary solution for tracking memory usage, pending
343 // resolution of http://code.google.com/p/skia/issues/detail?id=738
344 size_t fTempBitmapStorage;
junov@chromium.org77eec242012-07-18 17:54:45 +0000345#else
junov@google.com4370aed2012-01-18 16:21:08 +0000346 SkPicture fPicture;
junov@chromium.org77eec242012-07-18 17:54:45 +0000347#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000348 SkDevice* fImmediateDevice;
349 SkCanvas* fImmediateCanvas;
350 SkCanvas* fRecordingCanvas;
351 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000352 bool fFreshFrame;
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000353 size_t fMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000354 };
355
356 DeferredDevice* getDeferredDevice() const;
357
358protected:
359 virtual SkCanvas* canvasForDrawIter();
360
361private:
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000362 // FIXME: Temporary solution for tracking memory usage, pending
363 // resolution of http://code.google.com/p/skia/issues/detail?id=738
364#if SK_DEFERRED_CANVAS_USES_GPIPE
365 friend class AutoImmediateDrawIfNeeded;
366 void accountForTempBitmapStorage(const SkBitmap& bitmap) const;
367#endif
368
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000369 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000370 bool isFullFrame(const SkRect*, const SkPaint*) const;
371 void validate() const;
372 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000373 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000374
375 typedef SkCanvas INHERITED;
376};
377
378
379#endif