blob: f9616055cdb1fe2d9fbb0424ce74d1795b0d0afb [file] [log] [blame]
junov@google.com4370aed2012-01-18 16:21:08 +00001/*
junov@chromium.org9ed02b92012-08-14 13:36:26 +00002 * Copyright 2012 Google Inc.
junov@google.com4370aed2012-01-18 16:21:08 +00003 *
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"
junov@google.com4370aed2012-01-18 16:21:08 +000012#include "SkPixelRef.h"
13
junov@chromium.org88e29142012-08-07 16:48:22 +000014class DeferredDevice;
junov@chromium.org67d74222013-04-12 13:33:01 +000015class SkImage;
16class SkSurface;
junov@chromium.org77eec242012-07-18 17:54:45 +000017
junov@chromium.org66070a52013-05-28 17:39:08 +000018#if !defined(SK_DEFERRED_CANVAS_USES_FACTORIES)
19// This is temporary, for rolling the API change into Chromium/Blink
20#define SK_DEFERRED_CANVAS_USES_FACTORIES 0
21#endif
22
junov@google.com4370aed2012-01-18 16:21:08 +000023/** \class SkDeferredCanvas
junov@chromium.org77eec242012-07-18 17:54:45 +000024 Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred
25 drawing. The main difference between this class and SkPictureRecord (the
26 canvas provided by SkPicture) is that this is a full drop-in replacement
27 for SkCanvas, while SkPictureRecord only supports draw operations.
junov@google.com4370aed2012-01-18 16:21:08 +000028 SkDeferredCanvas will transparently trigger the flushing of deferred
vandebo@chromium.org74b46192012-01-28 01:45:11 +000029 draw operations when an attempt is made to access the pixel data.
junov@google.com4370aed2012-01-18 16:21:08 +000030*/
31class SK_API SkDeferredCanvas : public SkCanvas {
32public:
junov@chromium.org9ed02b92012-08-14 13:36:26 +000033 class NotificationClient;
junov@google.com4370aed2012-01-18 16:21:08 +000034
junov@chromium.org66070a52013-05-28 17:39:08 +000035 /** Construct a canvas with the specified surface to draw into.
36 This factory must be used for newImageSnapshot to work.
37 @param surface Specifies a surface for the canvas to draw into.
38 */
39 static SkDeferredCanvas* Create(SkSurface* surface);
40
41#ifdef SK_DEVELOPER
42 static SkDeferredCanvas* Create(SkDevice* device); // Used for testing
43#endif
44
45#if !SK_DEFERRED_CANVAS_USES_FACTORIES
46 /** DEPRECATED
47 */
junov@google.com4370aed2012-01-18 16:21:08 +000048 SkDeferredCanvas();
49
junov@chromium.org66070a52013-05-28 17:39:08 +000050 /** DEPRACATED, use create instead
51 Construct a canvas with the specified device to draw into.
junov@google.com4370aed2012-01-18 16:21:08 +000052 Equivalent to calling default constructor, then setDevice.
53 @param device Specifies a device for the canvas to draw into.
54 */
55 explicit SkDeferredCanvas(SkDevice* device);
56
junov@chromium.org66070a52013-05-28 17:39:08 +000057 /** DEPRECATED, use create instead
58 Construct a canvas with the specified surface to draw into.
junov@chromium.org67d74222013-04-12 13:33:01 +000059 This constructor must be used for newImageSnapshot to work.
60 @param surface Specifies a surface for the canvas to draw into.
61 */
62 explicit SkDeferredCanvas(SkSurface* surface);
junov@chromium.org66070a52013-05-28 17:39:08 +000063#endif
junov@chromium.org67d74222013-04-12 13:33:01 +000064
junov@google.com4370aed2012-01-18 16:21:08 +000065 virtual ~SkDeferredCanvas();
66
junov@chromium.org66070a52013-05-28 17:39:08 +000067 /** DEPRECATED
junov@google.com4370aed2012-01-18 16:21:08 +000068 * Specify a device to be used by this canvas. Calling setDevice will
junov@chromium.org9ed02b92012-08-14 13:36:26 +000069 * release the previously set device, if any. Takes a reference on the
70 * device.
junov@google.com4370aed2012-01-18 16:21:08 +000071 *
72 * @param device The device that the canvas will raw into
73 * @return The device argument, for convenience.
74 */
75 virtual SkDevice* setDevice(SkDevice* device);
76
77 /**
junov@chromium.org7070f762013-05-24 17:13:00 +000078 * Specify the surface to be used by this canvas. Calling setSurface will
79 * release the previously set surface or device. Takes a reference on the
80 * surface.
81 *
82 * @param surface The surface that the canvas will raw into
83 * @return The surface argument, for convenience.
84 */
85 SkSurface* setSurface(SkSurface* surface);
86
87 /**
junov@chromium.org9ed02b92012-08-14 13:36:26 +000088 * Specify a NotificationClient to be used by this canvas. Calling
rmistry@google.comfbfcd562012-08-23 18:09:54 +000089 * setNotificationClient will release the previously set
junov@chromium.org52805482012-08-20 14:25:04 +000090 * NotificationClient, if any. SkDeferredCanvas does not take ownership
91 * of the notification client. Therefore user code is resposible
92 * for its destruction. The notification client must be unregistered
93 * by calling setNotificationClient(NULL) if it is destroyed before
94 * this canvas.
junov@google.com4370aed2012-01-18 16:21:08 +000095 * Note: Must be called after the device is set with setDevice.
96 *
junov@chromium.org9ed02b92012-08-14 13:36:26 +000097 * @param notificationClient interface for dispatching notifications
98 * @return The notificationClient argument, for convenience.
junov@google.com4370aed2012-01-18 16:21:08 +000099 */
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000100 NotificationClient* setNotificationClient(NotificationClient* notificationClient);
junov@google.com4370aed2012-01-18 16:21:08 +0000101
102 /**
103 * Enable or disable deferred drawing. When deferral is disabled,
104 * pending draw operations are immediately flushed and from then on,
105 * the SkDeferredCanvas behaves just like a regular SkCanvas.
106 * This method must not be called while the save/restore stack is in use.
107 * @param deferred true/false
108 */
109 void setDeferredDrawing(bool deferred);
110
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000111 /**
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000112 * Returns true if deferred drawing is currenlty enabled.
113 */
junov@chromium.org88e29142012-08-07 16:48:22 +0000114 bool isDeferredDrawing() const;
115
116 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000117 * Returns true if the canvas contains a fresh frame. A frame is
junov@chromium.org88e29142012-08-07 16:48:22 +0000118 * considered fresh when its content do not depend on the contents
119 * of the previous frame. For example, if a canvas is cleared before
120 * drawing each frame, the frames will all be considered fresh.
121 * A frame is defined as the graphics image produced by as a result
122 * of all the canvas draws operation executed between two successive
123 * calls to isFreshFrame. The result of isFreshFrame is computed
124 * conservatively, so it may report false negatives.
125 */
126 bool isFreshFrame() const;
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000127
128 /**
junov@chromium.orga38dfb62012-09-20 22:10:33 +0000129 * Returns true if the canvas has recorded draw commands that have
130 * not yet been played back.
131 */
132 bool hasPendingCommands() const;
133
134 /**
junov@chromium.org67d74222013-04-12 13:33:01 +0000135 * Flushes pending draw commands, if any, and returns an image of the
136 * current state of the surface pixels up to this point. Subsequent
137 * changes to the surface (by drawing into its canvas) will not be
138 * reflected in this image. Will return NULL if the deferred canvas
139 * was not constructed from an SkSurface.
140 */
junov@chromium.org5ee449a2013-04-12 20:20:50 +0000141 SkImage* newImageSnapshot();
junov@chromium.org67d74222013-04-12 13:33:01 +0000142
143 /**
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000144 * Specify the maximum number of bytes to be allocated for the purpose
145 * of recording draw commands to this canvas. The default limit, is
146 * 64MB.
147 * @param maxStorage The maximum number of bytes to be allocated.
148 */
149 void setMaxRecordingStorage(size_t maxStorage);
150
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000151 /**
152 * Returns the number of bytes currently allocated for the purpose of
153 * recording draw commands.
154 */
155 size_t storageAllocatedForRecording() const;
156
157 /**
158 * Attempt to reduce the storage allocated for recording by evicting
159 * cache resources.
160 * @param bytesToFree minimum number of bytes that should be attempted to
161 * be freed.
162 * @return number of bytes actually freed.
163 */
164 size_t freeMemoryIfPossible(size_t bytesToFree);
165
junov@chromium.orgfb103892012-09-20 19:35:43 +0000166 /**
sugoi@google.com7775fd52012-11-21 15:47:04 +0000167 * Specifies the maximum size (in bytes) allowed for a given image to be
168 * rendered using the deferred canvas.
169 */
170 void setBitmapSizeThreshold(size_t sizeThreshold);
171
172 /**
junov@chromium.orgfb103892012-09-20 19:35:43 +0000173 * Executes all pending commands without drawing
174 */
175 void silentFlush();
176
junov@google.com4370aed2012-01-18 16:21:08 +0000177 // Overrides of the SkCanvas interface
178 virtual int save(SaveFlags flags) SK_OVERRIDE;
179 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
180 SaveFlags flags) SK_OVERRIDE;
181 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000182 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000183 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
184 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
185 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
186 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
187 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
188 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000189 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
190 bool doAntiAlias) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000191 virtual bool clipRRect(const SkRRect& rect, SkRegion::Op op,
192 bool doAntiAlias) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000193 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
194 bool doAntiAlias) SK_OVERRIDE;
195 virtual bool clipRegion(const SkRegion& deviceRgn,
196 SkRegion::Op op) SK_OVERRIDE;
197 virtual void clear(SkColor) SK_OVERRIDE;
198 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
199 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
200 const SkPaint& paint) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000201 virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
202 virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
203 virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000204 virtual void drawPath(const SkPath& path, const SkPaint& paint)
205 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000206 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000207 SkScalar top, const SkPaint* paint)
208 SK_OVERRIDE;
reed@google.com71121732012-09-18 15:14:33 +0000209 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
junov@google.com4370aed2012-01-18 16:21:08 +0000210 const SkRect& dst, const SkPaint* paint)
211 SK_OVERRIDE;
212
213 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
214 const SkPaint* paint) SK_OVERRIDE;
215 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
216 const SkRect& dst, const SkPaint* paint)
217 SK_OVERRIDE;
218 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
219 const SkPaint* paint) SK_OVERRIDE;
220 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
221 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
222 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000223 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000224 SK_OVERRIDE;
225 virtual void drawPosTextH(const void* text, size_t byteLength,
226 const SkScalar xpos[], SkScalar constY,
227 const SkPaint& paint) SK_OVERRIDE;
228 virtual void drawTextOnPath(const void* text, size_t byteLength,
229 const SkPath& path, const SkMatrix* matrix,
230 const SkPaint& paint) SK_OVERRIDE;
231 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
232 virtual void drawVertices(VertexMode vmode, int vertexCount,
233 const SkPoint vertices[], const SkPoint texs[],
234 const SkColor colors[], SkXfermode* xmode,
235 const uint16_t indices[], int indexCount,
236 const SkPaint& paint) SK_OVERRIDE;
237 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
238 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
239
junov@google.com4370aed2012-01-18 16:21:08 +0000240public:
junov@chromium.org52805482012-08-20 14:25:04 +0000241 class NotificationClient {
junov@google.com4370aed2012-01-18 16:21:08 +0000242 public:
robertphillips@google.com59903972013-02-07 21:02:23 +0000243 virtual ~NotificationClient() {}
244
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000245 /**
246 * Called before executing one or several draw commands, which means
247 * once per flush when deferred rendering is enabled.
248 */
junov@google.com4370aed2012-01-18 16:21:08 +0000249 virtual void prepareForDraw() {}
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000250
251 /**
252 * Called after a recording a draw command if additional memory
253 * had to be allocated for recording.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000254 * @param newAllocatedStorage same value as would be returned by
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000255 * storageAllocatedForRecording(), for convenience.
256 */
257 virtual void storageAllocatedForRecordingChanged(
258 size_t newAllocatedStorage) {}
259
260 /**
261 * Called after pending draw commands have been flushed
262 */
263 virtual void flushedDrawCommands() {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000264
junov@google.com52a00ca2012-10-01 15:27:14 +0000265 /**
266 * Called after pending draw commands have been skipped, meaning
267 * that they were optimized-out because the canvas is cleared
268 * or completely overwritten by the command currently being recorded.
269 */
270 virtual void skippedPendingDrawCommands() {}
junov@google.com4370aed2012-01-18 16:21:08 +0000271 };
272
junov@chromium.org77eec242012-07-18 17:54:45 +0000273protected:
junov@google.com4370aed2012-01-18 16:21:08 +0000274 virtual SkCanvas* canvasForDrawIter();
junov@chromium.org88e29142012-08-07 16:48:22 +0000275 DeferredDevice* getDeferredDevice() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000276
277private:
junov@chromium.org66070a52013-05-28 17:39:08 +0000278 SkDeferredCanvas(DeferredDevice*);
279
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000280 void recordedDrawCommand();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000281 SkCanvas* drawingCanvas() const;
junov@chromium.org88e29142012-08-07 16:48:22 +0000282 SkCanvas* immediateCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000283 bool isFullFrame(const SkRect*, const SkPaint*) const;
284 void validate() const;
285 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000286 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000287
junov@chromium.org88e29142012-08-07 16:48:22 +0000288 friend class SkDeferredCanvasTester; // for unit testing
junov@google.com4370aed2012-01-18 16:21:08 +0000289 typedef SkCanvas INHERITED;
290};
291
292
293#endif