Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2017 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 SkDeferredDisplayListRecorder_DEFINED
      9 #define SkDeferredDisplayListRecorder_DEFINED
     10 
     11 #include "../private/SkDeferredDisplayList.h"
     12 #include "SkImageInfo.h"
     13 #include "SkRefCnt.h"
     14 #include "SkSurfaceCharacterization.h"
     15 #include "SkTypes.h"
     16 
     17 class GrBackendFormat;
     18 class GrBackendTexture;
     19 class GrContext;
     20 class SkCanvas;
     21 class SkImage;
     22 class SkPromiseImageTexture;
     23 class SkSurface;
     24 struct SkYUVAIndex;
     25 struct SkYUVASizeInfo;
     26 
     27 /*
     28  * This class is intended to be used as:
     29  *   Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
     30  *   Create one of these (an SkDDLMaker) on the stack
     31  *   Get the canvas and render into it
     32  *   Snap off and hold on to an SkDeferredDisplayList
     33  *   Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
     34  *
     35  * This class never accesses the GPU but performs all the cpu work it can. It
     36  * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side
     37  * work in parallel ahead of time).
     38  */
     39 class SK_API SkDeferredDisplayListRecorder {
     40 public:
     41     SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
     42     ~SkDeferredDisplayListRecorder();
     43 
     44     const SkSurfaceCharacterization& characterization() const {
     45         return fCharacterization;
     46     }
     47 
     48     // The backing canvas will become invalid (and this entry point will return
     49     // null) once 'detach' is called.
     50     // Note: ownership of the SkCanvas is not transferred via this call.
     51     SkCanvas* getCanvas();
     52 
     53     std::unique_ptr<SkDeferredDisplayList> detach();
     54 
     55     using PromiseImageTextureContext = void*;
     56     using PromiseImageTextureFulfillProc =
     57             sk_sp<SkPromiseImageTexture> (*)(PromiseImageTextureContext);
     58     using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext);
     59     using PromiseImageTextureDoneProc = void (*)(PromiseImageTextureContext);
     60 
     61     // Deprecated types. To be removed.
     62     using LegacyPromiseImageTextureFulfillProc = void (*)(PromiseImageTextureContext,
     63                                                           GrBackendTexture*);
     64     using TextureContext = PromiseImageTextureContext;
     65 
     66     enum class DelayReleaseCallback : bool { kNo = false, kYes = true };
     67 
     68     /**
     69         Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main
     70         difference is that the client doesn't have the backend texture on the gpu yet but they know
     71         all the properties of the texture. So instead of passing in a GrBackendTexture the client
     72         supplies a GrBackendFormat, width, height, and GrMipMapped state.
     73 
     74         When we actually send the draw calls to the GPU, we will call the textureFulfillProc and
     75         the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must
     76         match those set during the SkImage creation, and it must have a valid backend gpu texture.
     77         The gpu texture supplied by the client must stay valid until we call the textureReleaseProc.
     78 
     79         The following applies when DelayReleaseCallback is kNo:
     80             When we are done with the texture returned by the textureFulfillProc we will call the
     81             textureReleaseProc passing in the textureContext. This is a signal to the client that
     82             they are free to delete the underlying gpu texture. If future draws also use the same
     83             promise image we will call the textureFulfillProc again if we've already called the
     84             textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in
     85             pairs. In other words we will never call textureFulfillProc or textureReleaseProc
     86             multiple times for the same textureContext before calling the other.
     87 
     88             We call the textureDoneProc when we will no longer call the textureFulfillProc again. We
     89             pass in the textureContext as a parameter to the textureDoneProc. We also guarantee that
     90             there will be no outstanding textureReleaseProcs that still need to be called when we
     91             call the textureDoneProc. Thus when the textureDoneProc gets called the client is able
     92             to cleanup all GPU objects and meta data needed for the textureFulfill call.
     93 
     94         When delayReleaseCallback is kYes:
     95             When all the following are true:
     96                 * the promise image is deleted,
     97                 * any SkDeferredDisplayLists that recorded draws referencing the image are deleted,
     98                 * and the texture is safe to delete in the underlying API with respect to drawn
     99                   SkDeferredDisplayLists that reference the image
    100             the textureReleaseProc and then textureDoneProc are called. The texture can be deleted
    101             by the client as soon as textureReleaseProc is called. In this mode there is only one
    102             call to each of textureFulfillProc, textureReleaseProc, and textureDoneProc.
    103 
    104 
    105         This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context.
    106 
    107         @param backendFormat       format of promised gpu texture
    108         @param width               width of promised gpu texture
    109         @param height              height of promised gpu texture
    110         @param mipMapped           mip mapped state of promised gpu texture
    111         @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
    112         @param colorType           one of: kUnknown_SkColorType, kAlpha_8_SkColorType,
    113                                    kRGB_565_SkColorType, kARGB_4444_SkColorType,
    114                                    kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,
    115                                    kGray_8_SkColorType, kRGBA_F16_SkColorType
    116         @param alphaType           one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,
    117                                    kPremul_SkAlphaType, kUnpremul_SkAlphaType
    118         @param colorSpace          range of colors; may be nullptr
    119         @param textureFulfillProc  function called to get actual gpu texture
    120         @param textureReleaseProc  function called when texture can be released
    121         @param promiseDoneProc     function called when we will no longer call textureFulfillProc
    122         @param textureContext      state passed to textureFulfillProc and textureReleaseProc
    123         @return                    created SkImage, or nullptr
    124      */
    125     sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
    126                                       int width,
    127                                       int height,
    128                                       GrMipMapped mipMapped,
    129                                       GrSurfaceOrigin origin,
    130                                       SkColorType colorType,
    131                                       SkAlphaType alphaType,
    132                                       sk_sp<SkColorSpace> colorSpace,
    133                                       PromiseImageTextureFulfillProc textureFulfillProc,
    134                                       PromiseImageTextureReleaseProc textureReleaseProc,
    135                                       PromiseImageTextureDoneProc textureDoneProc,
    136                                       PromiseImageTextureContext textureContext,
    137                                       DelayReleaseCallback delayReleaseCallback);
    138 
    139     /** Deprecated version that assumes DelayReleaseCallback::kNo. */
    140     sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
    141                                       int width,
    142                                       int height,
    143                                       GrMipMapped mipMapped,
    144                                       GrSurfaceOrigin origin,
    145                                       SkColorType colorType,
    146                                       SkAlphaType alphaType,
    147                                       sk_sp<SkColorSpace> colorSpace,
    148                                       PromiseImageTextureFulfillProc textureFulfillProc,
    149                                       PromiseImageTextureReleaseProc textureReleaseProc,
    150                                       PromiseImageTextureDoneProc textureDoneProc,
    151                                       PromiseImageTextureContext textureContext) {
    152         return this->makePromiseTexture(backendFormat, width, height, mipMapped, origin, colorType,
    153                                         alphaType, colorSpace, textureFulfillProc,
    154                                         textureReleaseProc, textureDoneProc, textureContext,
    155                                         DelayReleaseCallback::kNo);
    156     }
    157 
    158     /**
    159         This entry point operates the same as 'makePromiseTexture' except that its
    160         textureFulfillProc can be called up to four times to fetch the required YUVA
    161         planes (passing a different textureContext to each call). So, if the 'yuvaIndices'
    162         indicate that only the first two backend textures are used, 'textureFulfillProc' will
    163         be called with the first two 'textureContexts'.
    164      */
    165     sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
    166                                           const GrBackendFormat yuvaFormats[],
    167                                           const SkISize yuvaSizes[],
    168                                           const SkYUVAIndex yuvaIndices[4],
    169                                           int imageWidth,
    170                                           int imageHeight,
    171                                           GrSurfaceOrigin imageOrigin,
    172                                           sk_sp<SkColorSpace> imageColorSpace,
    173                                           PromiseImageTextureFulfillProc textureFulfillProc,
    174                                           PromiseImageTextureReleaseProc textureReleaseProc,
    175                                           PromiseImageTextureDoneProc textureDoneProc,
    176                                           PromiseImageTextureContext textureContexts[],
    177                                           DelayReleaseCallback delayReleaseCallback);
    178 
    179     /** Deprecated version that assumes DelayReleaseCallback::kNo. */
    180     sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
    181                                           const GrBackendFormat yuvaFormats[],
    182                                           const SkISize yuvaSizes[],
    183                                           const SkYUVAIndex yuvaIndices[4],
    184                                           int imageWidth,
    185                                           int imageHeight,
    186                                           GrSurfaceOrigin imageOrigin,
    187                                           sk_sp<SkColorSpace> imageColorSpace,
    188                                           PromiseImageTextureFulfillProc textureFulfillProc,
    189                                           PromiseImageTextureReleaseProc textureReleaseProc,
    190                                           PromiseImageTextureDoneProc textureDoneProc,
    191                                           PromiseImageTextureContext textureContexts[]) {
    192         return this->makeYUVAPromiseTexture(
    193                 yuvColorSpace, yuvaFormats, yuvaSizes, yuvaIndices, imageWidth, imageHeight,
    194                 imageOrigin, std::move(imageColorSpace), textureFulfillProc, textureReleaseProc,
    195                 textureDoneProc, textureContexts, DelayReleaseCallback::kNo);
    196     }
    197 
    198 private:
    199     bool init();
    200 
    201     const SkSurfaceCharacterization             fCharacterization;
    202 
    203 #if SK_SUPPORT_GPU
    204     sk_sp<GrContext>                            fContext;
    205     sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
    206     sk_sp<SkSurface>                            fSurface;
    207 #endif
    208 };
    209 
    210 #endif
    211