SkPicture.h revision 5199701acbf386cdc315de440eeafcc10fd0cdc3
1
2/*
3 * Copyright 2007 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkPicture_DEFINED
11#define SkPicture_DEFINED
12
13#include "SkBitmap.h"
14#include "SkImageDecoder.h"
15#include "SkRefCnt.h"
16
17#if SK_SUPPORT_GPU
18class GrContext;
19#endif
20
21class SkBBoxHierarchy;
22class SkCanvas;
23class SkDrawPictureCallback;
24class SkData;
25class SkPicturePlayback;
26class SkPictureRecord;
27class SkStream;
28class SkWStream;
29
30struct SkPictInfo;
31
32/** \class SkPicture
33
34    The SkPicture class records the drawing commands made to a canvas, to
35    be played back at a later time.
36*/
37class SK_API SkPicture : public SkRefCnt {
38public:
39    SK_DECLARE_INST_COUNT(SkPicture)
40
41    // AccelData provides a base class for device-specific acceleration
42    // data. It is added to the picture via a call to a device's optimize
43    // method.
44    class AccelData : public SkRefCnt {
45    public:
46        typedef uint8_t Domain;
47        typedef uint32_t Key;
48
49        AccelData(Key key) : fKey(key) { }
50
51        const Key& getKey() const { return fKey; }
52
53        // This entry point allows user's to get a unique domain prefix
54        // for their keys
55        static Domain GenerateDomain();
56    private:
57        Key fKey;
58
59        typedef SkRefCnt INHERITED;
60    };
61
62    SkPicture();
63    /** Make a copy of the contents of src. If src records more drawing after
64        this call, those elements will not appear in this picture.
65    */
66    SkPicture(const SkPicture& src);
67
68    /**  PRIVATE / EXPERIMENTAL -- do not call */
69    void EXPERIMENTAL_addAccelData(const AccelData* data) {
70        SkRefCnt_SafeAssign(fAccelData, data);
71    }
72    /**  PRIVATE / EXPERIMENTAL -- do not call */
73    const AccelData* EXPERIMENTAL_getAccelData(AccelData::Key key) const {
74        if (NULL != fAccelData && fAccelData->getKey() == key) {
75            return fAccelData;
76        }
77        return NULL;
78    }
79
80    /**
81     *  Function signature defining a function that sets up an SkBitmap from encoded data. On
82     *  success, the SkBitmap should have its Config, width, height, rowBytes and pixelref set.
83     *  If the installed pixelref has decoded the data into pixels, then the src buffer need not be
84     *  copied. If the pixelref defers the actual decode until its lockPixels() is called, then it
85     *  must make a copy of the src buffer.
86     *  @param src Encoded data.
87     *  @param length Size of the encoded data, in bytes.
88     *  @param dst SkBitmap to install the pixel ref on.
89     *  @param bool Whether or not a pixel ref was successfully installed.
90     */
91    typedef bool (*InstallPixelRefProc)(const void* src, size_t length, SkBitmap* dst);
92
93    /**
94     *  Recreate a picture that was serialized into a stream.
95     *  @param SkStream Serialized picture data.
96     *  @param proc Function pointer for installing pixelrefs on SkBitmaps representing the
97     *              encoded bitmap data from the stream.
98     *  @return A new SkPicture representing the serialized data, or NULL if the stream is
99     *          invalid.
100     */
101    static SkPicture* CreateFromStream(SkStream*,
102                                       InstallPixelRefProc proc = &SkImageDecoder::DecodeMemory);
103
104    /**
105     *  Recreate a picture that was serialized into a buffer. If the creation requires bitmap
106     *  decoding, the decoder must be set on the SkReadBuffer parameter by calling
107     *  SkReadBuffer::setBitmapDecoder() before calling SkPicture::CreateFromBuffer().
108     *  @param SkReadBuffer Serialized picture data.
109     *  @return A new SkPicture representing the serialized data, or NULL if the buffer is
110     *          invalid.
111     */
112    static SkPicture* CreateFromBuffer(SkReadBuffer&);
113
114    virtual ~SkPicture();
115
116    /**
117     *  Swap the contents of the two pictures. Guaranteed to succeed.
118     */
119    void swap(SkPicture& other);
120
121    /**
122     *  Creates a thread-safe clone of the picture that is ready for playback.
123     */
124    SkPicture* clone() const;
125
126    /**
127     * Creates multiple thread-safe clones of this picture that are ready for
128     * playback. The resulting clones are stored in the provided array of
129     * SkPictures.
130     */
131    void clone(SkPicture* pictures, int count) const;
132
133    enum RecordingFlags {
134        /*  This flag specifies that when clipPath() is called, the path will
135            be faithfully recorded, but the recording canvas' current clip will
136            only see the path's bounds. This speeds up the recording process
137            without compromising the fidelity of the playback. The only side-
138            effect for recording is that calling getTotalClip() or related
139            clip-query calls will reflect the path's bounds, not the actual
140            path.
141         */
142        kUsePathBoundsForClip_RecordingFlag = 0x01,
143        /*  This flag causes the picture to compute bounding boxes and build
144            up a spatial hierarchy (currently an R-Tree), plus a tree of Canvas'
145            usually stack-based clip/etc state. This requires an increase in
146            recording time (often ~2x; likely more for very complex pictures),
147            but allows us to perform much faster culling at playback time, and
148            completely avoid some unnecessary clips and other operations. This
149            is ideal for tiled rendering, or any other situation where you're
150            drawing a fraction of a large scene into a smaller viewport.
151
152            In most cases the record cost is offset by the playback improvement
153            after a frame or two of tiled rendering (and complex pictures that
154            induce the worst record times will generally get the largest
155            speedups at playback time).
156
157            Note: Currently this is not serializable, the bounding data will be
158            discarded if you serialize into a stream and then deserialize.
159        */
160        kOptimizeForClippedPlayback_RecordingFlag = 0x02,
161    };
162
163#ifndef SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD
164private:
165    friend class SkPictureRecorder;
166    friend class SkImage_Picture;
167    friend class SkSurface_Picture;
168#endif
169
170    /** Returns the canvas that records the drawing commands.
171        @param width the base width for the picture, as if the recording
172                     canvas' bitmap had this width.
173        @param height the base width for the picture, as if the recording
174                     canvas' bitmap had this height.
175        @param recordFlags optional flags that control recording.
176        @return the picture canvas.
177    */
178    SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
179
180    /** Returns the recording canvas if one is active, or NULL if recording is
181        not active. This does not alter the refcnt on the canvas (if present).
182    */
183    SkCanvas* getRecordingCanvas() const;
184    /** Signal that the caller is done recording. This invalidates the canvas
185        returned by beginRecording/getRecordingCanvas, and prepares the picture
186        for drawing. Note: this happens implicitly the first time the picture
187        is drawn.
188    */
189    void endRecording();
190
191#ifndef SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD
192public:
193#endif
194
195    /** Replays the drawing commands on the specified canvas. This internally
196        calls endRecording() if that has not already been called.
197        @param canvas the canvas receiving the drawing commands.
198    */
199    void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL);
200
201    /** Return the width of the picture's recording canvas. This
202        value reflects what was passed to setSize(), and does not necessarily
203        reflect the bounds of what has been recorded into the picture.
204        @return the width of the picture's recording canvas
205    */
206    int width() const { return fWidth; }
207
208    /** Return the height of the picture's recording canvas. This
209        value reflects what was passed to setSize(), and does not necessarily
210        reflect the bounds of what has been recorded into the picture.
211        @return the height of the picture's recording canvas
212    */
213    int height() const { return fHeight; }
214
215    /** Return a non-zero, unique value representing the picture. This call is
216        only valid when not recording. Between a beginRecording/endRecording
217        pair it will just return 0 (the invalid ID). Each beginRecording/
218        endRecording pair will cause a different generation ID to be returned.
219    */
220    uint32_t uniqueID() const;
221
222    /**
223     *  Function to encode an SkBitmap to an SkData. A function with this
224     *  signature can be passed to serialize() and SkWriteBuffer.
225     *  Returning NULL will tell the SkWriteBuffer to use
226     *  SkBitmap::flatten() to store the bitmap.
227     *
228     *  @param pixelRefOffset DEPRECATED -- caller assumes it will return 0.
229     *  @return SkData If non-NULL, holds encoded data representing the passed
230     *      in bitmap. The caller is responsible for calling unref().
231     */
232    typedef SkData* (*EncodeBitmap)(size_t* pixelRefOffset, const SkBitmap& bm);
233
234    /**
235     *  Serialize to a stream. If non NULL, encoder will be used to encode
236     *  any bitmaps in the picture.
237     *  encoder will never be called with a NULL pixelRefOffset.
238     */
239    void serialize(SkWStream*, EncodeBitmap encoder = NULL) const;
240
241    /**
242     *  Serialize to a buffer.
243     */
244    void flatten(SkWriteBuffer&) const;
245
246    /**
247     * Returns true if any bitmaps may be produced when this SkPicture
248     * is replayed.
249     * Returns false if called while still recording.
250     */
251    bool willPlayBackBitmaps() const;
252
253#ifdef SK_BUILD_FOR_ANDROID
254    /** Signals that the caller is prematurely done replaying the drawing
255        commands. This can be called from a canvas virtual while the picture
256        is drawing. Has no effect if the picture is not drawing.
257        @deprecated preserving for legacy purposes
258    */
259    void abortPlayback();
260#endif
261
262    /** Return true if the SkStream/Buffer represents a serialized picture, and
263        fills out SkPictInfo. After this function returns, the data source is not
264        rewound so it will have to be manually reset before passing to
265        CreateFromStream or CreateFromBuffer. Note, CreateFromStream and
266        CreateFromBuffer perform this check internally so these entry points are
267        intended for stand alone tools.
268        If false is returned, SkPictInfo is unmodified.
269    */
270    static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*);
271    static bool InternalOnly_BufferIsSKP(SkReadBuffer&, SkPictInfo*);
272
273    /** Enable/disable all the picture recording optimizations (i.e.,
274        those in SkPictureRecord). It is mainly intended for testing the
275        existing optimizations (i.e., to actually have the pattern
276        appear in an .skp we have to disable the optimization). Call right
277        after 'beginRecording'.
278    */
279    void internalOnly_EnableOpts(bool enableOpts);
280
281    /** Return true if the picture is suitable for rendering on the GPU.
282     */
283
284#if SK_SUPPORT_GPU
285    bool suitableForGpuRasterization(GrContext*) const;
286#endif
287
288protected:
289    // V2 : adds SkPixelRef's generation ID.
290    // V3 : PictInfo tag at beginning, and EOF tag at the end
291    // V4 : move SkPictInfo to be the header
292    // V5 : don't read/write FunctionPtr on cross-process (we can detect that)
293    // V6 : added serialization of SkPath's bounds (and packed its flags tighter)
294    // V7 : changed drawBitmapRect(IRect) to drawBitmapRectToRect(Rect)
295    // V8 : Add an option for encoding bitmaps
296    // V9 : Allow the reader and writer of an SKP disagree on whether to support
297    //      SK_SUPPORT_HINTING_SCALE_FACTOR
298    // V10: add drawRRect, drawOval, clipRRect
299    // V11: modify how readBitmap and writeBitmap store their info.
300    // V12: add conics to SkPath, use new SkPathRef flattening
301    // V13: add flag to drawBitmapRectToRect
302    //      parameterize blurs by sigma rather than radius
303    // V14: Add flags word to PathRef serialization
304    // V15: Remove A1 bitmap config (and renumber remaining configs)
305    // V16: Move SkPath's isOval flag to SkPathRef
306    // V17: SkPixelRef now writes SkImageInfo
307    // V18: SkBitmap now records x,y for its pixelref origin, instead of offset.
308    // V19: encode matrices and regions into the ops stream
309    // V20: added bool to SkPictureImageFilter's serialization (to allow SkPicture serialization)
310    // V21: add pushCull, popCull
311    // V22: SK_PICT_FACTORY_TAG's size is now the chunk size in bytes
312
313    // Note: If the picture version needs to be increased then please follow the
314    // steps to generate new SKPs in (only accessible to Googlers): http://goo.gl/qATVcw
315
316    // Only SKPs within the min/current picture version range (inclusive) can be read.
317    static const uint32_t MIN_PICTURE_VERSION = 19;
318    static const uint32_t CURRENT_PICTURE_VERSION = 22;
319
320    mutable uint32_t      fUniqueID;
321
322    // fPlayback, fRecord, fWidth & fHeight are protected to allow derived classes to
323    // install their own SkPicturePlayback-derived players,SkPictureRecord-derived
324    // recorders and set the picture size
325    SkPicturePlayback*    fPlayback;
326    SkPictureRecord*      fRecord;
327    int                   fWidth, fHeight;
328    const AccelData*      fAccelData;
329
330    void needsNewGenID() { fUniqueID = SK_InvalidGenID; }
331
332    // Create a new SkPicture from an existing SkPicturePlayback. Ref count of
333    // playback is unchanged.
334    SkPicture(SkPicturePlayback*, int width, int height);
335
336    // For testing. Derived classes may instantiate an alternate
337    // SkBBoxHierarchy implementation
338    virtual SkBBoxHierarchy* createBBoxHierarchy() const;
339private:
340    // An OperationList encapsulates a set of operation offsets into the picture byte
341    // stream along with the CTMs needed for those operation.
342    class OperationList : ::SkNoncopyable {
343    public:
344        virtual ~OperationList() {}
345
346        // If valid returns false then there is no optimization data
347        // present. All the draw operations need to be issued.
348        virtual bool valid() const { return false; }
349
350        // The following three entry points should only be accessed if
351        // 'valid' returns true.
352        virtual int numOps() const { SkASSERT(false); return 0; };
353        // The offset in the picture of the operation to execute.
354        virtual uint32_t offset(int index) const { SkASSERT(false); return 0; };
355        // The CTM that must be installed for the operation to behave correctly
356        virtual const SkMatrix& matrix(int index) const { SkASSERT(false); return SkMatrix::I(); }
357
358        static const OperationList& InvalidList();
359    };
360
361    /** PRIVATE / EXPERIMENTAL -- do not call
362        Return the operations required to render the content inside 'queryRect'.
363    */
364    const OperationList& EXPERIMENTAL_getActiveOps(const SkIRect& queryRect);
365
366    /** PRIVATE / EXPERIMENTAL -- do not call
367        Return the ID of the operation currently being executed when playing
368        back. 0 indicates no call is active.
369    */
370    size_t EXPERIMENTAL_curOpID() const;
371
372    void createHeader(SkPictInfo* info) const;
373    static bool IsValidPictInfo(const SkPictInfo& info);
374
375    friend class SkFlatPicture;
376    friend class SkPicturePlayback;
377    friend class SkGpuDevice;
378    friend class GrGatherDevice;
379    friend class SkDebugCanvas;
380
381    typedef SkRefCnt INHERITED;
382};
383
384/**
385 *  Subclasses of this can be passed to canvas.drawPicture. During the drawing
386 *  of the picture, this callback will periodically be invoked. If its
387 *  abortDrawing() returns true, then picture playback will be interrupted.
388 *
389 *  The resulting drawing is undefined, as there is no guarantee how often the
390 *  callback will be invoked. If the abort happens inside some level of nested
391 *  calls to save(), restore will automatically be called to return the state
392 *  to the same level it was before the drawPicture call was made.
393 */
394class SK_API SkDrawPictureCallback {
395public:
396    SkDrawPictureCallback() {}
397    virtual ~SkDrawPictureCallback() {}
398
399    virtual bool abortDrawing() = 0;
400};
401
402class SkPictureFactory : public SkRefCnt {
403public:
404    /**
405     *  Allocate a new SkPicture. Return NULL on failure.
406     */
407    virtual SkPicture* create(int width, int height) = 0;
408};
409
410class SK_API SkPictureRecorder : SkNoncopyable {
411public:
412    SkPictureRecorder(SkPictureFactory* factory = NULL) {
413        fFactory.reset(factory);
414        if (NULL != fFactory.get()) {
415            fFactory.get()->ref();
416        }
417    }
418
419    /** Returns the canvas that records the drawing commands.
420        @param width the base width for the picture, as if the recording
421                     canvas' bitmap had this width.
422        @param height the base width for the picture, as if the recording
423                     canvas' bitmap had this height.
424        @param recordFlags optional flags that control recording.
425        @return the canvas.
426    */
427    SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0) {
428        if (NULL != fFactory) {
429            fPicture.reset(fFactory->create(width, height));
430        } else {
431            fPicture.reset(SkNEW(SkPicture));
432        }
433
434        return fPicture->beginRecording(width, height, recordFlags);
435    }
436
437    /** Returns the recording canvas if one is active, or NULL if recording is
438        not active. This does not alter the refcnt on the canvas (if present).
439    */
440    SkCanvas* getRecordingCanvas() {
441        if (NULL != fPicture.get()) {
442            return fPicture->getRecordingCanvas();
443        }
444        return NULL;
445    }
446
447    /** Signal that the caller is done recording. This invalidates the canvas
448        returned by beginRecording/getRecordingCanvas, and returns the
449        created SkPicture. Note that the returned picture has its creation
450        ref which the caller must take ownership of.
451    */
452    SkPicture* endRecording() {
453        if (NULL != fPicture.get()) {
454            fPicture->endRecording();
455            return fPicture.detach();
456        }
457        return NULL;
458    }
459
460    /** Enable/disable all the picture recording optimizations (i.e.,
461        those in SkPictureRecord). It is mainly intended for testing the
462        existing optimizations (i.e., to actually have the pattern
463        appear in an .skp we have to disable the optimization). Call right
464        after 'beginRecording'.
465    */
466    void internalOnly_EnableOpts(bool enableOpts) {
467        if (NULL != fPicture.get()) {
468            fPicture->internalOnly_EnableOpts(enableOpts);
469        }
470    }
471
472private:
473    SkAutoTUnref<SkPictureFactory> fFactory;
474    SkAutoTUnref<SkPicture>        fPicture;
475
476    typedef SkNoncopyable INHERITED;
477};
478
479#endif
480