1 /*
2  * Copyright 2012 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 "SkPixelRef.h"
13 
14 class SkDeferredDevice;
15 class SkImage;
16 class SkSurface;
17 
18 /** \class SkDeferredCanvas
19     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.
23     SkDeferredCanvas will transparently trigger the flushing of deferred
24     draw operations when an attempt is made to access the pixel data.
25 */
26 class SK_API SkDeferredCanvas : public SkCanvas {
27 public:
28     class SK_API NotificationClient;
29 
30     /** Construct a canvas with the specified surface to draw into.
31         This factory must be used for newImageSnapshot to work.
32         @param surface Specifies a surface for the canvas to draw into.
33      */
34     static SkDeferredCanvas* Create(SkSurface* surface);
35 
36 //    static SkDeferredCanvas* Create(SkBaseDevice* device);
37 
38     virtual ~SkDeferredCanvas();
39 
40     /**
41      *  Specify the surface to be used by this canvas. Calling setSurface will
42      *  release the previously set surface or device. Takes a reference on the
43      *  surface.
44      *
45      *  @param surface The surface that the canvas will raw into
46      *  @return The surface argument, for convenience.
47      */
48     SkSurface* setSurface(SkSurface* surface);
49 
50     /**
51      *  Specify a NotificationClient to be used by this canvas. Calling
52      *  setNotificationClient will release the previously set
53      *  NotificationClient, if any. SkDeferredCanvas does not take ownership
54      *  of the notification client.  Therefore user code is resposible
55      *  for its destruction.  The notification client must be unregistered
56      *  by calling setNotificationClient(NULL) if it is destroyed before
57      *  this canvas.
58      *  Note: Must be called after the device is set with setDevice.
59      *
60      *  @param notificationClient interface for dispatching notifications
61      *  @return The notificationClient argument, for convenience.
62      */
63     NotificationClient* setNotificationClient(NotificationClient* notificationClient);
64 
65     /**
66      *  Enable or disable deferred drawing. When deferral is disabled,
67      *  pending draw operations are immediately flushed and from then on,
68      *  the SkDeferredCanvas behaves just like a regular SkCanvas.
69      *  This method must not be called while the save/restore stack is in use.
70      *  @param deferred true/false
71      */
72     void setDeferredDrawing(bool deferred);
73 
74     /**
75      *  Returns true if deferred drawing is currenlty enabled.
76      */
77     bool isDeferredDrawing() const;
78 
79     /**
80      *  Returns true if the canvas contains a fresh frame.  A frame is
81      *  considered fresh when its content do not depend on the contents
82      *  of the previous frame. For example, if a canvas is cleared before
83      *  drawing each frame, the frames will all be considered fresh.
84      *  A frame is defined as the graphics image produced by as a result
85      *  of all the canvas draws operation executed between two successive
86      *  calls to isFreshFrame.  The result of isFreshFrame is computed
87      *  conservatively, so it may report false negatives.
88      */
89     bool isFreshFrame() const;
90 
91     /**
92      * Returns canvas's size.
93      */
94     SkISize getCanvasSize() const;
95 
96     /**
97      *  Returns true if the canvas has recorded draw commands that have
98      *  not yet been played back.
99      */
100     bool hasPendingCommands() const;
101 
102     /**
103      *  Flushes pending draw commands, if any, and returns an image of the
104      *  current state of the surface pixels up to this point. Subsequent
105      *  changes to the surface (by drawing into its canvas) will not be
106      *  reflected in this image.  Will return NULL if the deferred canvas
107      *  was not constructed from an SkSurface.
108      */
109     SkImage* newImageSnapshot();
110 
111     /**
112      *  Specify the maximum number of bytes to be allocated for the purpose
113      *  of recording draw commands to this canvas.  The default limit, is
114      *  64MB.
115      *  @param maxStorage The maximum number of bytes to be allocated.
116      */
117     void setMaxRecordingStorage(size_t maxStorage);
118 
119     /**
120      *  Returns the number of bytes currently allocated for the purpose of
121      *  recording draw commands.
122      */
123     size_t storageAllocatedForRecording() const;
124 
125     /**
126      * Attempt to reduce the storage allocated for recording by evicting
127      * cache resources.
128      * @param bytesToFree minimum number of bytes that should be attempted to
129      *   be freed.
130      * @return number of bytes actually freed.
131      */
132     size_t freeMemoryIfPossible(size_t bytesToFree);
133 
134     /**
135      * Specifies the maximum size (in bytes) allowed for a given image to be
136      * rendered using the deferred canvas.
137      */
138     void setBitmapSizeThreshold(size_t sizeThreshold);
getBitmapSizeThreshold()139     size_t getBitmapSizeThreshold() const { return fBitmapSizeThreshold; }
140 
141     /**
142      * Executes all pending commands without drawing
143      */
144     void silentFlush();
145 
146     SkDrawFilter* setDrawFilter(SkDrawFilter* filter) override;
147 
148 protected:
149     void willSave() override;
150     SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) override;
151     void willRestore() override;
152 
153     void didConcat(const SkMatrix&) override;
154     void didSetMatrix(const SkMatrix&) override;
155 
156     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
157     virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
158                             const SkPaint&) override;
159     virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
160                                const SkPaint&) override;
161     virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
162                                 SkScalar constY, const SkPaint&) override;
163     virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
164                                   const SkMatrix* matrix, const SkPaint&) override;
165     virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
166                                 const SkPaint& paint) override;
167     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
168                              const SkPoint texCoords[4], SkXfermode* xmode,
169                              const SkPaint& paint) override;
170 
171     void onDrawPaint(const SkPaint&) override;
172     void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;
173     void onDrawRect(const SkRect&, const SkPaint&) override;
174     void onDrawOval(const SkRect&, const SkPaint&) override;
175     void onDrawRRect(const SkRRect&, const SkPaint&) override;
176     void onDrawPath(const SkPath&, const SkPaint&) override;
177     void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;
178     void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,
179                           DrawBitmapRectFlags flags) override;
180     void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;
181     void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,
182                          const SkPaint*) override;
183     void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
184                           const SkPaint*) override;
185     void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*) override;
186     void onDrawVertices(VertexMode vmode, int vertexCount,
187                         const SkPoint vertices[], const SkPoint texs[],
188                         const SkColor colors[], SkXfermode* xmode,
189                         const uint16_t indices[], int indexCount,
190                         const SkPaint&) override;
191 
192     void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) override;
193     void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) override;
194     void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) override;
195     void onClipRegion(const SkRegion&, SkRegion::Op) override;
196 
197     void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
198 
199 public:
200     class NotificationClient {
201     public:
~NotificationClient()202         virtual ~NotificationClient() {}
203 
204         /**
205          *  Called before executing one or several draw commands, which means
206          *  once per flush when deferred rendering is enabled.
207          */
prepareForDraw()208         virtual void prepareForDraw() {}
209 
210         /**
211          *  Called after a recording a draw command if additional memory
212          *  had to be allocated for recording.
213          *  @param newAllocatedStorage same value as would be returned by
214          *      storageAllocatedForRecording(), for convenience.
215          */
storageAllocatedForRecordingChanged(size_t)216         virtual void storageAllocatedForRecordingChanged(size_t /*newAllocatedStorage*/) {}
217 
218         /**
219          *  Called after pending draw commands have been flushed
220          */
flushedDrawCommands()221         virtual void flushedDrawCommands() {}
222 
223         /**
224          *  Called after pending draw commands have been skipped, meaning
225          *  that they were optimized-out because the canvas is cleared
226          *  or completely overwritten by the command currently being recorded.
227          */
skippedPendingDrawCommands()228         virtual void skippedPendingDrawCommands() {}
229     };
230 
231 protected:
232     SkCanvas* canvasForDrawIter() override;
233     SkDeferredDevice* getDeferredDevice() const;
234 
235 private:
236     SkDeferredCanvas(SkDeferredDevice*);
237 
238     void recordedDrawCommand();
239     SkCanvas* drawingCanvas() const;
240     SkCanvas* immediateCanvas() const;
241     bool isFullFrame(const SkRect*, const SkPaint*) const;
242     void validate() const;
243     void init();
244 
245 
246     int fSaveLevel;
247     int fFirstSaveLayerIndex;
248     size_t fBitmapSizeThreshold;
249     bool   fDeferredDrawing;
250 
251     mutable SkISize fCachedCanvasSize;
252     mutable bool    fCachedCanvasSizeDirty;
253 
254     friend class SkDeferredCanvasTester; // for unit testing
255     typedef SkCanvas INHERITED;
256 };
257 
258 
259 #endif
260