Home | History | Annotate | Download | only in core
      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 SkSurface_DEFINED
      9 #define SkSurface_DEFINED
     10 
     11 #include "SkRefCnt.h"
     12 #include "SkImage.h"
     13 #include "SkSurfaceProps.h"
     14 
     15 class SkCanvas;
     16 class SkPaint;
     17 class GrContext;
     18 class GrRenderTarget;
     19 
     20 /**
     21  *  SkSurface represents the backend/results of drawing to a canvas. For raster
     22  *  drawing, the surface will be pixels, but (for example) when drawing into
     23  *  a PDF or Picture canvas, the surface stores the recorded commands.
     24  *
     25  *  To draw into a canvas, first create the appropriate type of Surface, and
     26  *  then request the canvas from the surface.
     27  *
     28  *  SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
     29  *  of the requested dimensions are zero, then NULL will be returned.
     30  */
     31 class SK_API SkSurface : public SkRefCnt {
     32 public:
     33     static const SkBudgeted kYes_Budgeted = SkBudgeted::kYes;
     34     static const SkBudgeted kNo_Budgeted = SkBudgeted::kNo;
     35     using Budgeted = SkBudgeted;
     36 
     37     /**
     38      *  Create a new surface, using the specified pixels/rowbytes as its
     39      *  backend.
     40      *
     41      *  If the requested surface cannot be created, or the request is not a
     42      *  supported configuration, NULL will be returned.
     43      */
     44     static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
     45                                       const SkSurfaceProps* = NULL);
     46 
     47     /**
     48      *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
     49      *  when the surface is deleted, and is passed the pixel memory and the specified context.
     50      */
     51     static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
     52                                                  void (*releaseProc)(void* pixels, void* context),
     53                                                  void* context, const SkSurfaceProps* = NULL);
     54 
     55     /**
     56      *  Return a new surface, with the memory for the pixels automatically allocated, but respecting
     57      *  the specified rowBytes. If rowBytes==0, then a default value will be chosen. If a non-zero
     58      *  rowBytes is specified, then any images snapped off of this surface (via newImageSnapshot())
     59      *  are guaranteed to have the same rowBytes.
     60      *
     61      *  If the requested surface cannot be created, or the request is not a
     62      *  supported configuration, NULL will be returned.
     63      */
     64     static SkSurface* NewRaster(const SkImageInfo&, size_t rowBytes, const SkSurfaceProps*);
     65 
     66     /**
     67      *  Allocate a new surface, automatically computing the rowBytes.
     68      */
     69     static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
     70 
     71     /**
     72      *  Helper version of NewRaster. It creates a SkImageInfo with the
     73      *  specified width and height, and populates the rest of info to match
     74      *  pixels in SkPMColor format.
     75      */
     76     static SkSurface* NewRasterN32Premul(int width, int height, const SkSurfaceProps* props = NULL) {
     77         return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
     78     }
     79 
     80     /**
     81      *  Return a new surface using the specified render target.
     82      */
     83     static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
     84 
     85     static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
     86         return NewRenderTargetDirect(target, NULL);
     87     }
     88 
     89     /**
     90      *  Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag
     91      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
     92      *  of the texture and the client must ensure the texture is valid for the lifetime of the
     93      *  SkSurface.
     94      */
     95     static SkSurface* NewFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
     96                                             const SkSurfaceProps*);
     97     // Legacy alias
     98     static SkSurface* NewWrappedRenderTarget(GrContext* ctx, const GrBackendTextureDesc& desc,
     99                                              const SkSurfaceProps* props) {
    100         return NewFromBackendTexture(ctx, desc, props);
    101     }
    102 
    103     /**
    104      *  Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume
    105      *  ownership of the render target and the client must ensure the render target is valid for the
    106      *  lifetime of the SkSurface.
    107      */
    108     static SkSurface* NewFromBackendRenderTarget(GrContext*, const GrBackendRenderTargetDesc&,
    109                                                  const SkSurfaceProps*);
    110 
    111     /**
    112      *  Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as
    113      *  a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own
    114      *  the associated render target objects (but not the provided texture). The kRenderTarget flag
    115      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
    116      *  of the texture and the client must ensure the texture is valid for the lifetime of the
    117      *  SkSurface.
    118      */
    119     static SkSurface* NewFromBackendTextureAsRenderTarget(
    120             GrContext*, const GrBackendTextureDesc&, const SkSurfaceProps*);
    121 
    122     /**
    123      *  Return a new surface whose contents will be drawn to an offscreen
    124      *  render target, allocated by the surface.
    125      *
    126      *  The GrTextureStorageAllocator will be reused if SkImage snapshots create
    127      *  additional textures.
    128      */
    129     static SkSurface* NewRenderTarget(
    130             GrContext*, SkBudgeted, const SkImageInfo&, int sampleCount,
    131             const SkSurfaceProps* = NULL, GrTextureStorageAllocator = GrTextureStorageAllocator());
    132 
    133     static SkSurface* NewRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
    134         return NewRenderTarget(gr, b, info, 0);
    135     }
    136 
    137     int width() const { return fWidth; }
    138     int height() const { return fHeight; }
    139 
    140     /**
    141      *  Returns a unique non-zero, unique value identifying the content of this
    142      *  surface. Each time the content is changed changed, either by drawing
    143      *  into this surface, or explicitly calling notifyContentChanged()) this
    144      *  method will return a new value.
    145      *
    146      *  If this surface is empty (i.e. has a zero-dimention), this will return
    147      *  0.
    148      */
    149     uint32_t generationID();
    150 
    151     /**
    152      *  Modes that can be passed to notifyContentWillChange
    153      */
    154     enum ContentChangeMode {
    155         /**
    156          *  Use this mode if it is known that the upcoming content changes will
    157          *  clear or overwrite prior contents, thus making them discardable.
    158          */
    159         kDiscard_ContentChangeMode,
    160         /**
    161          *  Use this mode if prior surface contents need to be preserved or
    162          *  if in doubt.
    163          */
    164         kRetain_ContentChangeMode,
    165     };
    166 
    167     /**
    168      *  Call this if the contents are about to change. This will (lazily) force a new
    169      *  value to be returned from generationID() when it is called next.
    170      *
    171      *  CAN WE DEPRECATE THIS?
    172      */
    173     void notifyContentWillChange(ContentChangeMode mode);
    174 
    175     enum BackendHandleAccess {
    176         kFlushRead_BackendHandleAccess,     //!< caller may read from the backend object
    177         kFlushWrite_BackendHandleAccess,    //!< caller may write to the backend object
    178         kDiscardWrite_BackendHandleAccess,  //!< caller must over-write the entire backend object
    179     };
    180 
    181     /*
    182      * These are legacy aliases which will be removed soon
    183      */
    184     static const BackendHandleAccess kFlushRead_TextureHandleAccess =
    185             kFlushRead_BackendHandleAccess;
    186     static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
    187             kFlushWrite_BackendHandleAccess;
    188     static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
    189             kDiscardWrite_BackendHandleAccess;
    190 
    191 
    192     /**
    193      *  Retrieves the backend API handle of the texture used by this surface, or 0 if the surface
    194      *  is not backed by a GPU texture.
    195      *
    196      *  The returned texture-handle is only valid until the next draw-call into the surface,
    197      *  or the surface is deleted.
    198      */
    199     GrBackendObject getTextureHandle(BackendHandleAccess);
    200 
    201     /**
    202      *  Retrieves the backend API handle of the RenderTarget backing this surface.  Callers must
    203      *  ensure this function returns 'true' or else the GrBackendObject will be invalid
    204      *
    205      *  In OpenGL this will return the FramebufferObject ID.
    206      */
    207     bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess);
    208 
    209     /**
    210      *  Return a canvas that will draw into this surface. This will always
    211      *  return the same canvas for a given surface, and is manged/owned by the
    212      *  surface. It should not be used when its parent surface has gone out of
    213      *  scope.
    214      */
    215     SkCanvas* getCanvas();
    216 
    217     /**
    218      *  Return a new surface that is "compatible" with this one, in that it will
    219      *  efficiently be able to be drawn into this surface. Typical calling
    220      *  pattern:
    221      *
    222      *  SkSurface* A = SkSurface::New...();
    223      *  SkCanvas* canvasA = surfaceA->newCanvas();
    224      *  ...
    225      *  SkSurface* surfaceB = surfaceA->newSurface(...);
    226      *  SkCanvas* canvasB = surfaceB->newCanvas();
    227      *  ... // draw using canvasB
    228      *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
    229      */
    230     SkSurface* newSurface(const SkImageInfo&);
    231 
    232     /**
    233      *  Returns an image of the current state of the surface pixels up to this
    234      *  point. Subsequent changes to the surface (by drawing into its canvas)
    235      *  will not be reflected in this image. If a copy must be made the Budgeted
    236      *  parameter controls whether it counts against the resource budget
    237      *  (currently for the gpu backend only).
    238      */
    239     SkImage* newImageSnapshot(SkBudgeted = SkBudgeted::kYes);
    240 
    241     /**
    242      * In rare instances a client may want a unique copy of the SkSurface's contents in an image
    243      * snapshot. This enum can be used to enforce that the image snapshot's backing store is not
    244      * shared with another image snapshot or the surface's backing store. This is generally more
    245      * expensive. This was added for Chromium bug 585250.
    246      */
    247     enum ForceUnique {
    248         kNo_ForceUnique,
    249         kYes_ForceUnique
    250     };
    251     SkImage* newImageSnapshot(SkBudgeted, ForceUnique);
    252 
    253     /**
    254      *  Though the caller could get a snapshot image explicitly, and draw that,
    255      *  it seems that directly drawing a surface into another canvas might be
    256      *  a common pattern, and that we could possibly be more efficient, since
    257      *  we'd know that the "snapshot" need only live until we've handed it off
    258      *  to the canvas.
    259      */
    260     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
    261 
    262     /**
    263      *  If the surface has direct access to its pixels (i.e. they are in local
    264      *  RAM) return the const-address of those pixels, and if not null, return
    265      *  the ImageInfo and rowBytes. The returned address is only valid while
    266      *  the surface object is in scope, and no API call is made on the surface
    267      *  or its canvas.
    268      *
    269      *  On failure, returns NULL and the info and rowBytes parameters are
    270      *  ignored.
    271      */
    272     const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
    273 
    274     /**
    275      *  Copy the pixels from the surface into the specified buffer (pixels + rowBytes),
    276      *  converting them into the requested format (dstInfo). The surface pixels are read
    277      *  starting at the specified (srcX,srcY) location.
    278      *
    279      *  The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
    280      *
    281      *      srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
    282      *
    283      *  srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
    284      *  then we have two sets of pixels (of equal size). Replace the dst pixels with the
    285      *  corresponding src pixels, performing any colortype/alphatype transformations needed
    286      *  (in the case where the src and dst have different colortypes or alphatypes).
    287      *
    288      *  This call can fail, returning false, for several reasons:
    289      *  - If srcR does not intersect the surface bounds.
    290      *  - If the requested colortype/alphatype cannot be converted from the surface's types.
    291      */
    292     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    293                     int srcX, int srcY);
    294 
    295     const SkSurfaceProps& props() const { return fProps; }
    296 
    297     /**
    298      * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA.
    299      */
    300     void prepareForExternalIO();
    301 
    302 protected:
    303     SkSurface(int width, int height, const SkSurfaceProps*);
    304     SkSurface(const SkImageInfo&, const SkSurfaceProps*);
    305 
    306     // called by subclass if their contents have changed
    307     void dirtyGenerationID() {
    308         fGenerationID = 0;
    309     }
    310 
    311 private:
    312     const SkSurfaceProps fProps;
    313     const int            fWidth;
    314     const int            fHeight;
    315     uint32_t             fGenerationID;
    316 
    317     typedef SkRefCnt INHERITED;
    318 };
    319 
    320 #endif
    321