blob: dab1eb56439c6b34dcb69a3c67ad9ac353f8c092 [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@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
248 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
249 virtual int width() const SK_OVERRIDE;
250 virtual int height() const SK_OVERRIDE;
251 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
252
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000253 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
254 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000255 bool isOpaque,
256 Usage usage) SK_OVERRIDE;
257
258 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
259 SkCanvas::Config8888 config8888) SK_OVERRIDE;
260
261 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000262 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000263 virtual bool onReadPixels(const SkBitmap& bitmap,
264 int x, int y,
265 SkCanvas::Config8888 config8888) SK_OVERRIDE;
266
267 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000268 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000269 SK_OVERRIDE
270 {return false;}
271 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
272 const SkClipStack&) SK_OVERRIDE
273 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000274
275 // None of the following drawing methods should ever get called on the
276 // deferred device
277 virtual void clear(SkColor color)
278 {SkASSERT(0);}
279 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
280 {SkASSERT(0);}
281 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
282 size_t count, const SkPoint[],
283 const SkPaint& paint)
284 {SkASSERT(0);}
285 virtual void drawRect(const SkDraw&, const SkRect& r,
286 const SkPaint& paint)
287 {SkASSERT(0);}
288 virtual void drawPath(const SkDraw&, const SkPath& path,
289 const SkPaint& paint,
290 const SkMatrix* prePathMatrix = NULL,
291 bool pathIsMutable = false)
292 {SkASSERT(0);}
293 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
294 const SkIRect* srcRectOrNull,
295 const SkMatrix& matrix, const SkPaint& paint)
296 {SkASSERT(0);}
297 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
298 int x, int y, const SkPaint& paint)
299 {SkASSERT(0);}
300 virtual void drawText(const SkDraw&, const void* text, size_t len,
301 SkScalar x, SkScalar y, const SkPaint& paint)
302 {SkASSERT(0);}
303 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
304 const SkScalar pos[], SkScalar constY,
305 int scalarsPerPos, const SkPaint& paint)
306 {SkASSERT(0);}
307 virtual void drawTextOnPath(const SkDraw&, const void* text,
308 size_t len, const SkPath& path,
309 const SkMatrix* matrix,
310 const SkPaint& paint)
311 {SkASSERT(0);}
312 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
313 size_t len, const SkPoint pos[],
314 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000315 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000316 const SkMatrix* matrix)
317 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000318 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000319 int vertexCount, const SkPoint verts[],
320 const SkPoint texs[], const SkColor colors[],
321 SkXfermode* xmode, const uint16_t indices[],
322 int indexCount, const SkPaint& paint)
323 {SkASSERT(0);}
324 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
325 const SkPaint&)
326 {SkASSERT(0);}
327 private:
328 virtual void flush();
329
junov@chromium.org77eec242012-07-18 17:54:45 +0000330 void endRecording();
331 void beginRecording();
332
333#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org77eec242012-07-18 17:54:45 +0000334 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000335 SkGPipeWriter fPipeWriter;
junov@chromium.org77eec242012-07-18 17:54:45 +0000336#else
junov@google.com4370aed2012-01-18 16:21:08 +0000337 SkPicture fPicture;
junov@chromium.org77eec242012-07-18 17:54:45 +0000338#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000339 SkDevice* fImmediateDevice;
340 SkCanvas* fImmediateCanvas;
341 SkCanvas* fRecordingCanvas;
342 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000343 bool fFreshFrame;
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000344 size_t fMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000345 };
346
347 DeferredDevice* getDeferredDevice() const;
348
349protected:
350 virtual SkCanvas* canvasForDrawIter();
351
352private:
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000353 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000354 bool isFullFrame(const SkRect*, const SkPaint*) const;
355 void validate() const;
356 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000357 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000358
359 typedef SkCanvas INHERITED;
360};
361
362
363#endif