SkDeferredCanvas.h revision 25c1408c3da9ca90509b84f21a1161ef40052bd1
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
14class DeferredDevice;
15
16/** \class SkDeferredCanvas
17    Subclass of SkCanvas that encapsulates an SkPicture or SkGPipe for deferred
18    drawing. The main difference between this class and SkPictureRecord (the
19    canvas provided by SkPicture) is that this is a full drop-in replacement
20    for SkCanvas, while SkPictureRecord only supports draw operations.
21    SkDeferredCanvas will transparently trigger the flushing of deferred
22    draw operations when an attempt is made to access the pixel data.
23*/
24class SK_API SkDeferredCanvas : public SkCanvas {
25public:
26    class NotificationClient;
27
28    SkDeferredCanvas();
29
30    /** Construct a canvas with the specified device to draw into.
31        Equivalent to calling default constructor, then setDevice.
32        @param device Specifies a device for the canvas to draw into.
33    */
34    explicit SkDeferredCanvas(SkDevice* device);
35
36    virtual ~SkDeferredCanvas();
37
38    /**
39     *  Specify a device to be used by this canvas. Calling setDevice will
40     *  release the previously set device, if any. Takes a reference on the
41     *  device.
42     *
43     *  @param device The device that the canvas will raw into
44     *  @return The device argument, for convenience.
45     */
46    virtual SkDevice* setDevice(SkDevice* device);
47
48    /**
49     *  Specify a NotificationClient to be used by this canvas. Calling
50     *  setNotificationClient will release the previously set
51     *  NotificationClient, if any. SkDeferredCanvas does not take ownership
52     *  of the notification client.  Therefore user code is resposible
53     *  for its destruction.  The notification client must be unregistered
54     *  by calling setNotificationClient(NULL) if it is destroyed before
55     *  this canvas.
56     *  Note: Must be called after the device is set with setDevice.
57     *
58     *  @param notificationClient interface for dispatching notifications
59     *  @return The notificationClient argument, for convenience.
60     */
61    NotificationClient* setNotificationClient(NotificationClient* notificationClient);
62
63    /**
64     *  Enable or disable deferred drawing. When deferral is disabled,
65     *  pending draw operations are immediately flushed and from then on,
66     *  the SkDeferredCanvas behaves just like a regular SkCanvas.
67     *  This method must not be called while the save/restore stack is in use.
68     *  @param deferred true/false
69     */
70    void setDeferredDrawing(bool deferred);
71
72    /**
73     *  Returns true if deferred drawing is currenlty enabled.
74     */
75    bool isDeferredDrawing() const;
76
77    /**
78     *  Returns true if the canvas contains a fresh frame.  A frame is
79     *  considered fresh when its content do not depend on the contents
80     *  of the previous frame. For example, if a canvas is cleared before
81     *  drawing each frame, the frames will all be considered fresh.
82     *  A frame is defined as the graphics image produced by as a result
83     *  of all the canvas draws operation executed between two successive
84     *  calls to isFreshFrame.  The result of isFreshFrame is computed
85     *  conservatively, so it may report false negatives.
86     */
87    bool isFreshFrame() const;
88
89    /**
90     *  Returns true if the canvas has recorded draw commands that have
91     *  not yet been played back.
92     */
93    bool hasPendingCommands() const;
94
95    /**
96     *  Specify the maximum number of bytes to be allocated for the purpose
97     *  of recording draw commands to this canvas.  The default limit, is
98     *  64MB.
99     *  @param maxStorage The maximum number of bytes to be allocated.
100     */
101    void setMaxRecordingStorage(size_t maxStorage);
102
103    /**
104     *  Returns the number of bytes currently allocated for the purpose of
105     *  recording draw commands.
106     */
107    size_t storageAllocatedForRecording() const;
108
109    /**
110     * Attempt to reduce the storage allocated for recording by evicting
111     * cache resources.
112     * @param bytesToFree minimum number of bytes that should be attempted to
113     *   be freed.
114     * @return number of bytes actually freed.
115     */
116    size_t freeMemoryIfPossible(size_t bytesToFree);
117
118    /**
119     * Specifies the maximum size (in bytes) allowed for a given image to be
120     * rendered using the deferred canvas.
121     */
122    void setBitmapSizeThreshold(size_t sizeThreshold);
123
124    /**
125     * Executes all pending commands without drawing
126     */
127    void silentFlush();
128
129    // Overrides of the SkCanvas interface
130    virtual int save(SaveFlags flags) SK_OVERRIDE;
131    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
132                          SaveFlags flags) SK_OVERRIDE;
133    virtual void restore() SK_OVERRIDE;
134    virtual bool isDrawingToLayer() const SK_OVERRIDE;
135    virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
136    virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
137    virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
138    virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
139    virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
140    virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
141    virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
142                          bool doAntiAlias) SK_OVERRIDE;
143    virtual bool clipPath(const SkPath& path, SkRegion::Op op,
144                          bool doAntiAlias) SK_OVERRIDE;
145    virtual bool clipRegion(const SkRegion& deviceRgn,
146                            SkRegion::Op op) SK_OVERRIDE;
147    virtual void clear(SkColor) SK_OVERRIDE;
148    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
149    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
150                            const SkPaint& paint) SK_OVERRIDE;
151    virtual void drawRect(const SkRect& rect, const SkPaint& paint)
152                          SK_OVERRIDE;
153    virtual void drawPath(const SkPath& path, const SkPaint& paint)
154                          SK_OVERRIDE;
155    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
156                            SkScalar top, const SkPaint* paint)
157                            SK_OVERRIDE;
158    virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
159                                const SkRect& dst, const SkPaint* paint)
160                                SK_OVERRIDE;
161
162    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
163                                  const SkPaint* paint) SK_OVERRIDE;
164    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
165                                const SkRect& dst, const SkPaint* paint)
166                                SK_OVERRIDE;
167    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
168                            const SkPaint* paint) SK_OVERRIDE;
169    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
170                          SkScalar y, const SkPaint& paint) SK_OVERRIDE;
171    virtual void drawPosText(const void* text, size_t byteLength,
172                             const SkPoint pos[], const SkPaint& paint)
173                             SK_OVERRIDE;
174    virtual void drawPosTextH(const void* text, size_t byteLength,
175                              const SkScalar xpos[], SkScalar constY,
176                              const SkPaint& paint) SK_OVERRIDE;
177    virtual void drawTextOnPath(const void* text, size_t byteLength,
178                                const SkPath& path, const SkMatrix* matrix,
179                                const SkPaint& paint) SK_OVERRIDE;
180    virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
181    virtual void drawVertices(VertexMode vmode, int vertexCount,
182                              const SkPoint vertices[], const SkPoint texs[],
183                              const SkColor colors[], SkXfermode* xmode,
184                              const uint16_t indices[], int indexCount,
185                              const SkPaint& paint) SK_OVERRIDE;
186    virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
187    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
188
189public:
190    class NotificationClient {
191    public:
192        /**
193         *  Called before executing one or several draw commands, which means
194         *  once per flush when deferred rendering is enabled.
195         */
196        virtual void prepareForDraw() {}
197
198        /**
199         *  Called after a recording a draw command if additional memory
200         *  had to be allocated for recording.
201         *  @param newAllocatedStorage same value as would be returned by
202         *      storageAllocatedForRecording(), for convenience.
203         */
204        virtual void storageAllocatedForRecordingChanged(
205            size_t newAllocatedStorage) {}
206
207        /**
208         *  Called after pending draw commands have been flushed
209         */
210        virtual void flushedDrawCommands() {}
211
212        /**
213         *  Called after pending draw commands have been skipped, meaning
214         *  that they were optimized-out because the canvas is cleared
215         *  or completely overwritten by the command currently being recorded.
216         */
217        virtual void skippedPendingDrawCommands() {}
218
219    private:
220        typedef SkRefCnt INHERITED;
221    };
222
223protected:
224    virtual SkCanvas* canvasForDrawIter();
225    DeferredDevice* getDeferredDevice() const;
226
227private:
228    void recordedDrawCommand();
229    SkCanvas* drawingCanvas() const;
230    SkCanvas* immediateCanvas() const;
231    bool isFullFrame(const SkRect*, const SkPaint*) const;
232    void validate() const;
233    void init();
234    bool            fDeferredDrawing;
235
236    friend class SkDeferredCanvasTester; // for unit testing
237    typedef SkCanvas INHERITED;
238};
239
240
241#endif
242