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 GrBackendRenderTarget;
     18 class GrBackendSemaphore;
     19 class GrContext;
     20 class GrRenderTarget;
     21 
     22 /**
     23  *  SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be
     24  *  allocated either in CPU memory (a Raster surface) or on the GPU (a RenderTarget surface).
     25  *
     26  *  SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call
     27  *  surface->getCanvas() to use that canvas (but don't delete it, it is owned by the surface).
     28  *
     29  *  SkSurface always has non-zero dimensions. If there is a request for a new surface, and either
     30  *  of the requested dimensions are zero, then NULL will be returned.
     31  */
     32 class SK_API SkSurface : public SkRefCnt {
     33 public:
     34     /**
     35      *  Create a new surface, using the specified pixels/rowbytes as its
     36      *  backend.
     37      *
     38      *  If the requested surface cannot be created, or the request is not a
     39      *  supported configuration, NULL will be returned.
     40      *
     41      *  Callers are responsible for initialiazing the surface pixels.
     42      */
     43     static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo&, void* pixels, size_t rowBytes,
     44                                              const SkSurfaceProps* = nullptr);
     45 
     46     /**
     47      *  The same as NewRasterDirect, but also accepts a call-back routine, which is invoked
     48      *  when the surface is deleted, and is passed the pixel memory and the specified context.
     49      */
     50     static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo&, void* pixels, size_t rowBytes,
     51                                                  void (*releaseProc)(void* pixels, void* context),
     52                                                  void* context, const SkSurfaceProps* = nullptr);
     53 
     54     /**
     55      *  Return a new surface, with the memory for the pixels automatically allocated and
     56      *  zero-initialized, but respecting the specified rowBytes. If rowBytes==0, then a default
     57      *  value will be chosen. If a non-zero rowBytes is specified, then any images snapped off of
     58      *  this surface (via makeImageSnapshot()) are guaranteed to have the same rowBytes.
     59      *
     60      *  If the requested surface cannot be created, or the request is not a
     61      *  supported configuration, NULL will be returned.
     62      */
     63     static sk_sp<SkSurface> MakeRaster(const SkImageInfo&, size_t rowBytes, const SkSurfaceProps*);
     64 
     65     /**
     66      *  Allocate a new surface, automatically computing the rowBytes.
     67      */
     68     static sk_sp<SkSurface> MakeRaster(const SkImageInfo& info,
     69                                        const SkSurfaceProps* props = nullptr) {
     70         return MakeRaster(info, 0, props);
     71     }
     72 
     73     /**
     74      *  Helper version of NewRaster. It creates a SkImageInfo with the
     75      *  specified width and height, and populates the rest of info to match
     76      *  pixels in SkPMColor format.
     77      */
     78     static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height,
     79                                                 const SkSurfaceProps* props = nullptr) {
     80         return MakeRaster(SkImageInfo::MakeN32Premul(width, height), props);
     81     }
     82 
     83     /**
     84      *  Used to wrap a pre-existing backend 3D API texture as a SkSurface. The kRenderTarget flag
     85      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
     86      *  of the texture and the client must ensure the texture is valid for the lifetime of the
     87      *  SkSurface.
     88      */
     89     static sk_sp<SkSurface> MakeFromBackendTexture(GrContext*, const GrBackendTextureDesc&,
     90                                                    sk_sp<SkColorSpace>, const SkSurfaceProps*);
     91 
     92     /**
     93      *  Used to wrap a pre-existing backend 3D API texture as a SkSurface. Skia will not assume
     94      *  ownership of the texture and the client must ensure the texture is valid for the lifetime
     95      *  of the SkSurface. If sampleCnt > 0, then we will create an intermediate mssa surface which
     96      *  we will use for rendering. We then resolve into the passed in texture.
     97      */
     98     static sk_sp<SkSurface> MakeFromBackendTexture(GrContext*, const GrBackendTexture&,
     99                                                    GrSurfaceOrigin origin, int sampleCnt,
    100                                                    sk_sp<SkColorSpace>, const SkSurfaceProps*);
    101 
    102     /**
    103      *  Used to wrap a pre-existing 3D API rendering target as a SkSurface. Skia will not assume
    104      *  ownership of the render target and the client must ensure the render target is valid for the
    105      *  lifetime of the SkSurface.
    106      */
    107     static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext*,
    108                                                         const GrBackendRenderTargetDesc&,
    109                                                         sk_sp<SkColorSpace>,
    110                                                         const SkSurfaceProps*);
    111 
    112     static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext*,
    113                                                         const GrBackendRenderTarget&,
    114                                                         GrSurfaceOrigin origin,
    115                                                         sk_sp<SkColorSpace>,
    116                                                         const SkSurfaceProps*);
    117 
    118     /**
    119      *  Used to wrap a pre-existing 3D API texture as a SkSurface. Skia will treat the texture as
    120      *  a rendering target only, but unlike NewFromBackendRenderTarget, Skia will manage and own
    121      *  the associated render target objects (but not the provided texture). The kRenderTarget flag
    122      *  must be set on GrBackendTextureDesc for this to succeed. Skia will not assume ownership
    123      *  of the texture and the client must ensure the texture is valid for the lifetime of the
    124      *  SkSurface.
    125      */
    126     static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(
    127         GrContext*, const GrBackendTextureDesc&, sk_sp<SkColorSpace>, const SkSurfaceProps*);
    128 
    129     static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext*,
    130                                                                  const GrBackendTexture&,
    131                                                                  GrSurfaceOrigin origin,
    132                                                                  int sampleCnt,
    133                                                                  sk_sp<SkColorSpace>,
    134                                                                  const SkSurfaceProps*);
    135 
    136     /**
    137      * Legacy versions of the above factories, without color space support. These create "legacy"
    138      * surfaces that operate without gamma correction or color management.
    139      */
    140     static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* ctx, const GrBackendTextureDesc& desc,
    141                                                    const SkSurfaceProps* props) {
    142         return MakeFromBackendTexture(ctx, desc, nullptr, props);
    143     }
    144 
    145     static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* ctx,
    146                                                         const GrBackendRenderTargetDesc& desc,
    147                                                         const SkSurfaceProps* props) {
    148         return MakeFromBackendRenderTarget(ctx, desc, nullptr, props);
    149     }
    150 
    151     static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(
    152             GrContext* ctx, const GrBackendTextureDesc& desc, const SkSurfaceProps* props) {
    153         return MakeFromBackendTextureAsRenderTarget(ctx, desc, nullptr, props);
    154     }
    155 
    156 
    157     /**
    158      *  Return a new surface whose contents will be drawn to an offscreen
    159      *  render target, allocated by the surface.
    160      */
    161     static sk_sp<SkSurface> MakeRenderTarget(GrContext*, SkBudgeted, const SkImageInfo&,
    162                                              int sampleCount, GrSurfaceOrigin,
    163                                              const SkSurfaceProps*);
    164 
    165     static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,
    166                                              const SkImageInfo& info, int sampleCount,
    167                                              const SkSurfaceProps* props) {
    168         return MakeRenderTarget(context, budgeted, info, sampleCount,
    169                                 kBottomLeft_GrSurfaceOrigin, props);
    170     }
    171 
    172     static sk_sp<SkSurface> MakeRenderTarget(GrContext* gr, SkBudgeted b, const SkImageInfo& info) {
    173         if (!info.width() || !info.height()) {
    174             return nullptr;
    175         }
    176         return MakeRenderTarget(gr, b, info, 0, kBottomLeft_GrSurfaceOrigin, nullptr);
    177     }
    178 
    179     /**
    180      *  Returns a surface that stores no pixels. It can be drawn to via its canvas, but that
    181      *  canvas does not draw anything. Calling makeImageSnapshot() will return nullptr.
    182      */
    183     static sk_sp<SkSurface> MakeNull(int width, int height);
    184 
    185     int width() const { return fWidth; }
    186     int height() const { return fHeight; }
    187 
    188     /**
    189      *  Returns a unique non-zero, unique value identifying the content of this
    190      *  surface. Each time the content is changed changed, either by drawing
    191      *  into this surface, or explicitly calling notifyContentChanged()) this
    192      *  method will return a new value.
    193      *
    194      *  If this surface is empty (i.e. has a zero-dimention), this will return
    195      *  0.
    196      */
    197     uint32_t generationID();
    198 
    199     /**
    200      *  Modes that can be passed to notifyContentWillChange
    201      */
    202     enum ContentChangeMode {
    203         /**
    204          *  Use this mode if it is known that the upcoming content changes will
    205          *  clear or overwrite prior contents, thus making them discardable.
    206          */
    207         kDiscard_ContentChangeMode,
    208         /**
    209          *  Use this mode if prior surface contents need to be preserved or
    210          *  if in doubt.
    211          */
    212         kRetain_ContentChangeMode,
    213     };
    214 
    215     /**
    216      *  Call this if the contents are about to change. This will (lazily) force a new
    217      *  value to be returned from generationID() when it is called next.
    218      *
    219      *  CAN WE DEPRECATE THIS?
    220      */
    221     void notifyContentWillChange(ContentChangeMode mode);
    222 
    223     enum BackendHandleAccess {
    224         kFlushRead_BackendHandleAccess,     //!< caller may read from the backend object
    225         kFlushWrite_BackendHandleAccess,    //!< caller may write to the backend object
    226         kDiscardWrite_BackendHandleAccess,  //!< caller must over-write the entire backend object
    227     };
    228 
    229     /*
    230      * These are legacy aliases which will be removed soon
    231      */
    232     static const BackendHandleAccess kFlushRead_TextureHandleAccess =
    233             kFlushRead_BackendHandleAccess;
    234     static const BackendHandleAccess kFlushWrite_TextureHandleAccess =
    235             kFlushWrite_BackendHandleAccess;
    236     static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =
    237             kDiscardWrite_BackendHandleAccess;
    238 
    239 
    240     /**
    241      *  Retrieves the backend API handle of the texture used by this surface, or 0 if the surface
    242      *  is not backed by a GPU texture.
    243      *
    244      *  The returned texture-handle is only valid until the next draw-call into the surface,
    245      *  or the surface is deleted.
    246      */
    247     GrBackendObject getTextureHandle(BackendHandleAccess);
    248 
    249     /**
    250      *  Retrieves the backend API handle of the RenderTarget backing this surface.  Callers must
    251      *  ensure this function returns 'true' or else the GrBackendObject will be invalid
    252      *
    253      *  In OpenGL this will return the FramebufferObject ID.
    254      */
    255     bool getRenderTargetHandle(GrBackendObject*, BackendHandleAccess);
    256 
    257     /**
    258      *  Return a canvas that will draw into this surface. This will always
    259      *  return the same canvas for a given surface, and is manged/owned by the
    260      *  surface. It should not be used when its parent surface has gone out of
    261      *  scope.
    262      */
    263     SkCanvas* getCanvas();
    264 
    265     /**
    266      *  Return a new surface that is "compatible" with this one, in that it will
    267      *  efficiently be able to be drawn into this surface. Typical calling
    268      *  pattern:
    269      *
    270      *  SkSurface* A = SkSurface::New...();
    271      *  SkCanvas* canvasA = surfaceA->newCanvas();
    272      *  ...
    273      *  SkSurface* surfaceB = surfaceA->newSurface(...);
    274      *  SkCanvas* canvasB = surfaceB->newCanvas();
    275      *  ... // draw using canvasB
    276      *  canvasA->drawSurface(surfaceB); // <--- this will always be optimal!
    277      */
    278     sk_sp<SkSurface> makeSurface(const SkImageInfo&);
    279 
    280     /**
    281      *  Returns an image of the current state of the surface pixels up to this
    282      *  point. Subsequent changes to the surface (by drawing into its canvas)
    283      *  will not be reflected in this image. For the GPU-backend, the budgeting
    284      *  decision for the snapped image will match that of the surface.
    285      */
    286     sk_sp<SkImage> makeImageSnapshot();
    287 
    288     /**
    289      *  Though the caller could get a snapshot image explicitly, and draw that,
    290      *  it seems that directly drawing a surface into another canvas might be
    291      *  a common pattern, and that we could possibly be more efficient, since
    292      *  we'd know that the "snapshot" need only live until we've handed it off
    293      *  to the canvas.
    294      */
    295     void draw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*);
    296 
    297     /**
    298      *  If the surface has direct access to its pixels (i.e. they are in local
    299      *  RAM) return true, and if not null, set the pixmap parameter to point to the information
    300      *  about the surface's pixels. The pixel address in the pixmap is only valid while
    301      *  the surface object is in scope, and no API call is made on the surface
    302      *  or its canvas.
    303      *
    304      *  On failure, returns false and the pixmap parameter is ignored.
    305      */
    306     bool peekPixels(SkPixmap*);
    307 
    308     /**
    309      *  Copy the pixels from the surface into the specified buffer (pixels + rowBytes),
    310      *  converting them into the requested format (dstInfo). The surface pixels are read
    311      *  starting at the specified (srcX,srcY) location.
    312      *
    313      *  The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
    314      *
    315      *      srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
    316      *
    317      *  srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
    318      *  then we have two sets of pixels (of equal size). Replace the dst pixels with the
    319      *  corresponding src pixels, performing any colortype/alphatype transformations needed
    320      *  (in the case where the src and dst have different colortypes or alphatypes).
    321      *
    322      *  This call can fail, returning false, for several reasons:
    323      *  - If srcR does not intersect the surface bounds.
    324      *  - If the requested colortype/alphatype cannot be converted from the surface's types.
    325      */
    326     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    327                     int srcX, int srcY);
    328 
    329     const SkSurfaceProps& props() const { return fProps; }
    330 
    331     /**
    332      * Issue any pending surface IO to the current backend 3D API and resolve any surface MSAA.
    333      *
    334      * The flush calls below are the new preferred way to flush calls to a surface, and this call
    335      * will eventually be removed.
    336      */
    337     void prepareForExternalIO();
    338 
    339     /**
    340      * Issue any pending surface IO to the current backend 3D API
    341      */
    342     void flush();
    343 
    344     /**
    345      * Issue any pending surface IO to the current backend 3D API. After issuing all commands, we
    346      * will issue numSemaphore semaphores for the gpu to signal. We will then fill in the array
    347      * signalSemaphores with the info on the semaphores we submitted. The client is reposonsible for
    348      * allocating enough space in signalSemaphores to handle numSemaphores of GrBackendSemaphores.
    349      * The client will also take ownership of the returned underlying backend semaphores.
    350      *
    351      * If this call returns false, the GPU backend will not have created or added any semaphores to
    352      * signal. Thus the array of semaphores will remain uninitialized. However, we will still flush
    353      * any pending surface IO.
    354      */
    355     bool flushAndSignalSemaphores(int numSemaphores, GrBackendSemaphore* signalSemaphores);
    356 
    357     /**
    358      * Inserts a list of GPU semaphores that the current backend 3D API must wait on before
    359      * executing any more commands on the GPU for this surface. Skia will take ownership of the
    360      * underlying semaphores and delete them once they have been signaled and waited on.
    361      *
    362      * If this call returns false, then the GPU backend will not wait on any passed in semaphores,
    363      * and the client will still own the semaphores.
    364      */
    365     bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);
    366 
    367 protected:
    368     SkSurface(int width, int height, const SkSurfaceProps*);
    369     SkSurface(const SkImageInfo&, const SkSurfaceProps*);
    370 
    371     // called by subclass if their contents have changed
    372     void dirtyGenerationID() {
    373         fGenerationID = 0;
    374     }
    375 
    376 private:
    377     const SkSurfaceProps fProps;
    378     const int            fWidth;
    379     const int            fHeight;
    380     uint32_t             fGenerationID;
    381 
    382     typedef SkRefCnt INHERITED;
    383 };
    384 
    385 #endif
    386