blob: 829a72fccc6f88013e51dadd193be8eaf81b6a21 [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 /**
89 * Specify the maximum number of bytes to be allocated for the purpose
90 * of recording draw commands to this canvas. The default limit, is
91 * 64MB.
92 * @param maxStorage The maximum number of bytes to be allocated.
93 */
94 void setMaxRecordingStorage(size_t maxStorage);
95
junov@google.com4370aed2012-01-18 16:21:08 +000096 // Overrides of the SkCanvas interface
97 virtual int save(SaveFlags flags) SK_OVERRIDE;
98 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
99 SaveFlags flags) SK_OVERRIDE;
100 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000101 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000102 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
103 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
104 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
105 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
106 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
107 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000108 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
109 bool doAntiAlias) SK_OVERRIDE;
110 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
111 bool doAntiAlias) SK_OVERRIDE;
112 virtual bool clipRegion(const SkRegion& deviceRgn,
113 SkRegion::Op op) SK_OVERRIDE;
114 virtual void clear(SkColor) SK_OVERRIDE;
115 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
116 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
117 const SkPaint& paint) SK_OVERRIDE;
118 virtual void drawRect(const SkRect& rect, const SkPaint& paint)
119 SK_OVERRIDE;
120 virtual void drawPath(const SkPath& path, const SkPaint& paint)
121 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000122 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000123 SkScalar top, const SkPaint* paint)
124 SK_OVERRIDE;
125 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
126 const SkRect& dst, const SkPaint* paint)
127 SK_OVERRIDE;
128
129 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
130 const SkPaint* paint) SK_OVERRIDE;
131 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
132 const SkRect& dst, const SkPaint* paint)
133 SK_OVERRIDE;
134 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
135 const SkPaint* paint) SK_OVERRIDE;
136 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
137 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
138 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000139 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000140 SK_OVERRIDE;
141 virtual void drawPosTextH(const void* text, size_t byteLength,
142 const SkScalar xpos[], SkScalar constY,
143 const SkPaint& paint) SK_OVERRIDE;
144 virtual void drawTextOnPath(const void* text, size_t byteLength,
145 const SkPath& path, const SkMatrix* matrix,
146 const SkPaint& paint) SK_OVERRIDE;
147 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
148 virtual void drawVertices(VertexMode vmode, int vertexCount,
149 const SkPoint vertices[], const SkPoint texs[],
150 const SkColor colors[], SkXfermode* xmode,
151 const uint16_t indices[], int indexCount,
152 const SkPaint& paint) SK_OVERRIDE;
153 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
154 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
155
156private:
157 void flushIfNeeded(const SkBitmap& bitmap);
158
159public:
160 class DeviceContext : public SkRefCnt {
161 public:
reed@google.com563a3b42012-06-26 19:24:50 +0000162 SK_DECLARE_INST_COUNT(DeviceContext)
163
junov@google.com4370aed2012-01-18 16:21:08 +0000164 virtual void prepareForDraw() {}
reed@google.com563a3b42012-06-26 19:24:50 +0000165
166 private:
167 typedef SkRefCnt INHERITED;
junov@google.com4370aed2012-01-18 16:21:08 +0000168 };
169
junov@chromium.org77eec242012-07-18 17:54:45 +0000170#if SK_DEFERRED_CANVAS_USES_GPIPE
171protected:
172 class DeferredPipeController : public SkGPipeController {
173 public:
174 DeferredPipeController();
175 void setPlaybackCanvas(SkCanvas*);
176 virtual ~DeferredPipeController();
177 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
178 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
179 void playback();
180 void reset();
junov@chromium.org8317e172012-07-23 14:17:45 +0000181 bool hasRecorded() const { return fAllocator.blockCount() != 0; }
182 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
junov@chromium.org77eec242012-07-18 17:54:45 +0000183 private:
184 enum {
185 kMinBlockSize = 4096
186 };
187 struct PipeBlock {
188 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
189 void* fBlock;
190 size_t fSize;
191 };
192 void* fBlock;
193 size_t fBytesWritten;
194 SkChunkAlloc fAllocator;
195 SkTDArray<PipeBlock> fBlockList;
196 SkGPipeReader fReader;
197 };
198#endif
199
junov@google.com4370aed2012-01-18 16:21:08 +0000200public:
201 class DeferredDevice : public SkDevice {
202 public:
203 /**
204 * Constructor
205 * @param immediateDevice device to be drawn to when flushing
206 * deferred operations
207 * @param deviceContext callback interface for managing graphics
208 * context state, can be NULL.
209 */
210 DeferredDevice(SkDevice* immediateDevice,
211 DeviceContext* deviceContext = NULL);
212 ~DeferredDevice();
213
214 /**
215 * Sets the device context to be use with the device.
216 * @param deviceContext callback interface for managing graphics
217 * context state, can be NULL.
218 */
219 void setDeviceContext(DeviceContext* deviceContext);
220
221 /**
222 * Returns the recording canvas.
223 */
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000224 SkCanvas* recordingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000225
226 /**
227 * Returns the immediate (non deferred) canvas.
228 */
229 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
230
231 /**
232 * Returns the immediate (non deferred) device.
233 */
234 SkDevice* immediateDevice() const {return fImmediateDevice;}
235
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000236 /**
237 * Returns true if an opaque draw operation covering the entire canvas
238 * was performed since the last call to isFreshFrame().
239 */
240 bool isFreshFrame();
241
junov@google.com4370aed2012-01-18 16:21:08 +0000242 void flushPending();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000243 void contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000244 void flushIfNeeded(const SkBitmap& bitmap);
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000245 void setMaxRecordingStorage(size_t);
junov@google.com4370aed2012-01-18 16:21:08 +0000246
247 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
248 virtual int width() const SK_OVERRIDE;
249 virtual int height() const SK_OVERRIDE;
250 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
251
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000252 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
253 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000254 bool isOpaque,
255 Usage usage) SK_OVERRIDE;
256
257 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
258 SkCanvas::Config8888 config8888) SK_OVERRIDE;
259
260 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000261 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000262 virtual bool onReadPixels(const SkBitmap& bitmap,
263 int x, int y,
264 SkCanvas::Config8888 config8888) SK_OVERRIDE;
265
266 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000267 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000268 SK_OVERRIDE
269 {return false;}
270 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
271 const SkClipStack&) SK_OVERRIDE
272 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000273
274 // None of the following drawing methods should ever get called on the
275 // deferred device
276 virtual void clear(SkColor color)
277 {SkASSERT(0);}
278 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
279 {SkASSERT(0);}
280 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
281 size_t count, const SkPoint[],
282 const SkPaint& paint)
283 {SkASSERT(0);}
284 virtual void drawRect(const SkDraw&, const SkRect& r,
285 const SkPaint& paint)
286 {SkASSERT(0);}
287 virtual void drawPath(const SkDraw&, const SkPath& path,
288 const SkPaint& paint,
289 const SkMatrix* prePathMatrix = NULL,
290 bool pathIsMutable = false)
291 {SkASSERT(0);}
292 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
293 const SkIRect* srcRectOrNull,
294 const SkMatrix& matrix, const SkPaint& paint)
295 {SkASSERT(0);}
296 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
297 int x, int y, const SkPaint& paint)
298 {SkASSERT(0);}
299 virtual void drawText(const SkDraw&, const void* text, size_t len,
300 SkScalar x, SkScalar y, const SkPaint& paint)
301 {SkASSERT(0);}
302 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
303 const SkScalar pos[], SkScalar constY,
304 int scalarsPerPos, const SkPaint& paint)
305 {SkASSERT(0);}
306 virtual void drawTextOnPath(const SkDraw&, const void* text,
307 size_t len, const SkPath& path,
308 const SkMatrix* matrix,
309 const SkPaint& paint)
310 {SkASSERT(0);}
311 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
312 size_t len, const SkPoint pos[],
313 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000314 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000315 const SkMatrix* matrix)
316 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000317 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000318 int vertexCount, const SkPoint verts[],
319 const SkPoint texs[], const SkColor colors[],
320 SkXfermode* xmode, const uint16_t indices[],
321 int indexCount, const SkPaint& paint)
322 {SkASSERT(0);}
323 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
324 const SkPaint&)
325 {SkASSERT(0);}
326 private:
327 virtual void flush();
328
junov@chromium.org77eec242012-07-18 17:54:45 +0000329 void endRecording();
330 void beginRecording();
331
332#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org77eec242012-07-18 17:54:45 +0000333 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000334 SkGPipeWriter fPipeWriter;
junov@chromium.org77eec242012-07-18 17:54:45 +0000335#else
junov@google.com4370aed2012-01-18 16:21:08 +0000336 SkPicture fPicture;
junov@chromium.org77eec242012-07-18 17:54:45 +0000337#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000338 SkDevice* fImmediateDevice;
339 SkCanvas* fImmediateCanvas;
340 SkCanvas* fRecordingCanvas;
341 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000342 bool fFreshFrame;
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000343 size_t fMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000344 };
345
346 DeferredDevice* getDeferredDevice() const;
347
348protected:
349 virtual SkCanvas* canvasForDrawIter();
350
351private:
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000352 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000353 bool isFullFrame(const SkRect*, const SkPaint*) const;
354 void validate() const;
355 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000356 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000357
358 typedef SkCanvas INHERITED;
359};
360
361
362#endif