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     SK_DECLARE_INST_COUNT(SkSurface)
     34 
     35     /**
     36      *  Indicates whether a new surface or image should count against a cache budget. Currently this
     37      *  is only used by the GPU backend (sw-raster surfaces and images are never counted against the
     38      *  resource cache budget.)
     39      */
     40     enum Budgeted {
     41         /** The surface or image does not count against the cache budget. */
     42         kNo_Budgeted,
     43         /** The surface or image counts against the cache budget. */
     44         kYes_Budgeted
     45     };
     46 
     47     /**
     48      *  Create a new surface, using the specified pixels/rowbytes as its
     49      *  backend.
     50      *
     51      *  If the requested surface cannot be created, or the request is not a
     52      *  supported configuration, NULL will be returned.
     53      */
     54     static SkSurface* NewRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
     55                                       const SkSurfaceProps* = NULL);
     56 
     57     /**
     58      *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
     59      *  when the surface is deleted, and is passed the pixel memory and the specified context.
     60      */
     61     static SkSurface* NewRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
     62                                                  void (*releaseProc)(void* pixels, void* context),
     63                                                  void* context, const SkSurfaceProps* = NULL);
     64 
     65     /**
     66      *  Return a new surface, with the memory for the pixels automatically
     67      *  allocated.
     68      *
     69      *  If the requested surface cannot be created, or the request is not a
     70      *  supported configuration, NULL will be returned.
     71      */
     72     static SkSurface* NewRaster(const SkImageInfo&, const SkSurfaceProps* = NULL);
     73 
     74     /**
     75      *  Helper version of NewRaster. It creates a SkImageInfo with the
     76      *  specified width and height, and populates the rest of info to match
     77      *  pixels in SkPMColor format.
     78      */
     79 #ifdef SK_SUPPORT_LEGACY_NewRasterPMColor
     80     static SkSurface* NewRasterPMColor(int width, int height, const SkSurfaceProps* props = NULL) {
     81         return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
     82     }
     83 #endif
     84     static SkSurface* NewRasterN32Premul(int width, int height, const SkSurfaceProps* props = NULL) {
     85         return NewRaster(SkImageInfo::MakeN32Premul(width, height), props);
     86     }
     87 
     88     /**
     89      *  Return a new surface using the specified render target.
     90      */
     91     static SkSurface* NewRenderTargetDirect(GrRenderTarget*, const SkSurfaceProps*);
     92 
     93     static SkSurface* NewRenderTargetDirect(GrRenderTarget* target) {
     94         return NewRenderTargetDirect(target, NULL);
     95     }
     96 
     97     /**
     98      *  Used to wrap a pre-existing backend 3D API texture in a SkSurface. The kRenderTarget flag
     99      *  must be set on GrBackendTextureDesc for this to succeed.
    100      */
    101     static SkSurface* NewWrappedRenderTarget(GrContext*, GrBackendTextureDesc,
    102                                              const SkSurfaceProps*);
    103 
    104     /**
    105      *  Return a new surface whose contents will be drawn to an offscreen
    106      *  render target, allocated by the surface.
    107      */
    108     static SkSurface* NewRenderTarget(GrContext*, Budgeted, const SkImageInfo&, int sampleCount,
    109                                       const SkSurfaceProps* = NULL);
    110 
    111     static SkSurface* NewRenderTarget(GrContext* gr, Budgeted b, const SkImageInfo& info) {
    112         return NewRenderTarget(gr, b, info, 0, NULL);
    113     }
    114 
    115     int width() const { return fWidth; }
    116     int height() const { return fHeight; }
    117 
    118     /**
    119      *  Returns a unique non-zero, unique value identifying the content of this
    120      *  surface. Each time the content is changed changed, either by drawing
    121      *  into this surface, or explicitly calling notifyContentChanged()) this
    122      *  method will return a new value.
    123      *
    124      *  If this surface is empty (i.e. has a zero-dimention), this will return
    125      *  0.
    126      */
    127     uint32_t generationID();
    128 
    129     /**
    130      *  Modes that can be passed to notifyContentWillChange
    131      */
    132     enum ContentChangeMode {
    133         /**
    134          *  Use this mode if it is known that the upcoming content changes will
    135          *  clear or overwrite prior contents, thus making them discardable.
    136          */
    137         kDiscard_ContentChangeMode,
    138         /**
    139          *  Use this mode if prior surface contents need to be preserved or
    140          *  if in doubt.
    141          */
    142         kRetain_ContentChangeMode,
    143     };
    144 
    145     /**
    146      *  Call this if the contents are about to change. This will (lazily) force a new
    147      *  value to be returned from generationID() when it is called next.
    148      */
    149     void notifyContentWillChange(ContentChangeMode mode);
    150 
    151     /**
    152      *  Return a canvas that will draw into this surface. This will always
    153      *  return the same canvas for a given surface, and is manged/owned by the
    154      *  surface. It should not be used when its parent surface has gone out of
    155      *  scope.
    156      */
    157     SkCanvas* getCanvas();
    158 
    159     /**
    160      *  Return a new surface that is "compatible" with this one, in that it will
    161      *  efficiently be able to be drawn into this surface. Typical calling
    162      *  pattern:
    163      *
    164      *  SkSurface* A = SkSurface::New...();
    165      *  SkCanvas* canvasA = surfaceA->newCanvas();
    166      *  ...
    167      *  SkSurface* surfaceB = surfaceA->newSurface(...);
    168      *  SkCanvas* canvasB = surfaceB->newCanvas();
    169      *  ... // draw using canvasB
    170      *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
    171      */
    172     SkSurface* newSurface(const SkImageInfo&);
    173 
    174     /**
    175      *  Returns an image of the current state of the surface pixels up to this
    176      *  point. Subsequent changes to the surface (by drawing into its canvas)
    177      *  will not be reflected in this image. If a copy must be made the Budgeted
    178      *  parameter controls whether it counts against the resource budget
    179      *  (currently for the gpu backend only).
    180      */
    181     SkImage* newImageSnapshot(Budgeted = kYes_Budgeted);
    182 
    183     /**
    184      *  Though the caller could get a snapshot image explicitly, and draw that,
    185      *  it seems that directly drawing a surface into another canvas might be
    186      *  a common pattern, and that we could possibly be more efficient, since
    187      *  we'd know that the "snapshot" need only live until we've handed it off
    188      *  to the canvas.
    189      */
    190     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
    191 
    192     /**
    193      *  If the surface has direct access to its pixels (i.e. they are in local
    194      *  RAM) return the const-address of those pixels, and if not null, return
    195      *  the ImageInfo and rowBytes. The returned address is only valid while
    196      *  the surface object is in scope, and no API call is made on the surface
    197      *  or its canvas.
    198      *
    199      *  On failure, returns NULL and the info and rowBytes parameters are
    200      *  ignored.
    201      */
    202     const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
    203 
    204     /**
    205      *  Copy the pixels from the surface into the specified buffer (pixels + rowBytes),
    206      *  converting them into the requested format (dstInfo). The surface pixels are read
    207      *  starting at the specified (srcX,srcY) location.
    208      *
    209      *  The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
    210      *
    211      *      srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
    212      *
    213      *  srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
    214      *  then we have two sets of pixels (of equal size). Replace the dst pixels with the
    215      *  corresponding src pixels, performing any colortype/alphatype transformations needed
    216      *  (in the case where the src and dst have different colortypes or alphatypes).
    217      *
    218      *  This call can fail, returning false, for several reasons:
    219      *  - If srcR does not intersect the surface bounds.
    220      *  - If the requested colortype/alphatype cannot be converted from the surface's types.
    221      */
    222     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    223                     int srcX, int srcY);
    224 
    225     const SkSurfaceProps& props() const { return fProps; }
    226 
    227 protected:
    228     SkSurface(int width, int height, const SkSurfaceProps*);
    229     SkSurface(const SkImageInfo&, const SkSurfaceProps*);
    230 
    231     // called by subclass if their contents have changed
    232     void dirtyGenerationID() {
    233         fGenerationID = 0;
    234     }
    235 
    236 private:
    237     const SkSurfaceProps fProps;
    238     const int            fWidth;
    239     const int            fHeight;
    240     uint32_t             fGenerationID;
    241 
    242     typedef SkRefCnt INHERITED;
    243 };
    244 
    245 #endif
    246