blob: bef26c029828df734f342377c4562e477db35812 [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.org7070f762013-05-24 17:13:00 +000057 * Specify the surface to be used by this canvas. Calling setSurface will
58 * release the previously set surface or device. Takes a reference on the
59 * surface.
60 *
61 * @param surface The surface that the canvas will raw into
62 * @return The surface argument, for convenience.
63 */
64 SkSurface* setSurface(SkSurface* surface);
65
66 /**
junov@chromium.org9ed02b92012-08-14 13:36:26 +000067 * Specify a NotificationClient to be used by this canvas. Calling
rmistry@google.comfbfcd562012-08-23 18:09:54 +000068 * setNotificationClient will release the previously set
junov@chromium.org52805482012-08-20 14:25:04 +000069 * NotificationClient, if any. SkDeferredCanvas does not take ownership
70 * of the notification client. Therefore user code is resposible
71 * for its destruction. The notification client must be unregistered
72 * by calling setNotificationClient(NULL) if it is destroyed before
73 * this canvas.
junov@google.com4370aed2012-01-18 16:21:08 +000074 * Note: Must be called after the device is set with setDevice.
75 *
junov@chromium.org9ed02b92012-08-14 13:36:26 +000076 * @param notificationClient interface for dispatching notifications
77 * @return The notificationClient argument, for convenience.
junov@google.com4370aed2012-01-18 16:21:08 +000078 */
junov@chromium.org9ed02b92012-08-14 13:36:26 +000079 NotificationClient* setNotificationClient(NotificationClient* notificationClient);
junov@google.com4370aed2012-01-18 16:21:08 +000080
81 /**
82 * Enable or disable deferred drawing. When deferral is disabled,
83 * pending draw operations are immediately flushed and from then on,
84 * the SkDeferredCanvas behaves just like a regular SkCanvas.
85 * This method must not be called while the save/restore stack is in use.
86 * @param deferred true/false
87 */
88 void setDeferredDrawing(bool deferred);
89
junov@chromium.orgbfeddae2012-07-23 13:35:14 +000090 /**
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +000091 * Returns true if deferred drawing is currenlty enabled.
92 */
junov@chromium.org88e29142012-08-07 16:48:22 +000093 bool isDeferredDrawing() const;
94
95 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +000096 * Returns true if the canvas contains a fresh frame. A frame is
junov@chromium.org88e29142012-08-07 16:48:22 +000097 * considered fresh when its content do not depend on the contents
98 * of the previous frame. For example, if a canvas is cleared before
99 * drawing each frame, the frames will all be considered fresh.
100 * A frame is defined as the graphics image produced by as a result
101 * of all the canvas draws operation executed between two successive
102 * calls to isFreshFrame. The result of isFreshFrame is computed
103 * conservatively, so it may report false negatives.
104 */
105 bool isFreshFrame() const;
junov@chromium.orgb10a6bd2012-07-25 17:27:13 +0000106
107 /**
junov@chromium.orga38dfb62012-09-20 22:10:33 +0000108 * Returns true if the canvas has recorded draw commands that have
109 * not yet been played back.
110 */
111 bool hasPendingCommands() const;
112
113 /**
junov@chromium.org67d74222013-04-12 13:33:01 +0000114 * Flushes pending draw commands, if any, and returns an image of the
115 * current state of the surface pixels up to this point. Subsequent
116 * changes to the surface (by drawing into its canvas) will not be
117 * reflected in this image. Will return NULL if the deferred canvas
118 * was not constructed from an SkSurface.
119 */
junov@chromium.org5ee449a2013-04-12 20:20:50 +0000120 SkImage* newImageSnapshot();
junov@chromium.org67d74222013-04-12 13:33:01 +0000121
122 /**
junov@chromium.orgbfeddae2012-07-23 13:35:14 +0000123 * Specify the maximum number of bytes to be allocated for the purpose
124 * of recording draw commands to this canvas. The default limit, is
125 * 64MB.
126 * @param maxStorage The maximum number of bytes to be allocated.
127 */
128 void setMaxRecordingStorage(size_t maxStorage);
129
junov@chromium.org2e14ba82012-08-07 14:26:57 +0000130 /**
131 * Returns the number of bytes currently allocated for the purpose of
132 * recording draw commands.
133 */
134 size_t storageAllocatedForRecording() const;
135
136 /**
137 * Attempt to reduce the storage allocated for recording by evicting
138 * cache resources.
139 * @param bytesToFree minimum number of bytes that should be attempted to
140 * be freed.
141 * @return number of bytes actually freed.
142 */
143 size_t freeMemoryIfPossible(size_t bytesToFree);
144
junov@chromium.orgfb103892012-09-20 19:35:43 +0000145 /**
sugoi@google.com7775fd52012-11-21 15:47:04 +0000146 * Specifies the maximum size (in bytes) allowed for a given image to be
147 * rendered using the deferred canvas.
148 */
149 void setBitmapSizeThreshold(size_t sizeThreshold);
150
151 /**
junov@chromium.orgfb103892012-09-20 19:35:43 +0000152 * Executes all pending commands without drawing
153 */
154 void silentFlush();
155
junov@google.com4370aed2012-01-18 16:21:08 +0000156 // Overrides of the SkCanvas interface
157 virtual int save(SaveFlags flags) SK_OVERRIDE;
158 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
159 SaveFlags flags) SK_OVERRIDE;
160 virtual void restore() SK_OVERRIDE;
junov@chromium.orga907ac32012-02-24 21:54:07 +0000161 virtual bool isDrawingToLayer() const SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000162 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
163 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
164 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
165 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
166 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
167 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000168 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
169 bool doAntiAlias) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000170 virtual bool clipRRect(const SkRRect& rect, SkRegion::Op op,
171 bool doAntiAlias) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000172 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
173 bool doAntiAlias) SK_OVERRIDE;
174 virtual bool clipRegion(const SkRegion& deviceRgn,
175 SkRegion::Op op) SK_OVERRIDE;
176 virtual void clear(SkColor) SK_OVERRIDE;
177 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
178 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
179 const SkPaint& paint) SK_OVERRIDE;
reed@google.com4ed0fb72012-12-12 20:48:18 +0000180 virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
181 virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
182 virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
junov@google.com4370aed2012-01-18 16:21:08 +0000183 virtual void drawPath(const SkPath& path, const SkPaint& paint)
184 SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000185 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
junov@google.com4370aed2012-01-18 16:21:08 +0000186 SkScalar top, const SkPaint* paint)
187 SK_OVERRIDE;
reed@google.com71121732012-09-18 15:14:33 +0000188 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
junov@google.com4370aed2012-01-18 16:21:08 +0000189 const SkRect& dst, const SkPaint* paint)
190 SK_OVERRIDE;
191
192 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
193 const SkPaint* paint) SK_OVERRIDE;
194 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
195 const SkRect& dst, const SkPaint* paint)
196 SK_OVERRIDE;
197 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
198 const SkPaint* paint) SK_OVERRIDE;
199 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
200 SkScalar y, const SkPaint& paint) SK_OVERRIDE;
201 virtual void drawPosText(const void* text, size_t byteLength,
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000202 const SkPoint pos[], const SkPaint& paint)
junov@google.com4370aed2012-01-18 16:21:08 +0000203 SK_OVERRIDE;
204 virtual void drawPosTextH(const void* text, size_t byteLength,
205 const SkScalar xpos[], SkScalar constY,
206 const SkPaint& paint) SK_OVERRIDE;
207 virtual void drawTextOnPath(const void* text, size_t byteLength,
208 const SkPath& path, const SkMatrix* matrix,
209 const SkPaint& paint) SK_OVERRIDE;
210 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
211 virtual void drawVertices(VertexMode vmode, int vertexCount,
212 const SkPoint vertices[], const SkPoint texs[],
213 const SkColor colors[], SkXfermode* xmode,
214 const uint16_t indices[], int indexCount,
215 const SkPaint& paint) SK_OVERRIDE;
216 virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
217 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
218
junov@google.com4370aed2012-01-18 16:21:08 +0000219public:
junov@chromium.org52805482012-08-20 14:25:04 +0000220 class NotificationClient {
junov@google.com4370aed2012-01-18 16:21:08 +0000221 public:
robertphillips@google.com59903972013-02-07 21:02:23 +0000222 virtual ~NotificationClient() {}
223
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000224 /**
225 * Called before executing one or several draw commands, which means
226 * once per flush when deferred rendering is enabled.
227 */
junov@google.com4370aed2012-01-18 16:21:08 +0000228 virtual void prepareForDraw() {}
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000229
230 /**
231 * Called after a recording a draw command if additional memory
232 * had to be allocated for recording.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000233 * @param newAllocatedStorage same value as would be returned by
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000234 * storageAllocatedForRecording(), for convenience.
235 */
236 virtual void storageAllocatedForRecordingChanged(
237 size_t newAllocatedStorage) {}
238
239 /**
240 * Called after pending draw commands have been flushed
241 */
242 virtual void flushedDrawCommands() {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000243
junov@google.com52a00ca2012-10-01 15:27:14 +0000244 /**
245 * Called after pending draw commands have been skipped, meaning
246 * that they were optimized-out because the canvas is cleared
247 * or completely overwritten by the command currently being recorded.
248 */
249 virtual void skippedPendingDrawCommands() {}
junov@google.com4370aed2012-01-18 16:21:08 +0000250 };
251
junov@chromium.org77eec242012-07-18 17:54:45 +0000252protected:
junov@google.com4370aed2012-01-18 16:21:08 +0000253 virtual SkCanvas* canvasForDrawIter();
junov@chromium.org88e29142012-08-07 16:48:22 +0000254 DeferredDevice* getDeferredDevice() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000255
256private:
junov@chromium.org9ed02b92012-08-14 13:36:26 +0000257 void recordedDrawCommand();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000258 SkCanvas* drawingCanvas() const;
junov@chromium.org88e29142012-08-07 16:48:22 +0000259 SkCanvas* immediateCanvas() const;
junov@google.com4370aed2012-01-18 16:21:08 +0000260 bool isFullFrame(const SkRect*, const SkPaint*) const;
261 void validate() const;
262 void init();
junov@chromium.org5e5a0952012-02-28 15:27:59 +0000263 bool fDeferredDrawing;
junov@google.com4370aed2012-01-18 16:21:08 +0000264
junov@chromium.org88e29142012-08-07 16:48:22 +0000265 friend class SkDeferredCanvasTester; // for unit testing
junov@google.com4370aed2012-01-18 16:21:08 +0000266 typedef SkCanvas INHERITED;
267};
268
269
270#endif