blob: 38ee67815246c360ca982284e4f4ed57ab579ae9 [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
88 // Overrides of the SkCanvas interface
89 virtual int save(SaveFlags flags) SK_OVERRIDE;
90 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
91 SaveFlags flags) SK_OVERRIDE;
92 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +000093 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +000094 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
95 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
96 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
97 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
98 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
99 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000100 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
101 bool doAntiAlias) SK_OVERRIDE;
102 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
103 bool doAntiAlias) SK_OVERRIDE;
104 virtual bool clipRegion(const SkRegion& deviceRgn,
105 SkRegion::Op op) SK_OVERRIDE;
106 virtual void clear(SkColor) SK_OVERRIDE;
107 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
108 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
109 const SkPaint& paint) SK_OVERRIDE;
110 virtual void drawRect(const SkRect& rect, const SkPaint& paint)
111 SK_OVERRIDE;
112 virtual void drawPath(const SkPath& path, const SkPaint& paint)
113 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000114 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000115 SkScalar top, const SkPaint* paint)
116 SK_OVERRIDE;
117 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
118 const SkRect& dst, const SkPaint* paint)
119 SK_OVERRIDE;
120
121 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
122 const SkPaint* paint) SK_OVERRIDE;
123 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
124 const SkRect& dst, const SkPaint* paint)
125 SK_OVERRIDE;
126 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
127 const SkPaint* paint) SK_OVERRIDE;
128 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
129 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
130 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000131 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000132 SK_OVERRIDE;
133 virtual void drawPosTextH(const void* text, size_t byteLength,
134 const SkScalar xpos[], SkScalar constY,
135 const SkPaint& paint) SK_OVERRIDE;
136 virtual void drawTextOnPath(const void* text, size_t byteLength,
137 const SkPath& path, const SkMatrix* matrix,
138 const SkPaint& paint) SK_OVERRIDE;
139 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
140 virtual void drawVertices(VertexMode vmode, int vertexCount,
141 const SkPoint vertices[], const SkPoint texs[],
142 const SkColor colors[], SkXfermode* xmode,
143 const uint16_t indices[], int indexCount,
144 const SkPaint& paint) SK_OVERRIDE;
145 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
146 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
147
148private:
149 void flushIfNeeded(const SkBitmap& bitmap);
150
151public:
152 class DeviceContext : public SkRefCnt {
153 public:
reed@google.com563a3b42012-06-26 19:24:50 +0000154 SK_DECLARE_INST_COUNT(DeviceContext)
155
junov@google.com4370aed2012-01-18 16:21:08 +0000156 virtual void prepareForDraw() {}
reed@google.com563a3b42012-06-26 19:24:50 +0000157
158 private:
159 typedef SkRefCnt INHERITED;
junov@google.com4370aed2012-01-18 16:21:08 +0000160 };
161
junov@chromium.org77eec242012-07-18 17:54:45 +0000162#if SK_DEFERRED_CANVAS_USES_GPIPE
163protected:
164 class DeferredPipeController : public SkGPipeController {
165 public:
166 DeferredPipeController();
167 void setPlaybackCanvas(SkCanvas*);
168 virtual ~DeferredPipeController();
169 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
170 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
171 void playback();
172 void reset();
173 bool hasRecorded() {return fAllocator.blockCount() != 0;}
174 private:
175 enum {
176 kMinBlockSize = 4096
177 };
178 struct PipeBlock {
179 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
180 void* fBlock;
181 size_t fSize;
182 };
183 void* fBlock;
184 size_t fBytesWritten;
185 SkChunkAlloc fAllocator;
186 SkTDArray<PipeBlock> fBlockList;
187 SkGPipeReader fReader;
188 };
189#endif
190
junov@google.com4370aed2012-01-18 16:21:08 +0000191public:
192 class DeferredDevice : public SkDevice {
193 public:
194 /**
195 * Constructor
196 * @param immediateDevice device to be drawn to when flushing
197 * deferred operations
198 * @param deviceContext callback interface for managing graphics
199 * context state, can be NULL.
200 */
201 DeferredDevice(SkDevice* immediateDevice,
202 DeviceContext* deviceContext = NULL);
203 ~DeferredDevice();
204
205 /**
206 * Sets the device context to be use with the device.
207 * @param deviceContext callback interface for managing graphics
208 * context state, can be NULL.
209 */
210 void setDeviceContext(DeviceContext* deviceContext);
211
212 /**
213 * Returns the recording canvas.
214 */
215 SkCanvas* recordingCanvas() const {return fRecordingCanvas;}
216
217 /**
218 * Returns the immediate (non deferred) canvas.
219 */
220 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
221
222 /**
223 * Returns the immediate (non deferred) device.
224 */
225 SkDevice* immediateDevice() const {return fImmediateDevice;}
226
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000227 /**
228 * Returns true if an opaque draw operation covering the entire canvas
229 * was performed since the last call to isFreshFrame().
230 */
231 bool isFreshFrame();
232
junov@google.com4370aed2012-01-18 16:21:08 +0000233 void flushPending();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000234 void contentsCleared();
junov@google.com4370aed2012-01-18 16:21:08 +0000235 void flushIfNeeded(const SkBitmap& bitmap);
236
237 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
238 virtual int width() const SK_OVERRIDE;
239 virtual int height() const SK_OVERRIDE;
240 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
241
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000242 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
243 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000244 bool isOpaque,
245 Usage usage) SK_OVERRIDE;
246
247 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
248 SkCanvas::Config8888 config8888) SK_OVERRIDE;
249
250 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000251 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000252 virtual bool onReadPixels(const SkBitmap& bitmap,
253 int x, int y,
254 SkCanvas::Config8888 config8888) SK_OVERRIDE;
255
256 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000257 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000258 SK_OVERRIDE
259 {return false;}
260 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
261 const SkClipStack&) SK_OVERRIDE
262 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000263
264 // None of the following drawing methods should ever get called on the
265 // deferred device
266 virtual void clear(SkColor color)
267 {SkASSERT(0);}
268 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
269 {SkASSERT(0);}
270 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
271 size_t count, const SkPoint[],
272 const SkPaint& paint)
273 {SkASSERT(0);}
274 virtual void drawRect(const SkDraw&, const SkRect& r,
275 const SkPaint& paint)
276 {SkASSERT(0);}
277 virtual void drawPath(const SkDraw&, const SkPath& path,
278 const SkPaint& paint,
279 const SkMatrix* prePathMatrix = NULL,
280 bool pathIsMutable = false)
281 {SkASSERT(0);}
282 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
283 const SkIRect* srcRectOrNull,
284 const SkMatrix& matrix, const SkPaint& paint)
285 {SkASSERT(0);}
286 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
287 int x, int y, const SkPaint& paint)
288 {SkASSERT(0);}
289 virtual void drawText(const SkDraw&, const void* text, size_t len,
290 SkScalar x, SkScalar y, const SkPaint& paint)
291 {SkASSERT(0);}
292 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
293 const SkScalar pos[], SkScalar constY,
294 int scalarsPerPos, const SkPaint& paint)
295 {SkASSERT(0);}
296 virtual void drawTextOnPath(const SkDraw&, const void* text,
297 size_t len, const SkPath& path,
298 const SkMatrix* matrix,
299 const SkPaint& paint)
300 {SkASSERT(0);}
301 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
302 size_t len, const SkPoint pos[],
303 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000304 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000305 const SkMatrix* matrix)
306 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000307 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000308 int vertexCount, const SkPoint verts[],
309 const SkPoint texs[], const SkColor colors[],
310 SkXfermode* xmode, const uint16_t indices[],
311 int indexCount, const SkPaint& paint)
312 {SkASSERT(0);}
313 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
314 const SkPaint&)
315 {SkASSERT(0);}
316 private:
317 virtual void flush();
318
junov@chromium.org77eec242012-07-18 17:54:45 +0000319 void endRecording();
320 void beginRecording();
321
322#if SK_DEFERRED_CANVAS_USES_GPIPE
junov@chromium.org77eec242012-07-18 17:54:45 +0000323 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000324 SkGPipeWriter fPipeWriter;
junov@chromium.org77eec242012-07-18 17:54:45 +0000325#else
junov@google.com4370aed2012-01-18 16:21:08 +0000326 SkPicture fPicture;
junov@chromium.org77eec242012-07-18 17:54:45 +0000327#endif
junov@google.com4370aed2012-01-18 16:21:08 +0000328 SkDevice* fImmediateDevice;
329 SkCanvas* fImmediateCanvas;
330 SkCanvas* fRecordingCanvas;
331 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000332 bool fFreshFrame;
junov@google.com4370aed2012-01-18 16:21:08 +0000333 };
334
335 DeferredDevice* getDeferredDevice() const;
336
337protected:
338 virtual SkCanvas* canvasForDrawIter();
339
340private:
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000341 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000342 bool isFullFrame(const SkRect*, const SkPaint*) const;
343 void validate() const;
344 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000345 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000346
347 typedef SkCanvas INHERITED;
348};
349
350
351#endif