blob: 97b4a66517cf73dd66567c326d1216c195ad6c39 [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@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:
junov@chromium.org9ed02b92012-08-14 13:36:26 +000028 class NotificationClient;
junov@google.com4370aed2012-01-18 16:21:08 +000029
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
junov@chromium.org67d74222013-04-12 13:33:01 +000038 /** Construct a canvas with the specified surface to draw into.
39 This constructor must be used for newImageSnapshot to work.
40 @param surface Specifies a surface for the canvas to draw into.
41 */
42 explicit SkDeferredCanvas(SkSurface* surface);
43
junov@google.com4370aed2012-01-18 16:21:08 +000044 virtual ~SkDeferredCanvas();
45
46 /**
47 * Specify a device to be used by this canvas. Calling setDevice will
junov@chromium.org9ed02b92012-08-14 13:36:26 +000048 * release the previously set device, if any. Takes a reference on the
49 * device.
junov@google.com4370aed2012-01-18 16:21:08 +000050 *
51 * @param device The device that the canvas will raw into
52 * @return The device argument, for convenience.
53 */
54 virtual SkDevice* setDevice(SkDevice* device);
55
56 /**
junov@chromium.org9ed02b92012-08-14 13:36:26 +000057 * Specify a NotificationClient to be used by this canvas. Calling
rmistry@google.comfbfcd562012-08-23 18:09:54 +000058 * setNotificationClient will release the previously set
junov@chromium.org52805482012-08-20 14:25:04 +000059 * NotificationClient, if any. SkDeferredCanvas does not take ownership
60 * of the notification client. Therefore user code is resposible
61 * for its destruction. The notification client must be unregistered
62 * by calling setNotificationClient(NULL) if it is destroyed before
63 * this canvas.
junov@google.com4370aed2012-01-18 16:21:08 +000064 * Note: Must be called after the device is set with setDevice.
65 *
junov@chromium.org9ed02b92012-08-14 13:36:26 +000066 * @param notificationClient interface for dispatching notifications
67 * @return The notificationClient argument, for convenience.
junov@google.com4370aed2012-01-18 16:21:08 +000068 */
junov@chromium.org9ed02b92012-08-14 13:36:26 +000069 NotificationClient* setNotificationClient(NotificationClient* notificationClient);
junov@google.com4370aed2012-01-18 16:21:08 +000070
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 */
junov@chromium.org88e29142012-08-07 16:48:22 +000083 bool isDeferredDrawing() const;
84
85 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +000086 * Returns true if the canvas contains a fresh frame. A frame is
junov@chromium.org88e29142012-08-07 16:48:22 +000087 * considered fresh when its content do not depend on the contents
88 * of the previous frame. For example, if a canvas is cleared before
89 * drawing each frame, the frames will all be considered fresh.
90 * A frame is defined as the graphics image produced by as a result
91 * of all the canvas draws operation executed between two successive
92 * calls to isFreshFrame. The result of isFreshFrame is computed
93 * conservatively, so it may report false negatives.
94 */
95 bool isFreshFrame() const;
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000096
97 /**
junov@chromium.orga38dfb62012-09-20 22:10:33 +000098 * Returns true if the canvas has recorded draw commands that have
99 * not yet been played back.
100 */
101 bool hasPendingCommands() const;
102
103 /**
junov@chromium.org67d74222013-04-12 13:33:01 +0000104 * Flushes pending draw commands, if any, and returns an image of the
105 * current state of the surface pixels up to this point. Subsequent
106 * changes to the surface (by drawing into its canvas) will not be
107 * reflected in this image. Will return NULL if the deferred canvas
108 * was not constructed from an SkSurface.
109 */
110 SkImage* newImageShapshot();
111
112 /**
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000113 * Specify the maximum number of bytes to be allocated for the purpose
114 * of recording draw commands to this canvas. The default limit, is
115 * 64MB.
116 * @param maxStorage The maximum number of bytes to be allocated.
117 */
118 void setMaxRecordingStorage(size_t maxStorage);
119
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000120 /**
121 * Returns the number of bytes currently allocated for the purpose of
122 * recording draw commands.
123 */
124 size_t storageAllocatedForRecording() const;
125
126 /**
127 * Attempt to reduce the storage allocated for recording by evicting
128 * cache resources.
129 * @param bytesToFree minimum number of bytes that should be attempted to
130 * be freed.
131 * @return number of bytes actually freed.
132 */
133 size_t freeMemoryIfPossible(size_t bytesToFree);
134
junov@chromium.orgfb103892012-09-20 19:35:43 +0000135 /**
sugoi@google.com7775fd52012-11-21 15:47:04 +0000136 * Specifies the maximum size (in bytes) allowed for a given image to be
137 * rendered using the deferred canvas.
138 */
139 void setBitmapSizeThreshold(size_t sizeThreshold);
140
141 /**
junov@chromium.orgfb103892012-09-20 19:35:43 +0000142 * Executes all pending commands without drawing
143 */
144 void silentFlush();
145
junov@google.com4370aed2012-01-18 16:21:08 +0000146 // Overrides of the SkCanvas interface
147 virtual int save(SaveFlags flags) SK_OVERRIDE;
148 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
149 SaveFlags flags) SK_OVERRIDE;
150 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000151 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000152 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
153 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
154 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
155 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
156 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
157 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000158 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
159 bool doAntiAlias) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000160 virtual bool clipRRect(const SkRRect& rect, SkRegion::Op op,
161 bool doAntiAlias) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000162 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
163 bool doAntiAlias) SK_OVERRIDE;
164 virtual bool clipRegion(const SkRegion& deviceRgn,
165 SkRegion::Op op) SK_OVERRIDE;
166 virtual void clear(SkColor) SK_OVERRIDE;
167 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
168 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
169 const SkPaint& paint) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000170 virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
171 virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
172 virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000173 virtual void drawPath(const SkPath& path, const SkPaint& paint)
174 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000175 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000176 SkScalar top, const SkPaint* paint)
177 SK_OVERRIDE;
reed@google.com71121732012-09-18 15:14:33 +0000178 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
junov@google.com4370aed2012-01-18 16:21:08 +0000179 const SkRect& dst, const SkPaint* paint)
180 SK_OVERRIDE;
181
182 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
183 const SkPaint* paint) SK_OVERRIDE;
184 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
185 const SkRect& dst, const SkPaint* paint)
186 SK_OVERRIDE;
187 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
188 const SkPaint* paint) SK_OVERRIDE;
189 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
190 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
191 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000192 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000193 SK_OVERRIDE;
194 virtual void drawPosTextH(const void* text, size_t byteLength,
195 const SkScalar xpos[], SkScalar constY,
196 const SkPaint& paint) SK_OVERRIDE;
197 virtual void drawTextOnPath(const void* text, size_t byteLength,
198 const SkPath& path, const SkMatrix* matrix,
199 const SkPaint& paint) SK_OVERRIDE;
200 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
201 virtual void drawVertices(VertexMode vmode, int vertexCount,
202 const SkPoint vertices[], const SkPoint texs[],
203 const SkColor colors[], SkXfermode* xmode,
204 const uint16_t indices[], int indexCount,
205 const SkPaint& paint) SK_OVERRIDE;
206 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
207 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
208
junov@google.com4370aed2012-01-18 16:21:08 +0000209public:
junov@chromium.org52805482012-08-20 14:25:04 +0000210 class NotificationClient {
junov@google.com4370aed2012-01-18 16:21:08 +0000211 public:
robertphillips@google.com59903972013-02-07 21:02:23 +0000212 virtual ~NotificationClient() {}
213
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000214 /**
215 * Called before executing one or several draw commands, which means
216 * once per flush when deferred rendering is enabled.
217 */
junov@google.com4370aed2012-01-18 16:21:08 +0000218 virtual void prepareForDraw() {}
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000219
220 /**
221 * Called after a recording a draw command if additional memory
222 * had to be allocated for recording.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000223 * @param newAllocatedStorage same value as would be returned by
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000224 * storageAllocatedForRecording(), for convenience.
225 */
226 virtual void storageAllocatedForRecordingChanged(
227 size_t newAllocatedStorage) {}
228
229 /**
230 * Called after pending draw commands have been flushed
231 */
232 virtual void flushedDrawCommands() {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000233
junov@google.com52a00ca2012-10-01 15:27:14 +0000234 /**
235 * Called after pending draw commands have been skipped, meaning
236 * that they were optimized-out because the canvas is cleared
237 * or completely overwritten by the command currently being recorded.
238 */
239 virtual void skippedPendingDrawCommands() {}
junov@google.com4370aed2012-01-18 16:21:08 +0000240 };
241
junov@chromium.org77eec242012-07-18 17:54:45 +0000242protected:
junov@google.com4370aed2012-01-18 16:21:08 +0000243 virtual SkCanvas* canvasForDrawIter();
junov@chromium.org88e29142012-08-07 16:48:22 +0000244 DeferredDevice* getDeferredDevice() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000245
246private:
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000247 void recordedDrawCommand();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000248 SkCanvas* drawingCanvas() const;
junov@chromium.org88e29142012-08-07 16:48:22 +0000249 SkCanvas* immediateCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000250 bool isFullFrame(const SkRect*, const SkPaint*) const;
251 void validate() const;
252 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000253 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000254
junov@chromium.org88e29142012-08-07 16:48:22 +0000255 friend class SkDeferredCanvasTester; // for unit testing
junov@google.com4370aed2012-01-18 16:21:08 +0000256 typedef SkCanvas INHERITED;
257};
258
259
260#endif