blob: 363de1bcf2f565e62bdd99331a3cf40705f3b9d0 [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.orgd122fd52012-08-01 20:00:03 +000012#define SK_DEFERRED_CANVAS_USES_GPIPE 1
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@chromium.org2e14ba82012-08-07 14:26:57 +0000101 /**
102 * Returns the number of bytes currently allocated for the purpose of
103 * recording draw commands.
104 */
105 size_t storageAllocatedForRecording() const;
106
107 /**
108 * Attempt to reduce the storage allocated for recording by evicting
109 * cache resources.
110 * @param bytesToFree minimum number of bytes that should be attempted to
111 * be freed.
112 * @return number of bytes actually freed.
113 */
114 size_t freeMemoryIfPossible(size_t bytesToFree);
115
junov@google.com4370aed2012-01-18 16:21:08 +0000116 // Overrides of the SkCanvas interface
117 virtual int save(SaveFlags flags) SK_OVERRIDE;
118 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
119 SaveFlags flags) SK_OVERRIDE;
120 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000121 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000122 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
123 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
124 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
125 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
126 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
127 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000128 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
129 bool doAntiAlias) SK_OVERRIDE;
130 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
131 bool doAntiAlias) SK_OVERRIDE;
132 virtual bool clipRegion(const SkRegion& deviceRgn,
133 SkRegion::Op op) SK_OVERRIDE;
134 virtual void clear(SkColor) SK_OVERRIDE;
135 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
136 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
137 const SkPaint& paint) SK_OVERRIDE;
138 virtual void drawRect(const SkRect& rect, const SkPaint& paint)
139 SK_OVERRIDE;
140 virtual void drawPath(const SkPath& path, const SkPaint& paint)
141 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000142 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000143 SkScalar top, const SkPaint* paint)
144 SK_OVERRIDE;
145 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
146 const SkRect& dst, const SkPaint* paint)
147 SK_OVERRIDE;
148
149 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
150 const SkPaint* paint) SK_OVERRIDE;
151 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
152 const SkRect& dst, const SkPaint* paint)
153 SK_OVERRIDE;
154 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
155 const SkPaint* paint) SK_OVERRIDE;
156 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
157 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
158 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000159 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000160 SK_OVERRIDE;
161 virtual void drawPosTextH(const void* text, size_t byteLength,
162 const SkScalar xpos[], SkScalar constY,
163 const SkPaint& paint) SK_OVERRIDE;
164 virtual void drawTextOnPath(const void* text, size_t byteLength,
165 const SkPath& path, const SkMatrix* matrix,
166 const SkPaint& paint) SK_OVERRIDE;
167 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
168 virtual void drawVertices(VertexMode vmode, int vertexCount,
169 const SkPoint vertices[], const SkPoint texs[],
170 const SkColor colors[], SkXfermode* xmode,
171 const uint16_t indices[], int indexCount,
172 const SkPaint& paint) SK_OVERRIDE;
173 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
174 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
175
junov@google.com4370aed2012-01-18 16:21:08 +0000176public:
177 class DeviceContext : public SkRefCnt {
178 public:
reed@google.com563a3b42012-06-26 19:24:50 +0000179 SK_DECLARE_INST_COUNT(DeviceContext)
180
junov@google.com4370aed2012-01-18 16:21:08 +0000181 virtual void prepareForDraw() {}
reed@google.com563a3b42012-06-26 19:24:50 +0000182
183 private:
184 typedef SkRefCnt INHERITED;
junov@google.com4370aed2012-01-18 16:21:08 +0000185 };
186
junov@chromium.org77eec242012-07-18 17:54:45 +0000187#if SK_DEFERRED_CANVAS_USES_GPIPE
188protected:
189 class DeferredPipeController : public SkGPipeController {
190 public:
191 DeferredPipeController();
192 void setPlaybackCanvas(SkCanvas*);
193 virtual ~DeferredPipeController();
194 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
195 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
196 void playback();
197 void reset();
junov@chromium.org8317e172012-07-23 14:17:45 +0000198 bool hasRecorded() const { return fAllocator.blockCount() != 0; }
199 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
junov@chromium.org77eec242012-07-18 17:54:45 +0000200 private:
201 enum {
202 kMinBlockSize = 4096
203 };
204 struct PipeBlock {
205 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
206 void* fBlock;
207 size_t fSize;
208 };
209 void* fBlock;
210 size_t fBytesWritten;
211 SkChunkAlloc fAllocator;
212 SkTDArray<PipeBlock> fBlockList;
213 SkGPipeReader fReader;
214 };
215#endif
216
junov@google.com4370aed2012-01-18 16:21:08 +0000217public:
218 class DeferredDevice : public SkDevice {
219 public:
220 /**
221 * Constructor
222 * @param immediateDevice device to be drawn to when flushing
223 * deferred operations
224 * @param deviceContext callback interface for managing graphics
225 * context state, can be NULL.
226 */
227 DeferredDevice(SkDevice* immediateDevice,
228 DeviceContext* deviceContext = NULL);
229 ~DeferredDevice();
230
231 /**
232 * Sets the device context to be use with the device.
233 * @param deviceContext callback interface for managing graphics
234 * context state, can be NULL.
235 */
236 void setDeviceContext(DeviceContext* deviceContext);
237
238 /**
239 * Returns the recording canvas.
240 */
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000241 SkCanvas* recordingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000242
243 /**
244 * Returns the immediate (non deferred) canvas.
245 */
246 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
247
248 /**
249 * Returns the immediate (non deferred) device.
250 */
251 SkDevice* immediateDevice() const {return fImmediateDevice;}
252
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000253 /**
254 * Returns true if an opaque draw operation covering the entire canvas
255 * was performed since the last call to isFreshFrame().
256 */
257 bool isFreshFrame();
258
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000259 size_t storageAllocatedForRecording() const;
260 size_t freeMemoryIfPossible(size_t bytesToFree);
junov@google.com4370aed2012-01-18 16:21:08 +0000261 void flushPending();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000262 void contentsCleared();
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000263 void setMaxRecordingStorage(size_t);
junov@google.com4370aed2012-01-18 16:21:08 +0000264
265 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
266 virtual int width() const SK_OVERRIDE;
267 virtual int height() const SK_OVERRIDE;
268 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
269
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000270 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
271 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000272 bool isOpaque,
273 Usage usage) SK_OVERRIDE;
274
275 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
276 SkCanvas::Config8888 config8888) SK_OVERRIDE;
277
278 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000279 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000280 virtual bool onReadPixels(const SkBitmap& bitmap,
281 int x, int y,
282 SkCanvas::Config8888 config8888) SK_OVERRIDE;
283
284 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000285 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000286 SK_OVERRIDE
287 {return false;}
288 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
289 const SkClipStack&) SK_OVERRIDE
290 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000291
292 // None of the following drawing methods should ever get called on the
293 // deferred device
294 virtual void clear(SkColor color)
295 {SkASSERT(0);}
296 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
297 {SkASSERT(0);}
298 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
299 size_t count, const SkPoint[],
300 const SkPaint& paint)
301 {SkASSERT(0);}
302 virtual void drawRect(const SkDraw&, const SkRect& r,
303 const SkPaint& paint)
304 {SkASSERT(0);}
305 virtual void drawPath(const SkDraw&, const SkPath& path,
306 const SkPaint& paint,
307 const SkMatrix* prePathMatrix = NULL,
308 bool pathIsMutable = false)
309 {SkASSERT(0);}
310 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
311 const SkIRect* srcRectOrNull,
312 const SkMatrix& matrix, const SkPaint& paint)
313 {SkASSERT(0);}
314 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
315 int x, int y, const SkPaint& paint)
316 {SkASSERT(0);}
317 virtual void drawText(const SkDraw&, const void* text, size_t len,
318 SkScalar x, SkScalar y, const SkPaint& paint)
319 {SkASSERT(0);}
320 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
321 const SkScalar pos[], SkScalar constY,
322 int scalarsPerPos, const SkPaint& paint)
323 {SkASSERT(0);}
324 virtual void drawTextOnPath(const SkDraw&, const void* text,
325 size_t len, const SkPath& path,
326 const SkMatrix* matrix,
327 const SkPaint& paint)
328 {SkASSERT(0);}
329 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
330 size_t len, const SkPoint pos[],
331 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000332 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000333 const SkMatrix* matrix)
334 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000335 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000336 int vertexCount, const SkPoint verts[],
337 const SkPoint texs[], const SkColor colors[],
338 SkXfermode* xmode, const uint16_t indices[],
339 int indexCount, const SkPaint& paint)
340 {SkASSERT(0);}
341 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
342 const SkPaint&)
343 {SkASSERT(0);}
344 private:
345 virtual void flush();
346
junov@chromium.org77eec242012-07-18 17:54:45 +0000347 void endRecording();
348 void beginRecording();
349
350#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org77eec242012-07-18 17:54:45 +0000351 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000352 SkGPipeWriter fPipeWriter;
junov@chromium.org77eec242012-07-18 17:54:45 +0000353#else
junov@google.com4370aed2012-01-18 16:21:08 +0000354 SkPicture fPicture;
junov@chromium.org77eec242012-07-18 17:54:45 +0000355#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000356 SkDevice* fImmediateDevice;
357 SkCanvas* fImmediateCanvas;
358 SkCanvas* fRecordingCanvas;
359 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000360 bool fFreshFrame;
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000361 size_t fMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000362 };
363
364 DeferredDevice* getDeferredDevice() const;
365
366protected:
367 virtual SkCanvas* canvasForDrawIter();
368
369private:
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000370 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000371 bool isFullFrame(const SkRect*, const SkPaint*) const;
372 void validate() const;
373 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000374 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000375
376 typedef SkCanvas INHERITED;
377};
378
379
380#endif