blob: 01a71140fa38d571611b382431c2f4c89ea7f347 [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
11#include "SkCanvas.h"
12#include "SkDevice.h"
junov@google.com4370aed2012-01-18 16:21:08 +000013#include "SkPixelRef.h"
14
junov@chromium.org77eec242012-07-18 17:54:45 +000015#include "SkGPipe.h"
16#include "SkChunkAlloc.h"
junov@chromium.org77eec242012-07-18 17:54:45 +000017
junov@google.com4370aed2012-01-18 16:21:08 +000018/** \class SkDeferredCanvas
junov@chromium.org77eec242012-07-18 17:54:45 +000019 Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred
20 drawing. The main difference between this class and SkPictureRecord (the
21 canvas provided by SkPicture) is that this is a full drop-in replacement
22 for SkCanvas, while SkPictureRecord only supports draw operations.
junov@google.com4370aed2012-01-18 16:21:08 +000023 SkDeferredCanvas will transparently trigger the flushing of deferred
vandebo@chromium.org74b46192012-01-28 01:45:11 +000024 draw operations when an attempt is made to access the pixel data.
junov@google.com4370aed2012-01-18 16:21:08 +000025*/
26class SK_API SkDeferredCanvas : public SkCanvas {
27public:
28 class DeviceContext;
29
30 SkDeferredCanvas();
31
32 /** Construct a canvas with the specified device to draw into.
33 Equivalent to calling default constructor, then setDevice.
34 @param device Specifies a device for the canvas to draw into.
35 */
36 explicit SkDeferredCanvas(SkDevice* device);
37
38 /** Construct a canvas with the specified device to draw into, and
39 * a device context. Equivalent to calling default constructor, then
40 * setDevice.
41 * @param device Specifies a device for the canvas to draw into.
42 * @param deviceContext interface for the device's the graphics context
43 */
44 explicit SkDeferredCanvas(SkDevice* device, DeviceContext* deviceContext);
45
46 virtual ~SkDeferredCanvas();
47
48 /**
49 * Specify a device to be used by this canvas. Calling setDevice will
50 * release the previously set device, if any.
51 *
52 * @param device The device that the canvas will raw into
53 * @return The device argument, for convenience.
54 */
55 virtual SkDevice* setDevice(SkDevice* device);
56
57 /**
vandebo@chromium.org74b46192012-01-28 01:45:11 +000058 * Specify a deviceContext to be used by this canvas. Calling
junov@google.com4370aed2012-01-18 16:21:08 +000059 * setDeviceContext will release the previously set deviceContext, if any.
60 * A deviceContext must be specified if the device uses a graphics context
vandebo@chromium.org74b46192012-01-28 01:45:11 +000061 * that requires some form of state initialization prior to drawing
junov@google.com4370aed2012-01-18 16:21:08 +000062 * and/or explicit flushing to synchronize the execution of rendering
vandebo@chromium.org74b46192012-01-28 01:45:11 +000063 * operations.
junov@google.com4370aed2012-01-18 16:21:08 +000064 * Note: Must be called after the device is set with setDevice.
65 *
66 * @deviceContext interface for the device's the graphics context
67 * @return The deviceContext argument, for convenience.
68 */
69 DeviceContext* setDeviceContext(DeviceContext* deviceContext);
70
71 /**
72 * Enable or disable deferred drawing. When deferral is disabled,
73 * pending draw operations are immediately flushed and from then on,
74 * the SkDeferredCanvas behaves just like a regular SkCanvas.
75 * This method must not be called while the save/restore stack is in use.
76 * @param deferred true/false
77 */
78 void setDeferredDrawing(bool deferred);
79
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000080 /**
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000081 * Returns true if deferred drawing is currenlty enabled.
82 */
83 bool isDeferredDrawing();
84
85 /**
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000086 * Specify the maximum number of bytes to be allocated for the purpose
87 * of recording draw commands to this canvas. The default limit, is
88 * 64MB.
89 * @param maxStorage The maximum number of bytes to be allocated.
90 */
91 void setMaxRecordingStorage(size_t maxStorage);
92
junov@chromium.org2e14ba82012-08-07 14:26:57 +000093 /**
94 * Returns the number of bytes currently allocated for the purpose of
95 * recording draw commands.
96 */
97 size_t storageAllocatedForRecording() const;
98
99 /**
100 * Attempt to reduce the storage allocated for recording by evicting
101 * cache resources.
102 * @param bytesToFree minimum number of bytes that should be attempted to
103 * be freed.
104 * @return number of bytes actually freed.
105 */
106 size_t freeMemoryIfPossible(size_t bytesToFree);
107
junov@google.com4370aed2012-01-18 16:21:08 +0000108 // Overrides of the SkCanvas interface
109 virtual int save(SaveFlags flags) SK_OVERRIDE;
110 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
111 SaveFlags flags) SK_OVERRIDE;
112 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000113 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000114 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
115 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
116 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
117 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
118 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
119 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000120 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
121 bool doAntiAlias) SK_OVERRIDE;
122 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
123 bool doAntiAlias) SK_OVERRIDE;
124 virtual bool clipRegion(const SkRegion& deviceRgn,
125 SkRegion::Op op) SK_OVERRIDE;
126 virtual void clear(SkColor) SK_OVERRIDE;
127 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
128 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
129 const SkPaint& paint) SK_OVERRIDE;
130 virtual void drawRect(const SkRect& rect, const SkPaint& paint)
131 SK_OVERRIDE;
132 virtual void drawPath(const SkPath& path, const SkPaint& paint)
133 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000134 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000135 SkScalar top, const SkPaint* paint)
136 SK_OVERRIDE;
137 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
138 const SkRect& dst, const SkPaint* paint)
139 SK_OVERRIDE;
140
141 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
142 const SkPaint* paint) SK_OVERRIDE;
143 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
144 const SkRect& dst, const SkPaint* paint)
145 SK_OVERRIDE;
146 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
147 const SkPaint* paint) SK_OVERRIDE;
148 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
149 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
150 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000151 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000152 SK_OVERRIDE;
153 virtual void drawPosTextH(const void* text, size_t byteLength,
154 const SkScalar xpos[], SkScalar constY,
155 const SkPaint& paint) SK_OVERRIDE;
156 virtual void drawTextOnPath(const void* text, size_t byteLength,
157 const SkPath& path, const SkMatrix* matrix,
158 const SkPaint& paint) SK_OVERRIDE;
159 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
160 virtual void drawVertices(VertexMode vmode, int vertexCount,
161 const SkPoint vertices[], const SkPoint texs[],
162 const SkColor colors[], SkXfermode* xmode,
163 const uint16_t indices[], int indexCount,
164 const SkPaint& paint) SK_OVERRIDE;
165 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
166 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
167
junov@google.com4370aed2012-01-18 16:21:08 +0000168public:
169 class DeviceContext : public SkRefCnt {
170 public:
reed@google.com563a3b42012-06-26 19:24:50 +0000171 SK_DECLARE_INST_COUNT(DeviceContext)
172
junov@google.com4370aed2012-01-18 16:21:08 +0000173 virtual void prepareForDraw() {}
reed@google.com563a3b42012-06-26 19:24:50 +0000174
175 private:
176 typedef SkRefCnt INHERITED;
junov@google.com4370aed2012-01-18 16:21:08 +0000177 };
178
junov@chromium.org77eec242012-07-18 17:54:45 +0000179protected:
180 class DeferredPipeController : public SkGPipeController {
181 public:
182 DeferredPipeController();
183 void setPlaybackCanvas(SkCanvas*);
184 virtual ~DeferredPipeController();
185 virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
186 virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
187 void playback();
188 void reset();
junov@chromium.org8317e172012-07-23 14:17:45 +0000189 bool hasRecorded() const { return fAllocator.blockCount() != 0; }
190 size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
junov@chromium.org77eec242012-07-18 17:54:45 +0000191 private:
192 enum {
193 kMinBlockSize = 4096
194 };
195 struct PipeBlock {
196 PipeBlock(void* block, size_t size) { fBlock = block, fSize = size; }
197 void* fBlock;
198 size_t fSize;
199 };
200 void* fBlock;
201 size_t fBytesWritten;
202 SkChunkAlloc fAllocator;
203 SkTDArray<PipeBlock> fBlockList;
204 SkGPipeReader fReader;
205 };
junov@chromium.org77eec242012-07-18 17:54:45 +0000206
junov@google.com4370aed2012-01-18 16:21:08 +0000207public:
208 class DeferredDevice : public SkDevice {
209 public:
210 /**
211 * Constructor
212 * @param immediateDevice device to be drawn to when flushing
213 * deferred operations
214 * @param deviceContext callback interface for managing graphics
215 * context state, can be NULL.
216 */
217 DeferredDevice(SkDevice* immediateDevice,
218 DeviceContext* deviceContext = NULL);
219 ~DeferredDevice();
220
221 /**
222 * Sets the device context to be use with the device.
223 * @param deviceContext callback interface for managing graphics
224 * context state, can be NULL.
225 */
226 void setDeviceContext(DeviceContext* deviceContext);
227
228 /**
229 * Returns the recording canvas.
230 */
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000231 SkCanvas* recordingCanvas();
junov@google.com4370aed2012-01-18 16:21:08 +0000232
233 /**
234 * Returns the immediate (non deferred) canvas.
235 */
236 SkCanvas* immediateCanvas() const {return fImmediateCanvas;}
237
238 /**
239 * Returns the immediate (non deferred) device.
240 */
241 SkDevice* immediateDevice() const {return fImmediateDevice;}
242
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000243 /**
244 * Returns true if an opaque draw operation covering the entire canvas
245 * was performed since the last call to isFreshFrame().
246 */
247 bool isFreshFrame();
248
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000249 size_t storageAllocatedForRecording() const;
250 size_t freeMemoryIfPossible(size_t bytesToFree);
junov@google.com4370aed2012-01-18 16:21:08 +0000251 void flushPending();
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000252 void contentsCleared();
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000253 void setMaxRecordingStorage(size_t);
junov@google.com4370aed2012-01-18 16:21:08 +0000254
255 virtual uint32_t getDeviceCapabilities() SK_OVERRIDE;
256 virtual int width() const SK_OVERRIDE;
257 virtual int height() const SK_OVERRIDE;
258 virtual SkGpuRenderTarget* accessRenderTarget() SK_OVERRIDE;
259
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000260 virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config,
261 int width, int height,
junov@google.com4370aed2012-01-18 16:21:08 +0000262 bool isOpaque,
263 Usage usage) SK_OVERRIDE;
264
265 virtual void writePixels(const SkBitmap& bitmap, int x, int y,
266 SkCanvas::Config8888 config8888) SK_OVERRIDE;
267
268 protected:
junov@chromium.org1f9767c2012-02-07 16:27:57 +0000269 virtual const SkBitmap& onAccessBitmap(SkBitmap*) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000270 virtual bool onReadPixels(const SkBitmap& bitmap,
271 int x, int y,
272 SkCanvas::Config8888 config8888) SK_OVERRIDE;
273
274 // The following methods are no-ops on a deferred device
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000275 virtual bool filterTextFlags(const SkPaint& paint, TextFlags*)
junov@google.com4370aed2012-01-18 16:21:08 +0000276 SK_OVERRIDE
277 {return false;}
278 virtual void setMatrixClip(const SkMatrix&, const SkRegion&,
279 const SkClipStack&) SK_OVERRIDE
280 {}
junov@google.com4370aed2012-01-18 16:21:08 +0000281
282 // None of the following drawing methods should ever get called on the
283 // deferred device
284 virtual void clear(SkColor color)
285 {SkASSERT(0);}
286 virtual void drawPaint(const SkDraw&, const SkPaint& paint)
287 {SkASSERT(0);}
288 virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode,
289 size_t count, const SkPoint[],
290 const SkPaint& paint)
291 {SkASSERT(0);}
292 virtual void drawRect(const SkDraw&, const SkRect& r,
293 const SkPaint& paint)
294 {SkASSERT(0);}
295 virtual void drawPath(const SkDraw&, const SkPath& path,
296 const SkPaint& paint,
297 const SkMatrix* prePathMatrix = NULL,
298 bool pathIsMutable = false)
299 {SkASSERT(0);}
300 virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
301 const SkIRect* srcRectOrNull,
302 const SkMatrix& matrix, const SkPaint& paint)
303 {SkASSERT(0);}
304 virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
305 int x, int y, const SkPaint& paint)
306 {SkASSERT(0);}
307 virtual void drawText(const SkDraw&, const void* text, size_t len,
308 SkScalar x, SkScalar y, const SkPaint& paint)
309 {SkASSERT(0);}
310 virtual void drawPosText(const SkDraw&, const void* text, size_t len,
311 const SkScalar pos[], SkScalar constY,
312 int scalarsPerPos, const SkPaint& paint)
313 {SkASSERT(0);}
314 virtual void drawTextOnPath(const SkDraw&, const void* text,
315 size_t len, const SkPath& path,
316 const SkMatrix* matrix,
317 const SkPaint& paint)
318 {SkASSERT(0);}
319 virtual void drawPosTextOnPath(const SkDraw& draw, const void* text,
320 size_t len, const SkPoint pos[],
321 const SkPaint& paint,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000322 const SkPath& path,
junov@google.com4370aed2012-01-18 16:21:08 +0000323 const SkMatrix* matrix)
324 {SkASSERT(0);}
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000325 virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode,
junov@google.com4370aed2012-01-18 16:21:08 +0000326 int vertexCount, const SkPoint verts[],
327 const SkPoint texs[], const SkColor colors[],
328 SkXfermode* xmode, const uint16_t indices[],
329 int indexCount, const SkPaint& paint)
330 {SkASSERT(0);}
331 virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
332 const SkPaint&)
333 {SkASSERT(0);}
334 private:
335 virtual void flush();
336
junov@chromium.org77eec242012-07-18 17:54:45 +0000337 void endRecording();
338 void beginRecording();
339
junov@chromium.org77eec242012-07-18 17:54:45 +0000340 DeferredPipeController fPipeController;
junov@chromium.org6a0d0102012-07-19 21:00:07 +0000341 SkGPipeWriter fPipeWriter;
junov@google.com4370aed2012-01-18 16:21:08 +0000342 SkDevice* fImmediateDevice;
343 SkCanvas* fImmediateCanvas;
344 SkCanvas* fRecordingCanvas;
345 DeviceContext* fDeviceContext;
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000346 bool fFreshFrame;
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000347 size_t fMaxRecordingStorageBytes;
junov@google.com4370aed2012-01-18 16:21:08 +0000348 };
349
350 DeferredDevice* getDeferredDevice() const;
351
352protected:
353 virtual SkCanvas* canvasForDrawIter();
354
355private:
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000356 SkCanvas* drawingCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000357 bool isFullFrame(const SkRect*, const SkPaint*) const;
358 void validate() const;
359 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000360 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000361
362 typedef SkCanvas INHERITED;
363};
364
365
366#endif