Home | History | Annotate | Download | only in utils
      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);
    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 
    178 protected:
    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 
    208 public:
    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 
    241 protected:
    242     virtual SkCanvas* canvasForDrawIter();
    243     SkDeferredDevice* getDeferredDevice() const;
    244 
    245 private:
    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