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 SkDeferredDevice;
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 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);
139    size_t getBitmapSizeThreshold() const { return fBitmapSizeThreshold; }
140
141    /**
142     * Executes all pending commands without drawing
143     */
144    void silentFlush();
145
146    // Overrides of the SkCanvas interface
147    virtual bool isDrawingToLayer() const SK_OVERRIDE;
148    virtual void clear(SkColor) SK_OVERRIDE;
149    virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
150    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
151                            const SkPaint& paint) SK_OVERRIDE;
152    virtual void drawOval(const SkRect&, const SkPaint& paint) SK_OVERRIDE;
153    virtual void drawRect(const SkRect& rect, const SkPaint& paint) SK_OVERRIDE;
154    virtual void drawRRect(const SkRRect&, const SkPaint& paint) SK_OVERRIDE;
155    virtual void drawPath(const SkPath& path, const SkPaint& paint)
156                          SK_OVERRIDE;
157    virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left,
158                            SkScalar top, const SkPaint* paint)
159                            SK_OVERRIDE;
160    virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
161                                      const SkRect& dst, const SkPaint* paint,
162                                      DrawBitmapRectFlags flags) SK_OVERRIDE;
163
164    virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
165                                  const SkPaint* paint) SK_OVERRIDE;
166    virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
167                                const SkRect& dst, const SkPaint* paint)
168                                SK_OVERRIDE;
169    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
170                            const SkPaint* paint) SK_OVERRIDE;
171    virtual void drawVertices(VertexMode vmode, int vertexCount,
172                              const SkPoint vertices[], const SkPoint texs[],
173                              const SkColor colors[], SkXfermode* xmode,
174                              const uint16_t indices[], int indexCount,
175                              const SkPaint& paint) SK_OVERRIDE;
176    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter) SK_OVERRIDE;
177
178protected:
179    virtual void willSave() SK_OVERRIDE;
180    virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) SK_OVERRIDE;
181    virtual void willRestore() SK_OVERRIDE;
182
183    virtual void didConcat(const SkMatrix&) SK_OVERRIDE;
184    virtual void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
185
186    virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
187    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
188                            const SkPaint&) SK_OVERRIDE;
189    virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
190                               const SkPaint&) SK_OVERRIDE;
191    virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
192                                SkScalar constY, const SkPaint&) SK_OVERRIDE;
193    virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
194                                  const SkMatrix* matrix, const SkPaint&) SK_OVERRIDE;
195    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
196                                const SkPaint& paint) SK_OVERRIDE;
197    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
198                             const SkPoint texCoords[4], SkXfermode* xmode,
199                             const SkPaint& paint) SK_OVERRIDE;
200
201    virtual void onClipRect(const SkRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
202    virtual void onClipRRect(const SkRRect&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
203    virtual void onClipPath(const SkPath&, SkRegion::Op, ClipEdgeStyle) SK_OVERRIDE;
204    virtual void onClipRegion(const SkRegion&, SkRegion::Op) SK_OVERRIDE;
205
206    virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) SK_OVERRIDE;
207
208public:
209    class NotificationClient {
210    public:
211        virtual ~NotificationClient() {}
212
213        /**
214         *  Called before executing one or several draw commands, which means
215         *  once per flush when deferred rendering is enabled.
216         */
217        virtual void prepareForDraw() {}
218
219        /**
220         *  Called after a recording a draw command if additional memory
221         *  had to be allocated for recording.
222         *  @param newAllocatedStorage same value as would be returned by
223         *      storageAllocatedForRecording(), for convenience.
224         */
225        virtual void storageAllocatedForRecordingChanged(
226            size_t newAllocatedStorage) {}
227
228        /**
229         *  Called after pending draw commands have been flushed
230         */
231        virtual void flushedDrawCommands() {}
232
233        /**
234         *  Called after pending draw commands have been skipped, meaning
235         *  that they were optimized-out because the canvas is cleared
236         *  or completely overwritten by the command currently being recorded.
237         */
238        virtual void skippedPendingDrawCommands() {}
239    };
240
241protected:
242    virtual SkCanvas* canvasForDrawIter();
243    SkDeferredDevice* getDeferredDevice() const;
244
245private:
246    SkDeferredCanvas(SkDeferredDevice*);
247
248    void recordedDrawCommand();
249    SkCanvas* drawingCanvas() const;
250    SkCanvas* immediateCanvas() const;
251    bool isFullFrame(const SkRect*, const SkPaint*) const;
252    void validate() const;
253    void init();
254
255    size_t fBitmapSizeThreshold;
256    bool   fDeferredDrawing;
257
258    mutable SkISize fCachedCanvasSize;
259    mutable bool    fCachedCanvasSizeDirty;
260
261    friend class SkDeferredCanvasTester; // for unit testing
262    typedef SkCanvas INHERITED;
263};
264
265
266#endif
267