Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2018 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 GrProxyProvider_DEFINED
      9 #define GrProxyProvider_DEFINED
     10 
     11 #include "GrResourceKey.h"
     12 #include "GrTextureProxy.h"
     13 #include "GrTypes.h"
     14 #include "SkRefCnt.h"
     15 #include "SkTDynamicHash.h"
     16 
     17 class GrCaps;
     18 class GrResourceProvider;
     19 class GrSingleOwner;
     20 class GrBackendRenderTarget;
     21 class SkImage;
     22 
     23 /*
     24  * A factory for creating GrSurfaceProxy-derived objects.
     25  */
     26 class GrProxyProvider {
     27 public:
     28     GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp<const GrCaps>, GrSingleOwner*);
     29 
     30     ~GrProxyProvider();
     31 
     32     /*
     33      * Assigns a unique key to a proxy. The proxy will be findable via this key using
     34      * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
     35      */
     36     bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
     37 
     38     /*
     39      * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
     40      * have a valid unique key.
     41      */
     42     void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);
     43 
     44     /*
     45      * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
     46      * also remove the unique key from the target GrSurface.
     47      */
     48     void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
     49 
     50     /*
     51      * Finds a proxy by unique key.
     52      */
     53     sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
     54 
     55     /*
     56      * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
     57      * key.
     58      */
     59     sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
     60 
     61     /*
     62      * Create a texture proxy that is backed by an instantiated GrSurface. This is almost entirely
     63      * used by Skia's testing code.
     64      * DDL TODO: remove the remaining Skia-internal use of this method and make it truly
     65      * testing-only.
     66      */
     67     sk_sp<GrTextureProxy> createInstantiatedProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
     68                                                   uint32_t flags = 0);
     69 
     70     /*
     71      * Create an un-mipmapped texture proxy with data.
     72      * DDL TODO: need to refine ownership semantics of 'srcData' if we're in completely
     73      * deferred mode
     74      */
     75     sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted,
     76                                              const void* srcData, size_t rowBytes);
     77 
     78     /*
     79      * Create an un-mipmapped texture proxy with data. The SkImage must be a raster backend image.
     80      * Since the SkImage is ref counted, we simply take a ref on it to keep the data alive until we
     81      * actually upload the data to the gpu.
     82      */
     83     sk_sp<GrTextureProxy> createTextureProxy(sk_sp<SkImage> srcImage,
     84                                              GrSurfaceFlags flags,
     85                                              GrSurfaceOrigin origin,
     86                                              int sampleCnt,
     87                                              SkBudgeted budgeted);
     88 
     89     /*
     90      * Create a mipmapped texture proxy with data.
     91      *
     92      * @param desc          Description of the texture properties.
     93      * @param budgeted      Does the texture count against the resource cache budget?
     94      * @param texels        A contiguous array of mipmap levels
     95      * @param mipLevelCount The amount of elements in the texels array
     96      */
     97     sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted,
     98                                             const GrMipLevel texels[], int mipLevelCount,
     99                                             SkDestinationSurfaceColorMode mipColorMode =
    100                                                             SkDestinationSurfaceColorMode::kLegacy);
    101 
    102     /*
    103      * Create a mipmapped texture proxy without any data.
    104      *
    105      * Like the call above but there are no texels to upload. A texture proxy is returned that
    106      * simply has space allocated for the mips. We will allocated the full amount of mip levels
    107      * based on the width and height in the GrSurfaceDesc.
    108      */
    109     sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted);
    110 
    111     /*
    112      * Create a GrSurfaceProxy without any data.
    113      */
    114     sk_sp<GrTextureProxy> createProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
    115                                       uint32_t flags = 0);
    116 
    117     // These match the definitions in SkImage & GrTexture.h, for whence they came
    118     typedef void* ReleaseContext;
    119     typedef void (*ReleaseProc)(ReleaseContext);
    120 
    121     /*
    122      * Create a texture proxy that wraps a (non-renderable) backend texture.
    123      */
    124     sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&, GrSurfaceOrigin,
    125                                                     GrWrapOwnership = kBorrow_GrWrapOwnership,
    126                                                     ReleaseProc = nullptr,
    127                                                     ReleaseContext = nullptr);
    128 
    129     /*
    130      * Create a texture proxy that wraps a backend texture and is both texture-able and renderable
    131      */
    132     sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&,
    133                                                     GrSurfaceOrigin,
    134                                                     int sampleCnt);
    135 
    136     /*
    137      * Create a render target proxy that wraps a backend rendertarget
    138      */
    139     sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendRenderTarget&,
    140                                                          GrSurfaceOrigin);
    141 
    142     /*
    143      * Create a render target proxy that wraps a backend texture?
    144      */
    145     sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendTexture& tex,
    146                                                          GrSurfaceOrigin origin,
    147                                                          int sampleCnt);
    148 
    149     using LazyInstantiateCallback = std::function<sk_sp<GrTexture>(GrResourceProvider*,
    150                                                                    GrSurfaceOrigin* outOrigin)>;
    151 
    152     enum class Renderable : bool {
    153         kNo = false,
    154         kYes = true
    155     };
    156 
    157     /**
    158      * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
    159      * (Stencil is not supported by this method.) The width and height must either both be greater
    160      * than 0 or both less than or equal to zero. A non-positive value is a signal that the width
    161      * and height are currently unknown.
    162      *
    163      * When called, the callback must be able to cleanup any resources that it captured at creation.
    164      * It also must support being passed in a null GrResourceProvider. When this happens, the
    165      * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
    166      */
    167     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
    168                                           GrMipMapped, SkBackingFit, SkBudgeted);
    169 
    170     sk_sp<GrTextureProxy> createFullyLazyProxy(LazyInstantiateCallback&&,
    171                                                Renderable, GrPixelConfig);
    172 
    173     // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
    174     // determine if it is going to need a texture domain or a full clear.
    175     static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
    176 
    177     /**
    178      * Either the proxy attached to the unique key is being deleted (in which case we
    179      * don't want it cluttering up the hash table) or the client has indicated that
    180      * it will never refer to the unique key again. In either case, remove the key
    181      * from the hash table.
    182      * Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
    183      */
    184     void processInvalidProxyUniqueKey(const GrUniqueKey&);
    185 
    186     /**
    187      * Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
    188      * GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
    189      * also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
    190      */
    191     void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);
    192 
    193     const GrCaps* caps() const { return fCaps.get(); }
    194 
    195     void abandon() {
    196         fResourceCache = nullptr;
    197         fResourceProvider = nullptr;
    198         fAbandoned = true;
    199     }
    200 
    201     bool isAbandoned() const {
    202 #ifdef SK_DEBUG
    203         if (fAbandoned) {
    204             SkASSERT(!fResourceCache && !fResourceProvider);
    205         }
    206 #endif
    207         return fAbandoned;
    208     }
    209 
    210     int numUniqueKeyProxies_TestOnly() const;
    211 
    212     void removeAllUniqueKeys();
    213 
    214 private:
    215     friend class GrAHardwareBufferImageGenerator; // for createWrapped
    216 
    217     sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);
    218 
    219     struct UniquelyKeyedProxyHashTraits {
    220         static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
    221 
    222         static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
    223     };
    224     typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
    225 
    226     // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
    227     // on these proxies but they must send a message to the resourceCache when they are deleted.
    228     UniquelyKeyedProxyHash fUniquelyKeyedProxies;
    229 
    230     GrResourceProvider*    fResourceProvider;
    231     GrResourceCache*       fResourceCache;
    232     bool                   fAbandoned;
    233     sk_sp<const GrCaps>    fCaps;
    234 
    235     // In debug builds we guard against improper thread handling
    236     SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
    237 };
    238 
    239 #endif
    240