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;
15class SkImage;
16class 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*/
26class SK_API SkDeferredCanvas : public SkCanvas {
27public:
28    class 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(SkDevice* 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 true if the canvas has recorded draw commands that have
93     *  not yet been played back.
94     */
95    bool hasPendingCommands() const;
96
97    /**
98     *  Flushes pending draw commands, if any, and returns an image of the
99     *  current state of the surface pixels up to this point. Subsequent
100     *  changes to the surface (by drawing into its canvas) will not be
101     *  reflected in this image.  Will return NULL if the deferred canvas
102     *  was not constructed from an SkSurface.
103     */
104    SkImage* newImageSnapshot();
105
106    /**
107     *  Specify the maximum number of bytes to be allocated for the purpose
108     *  of recording draw commands to this canvas.  The default limit, is
109     *  64MB.
110     *  @param maxStorage The maximum number of bytes to be allocated.
111     */
112    void setMaxRecordingStorage(size_t maxStorage);
113
114    /**
115     *  Returns the number of bytes currently allocated for the purpose of
116     *  recording draw commands.
117     */
118    size_t storageAllocatedForRecording() const;
119
120    /**
121     * Attempt to reduce the storage allocated for recording by evicting
122     * cache resources.
123     * @param bytesToFree minimum number of bytes that should be attempted to
124     *   be freed.
125     * @return number of bytes actually freed.
126     */
127    size_t freeMemoryIfPossible(size_t bytesToFree);
128
129    /**
130     * Specifies the maximum size (in bytes) allowed for a given image to be
131     * rendered using the deferred canvas.
132     */
133    void setBitmapSizeThreshold(size_t sizeThreshold);
134
135    /**
136     * Executes all pending commands without drawing
137     */
138    void silentFlush();
139
140    // Overrides of the SkCanvas interface
141    virtual int save(SaveFlags flags) SK_OVERRIDE;
142    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
143                          SaveFlags flags) SK_OVERRIDE;
144    virtual void restore() SK_OVERRIDE;
145    virtual bool isDrawingToLayer() const SK_OVERRIDE;
146    virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
147    virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
148    virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
149    virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
150    virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
151    virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
152    virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
153                          bool doAntiAlias) SK_OVERRIDE;
154    virtual bool clipRRect(const SkRRect& rect, SkRegion::Op op,
155                           bool doAntiAlias) SK_OVERRIDE;
156    virtual bool clipPath(const SkPath& path, SkRegion::Op op,
157                          bool doAntiAlias) SK_OVERRIDE;
158    virtual bool clipRegion(const SkRegion& deviceRgn,
159                            SkRegion::Op op) SK_OVERRIDE;
160    virtual void clear(SkColor) SK_OVERRIDE;
161    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
162    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
163                            const SkPaint& paint) SK_OVERRIDE;
164    virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
165    virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
166    virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
167    virtual void drawPath(const SkPath& path, const SkPaint& paint)
168                          SK_OVERRIDE;
169    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
170                            SkScalar top, const SkPaint* paint)
171                            SK_OVERRIDE;
172    virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
173                                const SkRect& dst, const SkPaint* paint)
174                                SK_OVERRIDE;
175
176    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
177                                  const SkPaint* paint) SK_OVERRIDE;
178    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
179                                const SkRect& dst, const SkPaint* paint)
180                                SK_OVERRIDE;
181    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
182                            const SkPaint* paint) SK_OVERRIDE;
183    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
184                          SkScalar y, const SkPaint& paint) SK_OVERRIDE;
185    virtual void drawPosText(const void* text, size_t byteLength,
186                             const SkPoint pos[], const SkPaint& paint)
187                             SK_OVERRIDE;
188    virtual void drawPosTextH(const void* text, size_t byteLength,
189                              const SkScalar xpos[], SkScalar constY,
190                              const SkPaint& paint) SK_OVERRIDE;
191    virtual void drawTextOnPath(const void* text, size_t byteLength,
192                                const SkPath& path, const SkMatrix* matrix,
193                                const SkPaint& paint) SK_OVERRIDE;
194    virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
195    virtual void drawVertices(VertexMode vmode, int vertexCount,
196                              const SkPoint vertices[], const SkPoint texs[],
197                              const SkColor colors[], SkXfermode* xmode,
198                              const uint16_t indices[], int indexCount,
199                              const SkPaint& paint) SK_OVERRIDE;
200    virtual SkBounder* setBounder(SkBounder* bounder) SK_OVERRIDE;
201    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
202
203public:
204    class NotificationClient {
205    public:
206        virtual ~NotificationClient() {}
207
208        /**
209         *  Called before executing one or several draw commands, which means
210         *  once per flush when deferred rendering is enabled.
211         */
212        virtual void prepareForDraw() {}
213
214        /**
215         *  Called after a recording a draw command if additional memory
216         *  had to be allocated for recording.
217         *  @param newAllocatedStorage same value as would be returned by
218         *      storageAllocatedForRecording(), for convenience.
219         */
220        virtual void storageAllocatedForRecordingChanged(
221            size_t newAllocatedStorage) {}
222
223        /**
224         *  Called after pending draw commands have been flushed
225         */
226        virtual void flushedDrawCommands() {}
227
228        /**
229         *  Called after pending draw commands have been skipped, meaning
230         *  that they were optimized-out because the canvas is cleared
231         *  or completely overwritten by the command currently being recorded.
232         */
233        virtual void skippedPendingDrawCommands() {}
234    };
235
236protected:
237    virtual SkCanvas* canvasForDrawIter();
238    DeferredDevice* getDeferredDevice() const;
239
240private:
241    SkDeferredCanvas(DeferredDevice*);
242
243    void recordedDrawCommand();
244    SkCanvas* drawingCanvas() const;
245    SkCanvas* immediateCanvas() const;
246    bool isFullFrame(const SkRect*, const SkPaint*) const;
247    void validate() const;
248    void init();
249    bool            fDeferredDrawing;
250
251    friend class SkDeferredCanvasTester; // for unit testing
252    typedef SkCanvas INHERITED;
253};
254
255
256#endif
257