Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 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 GrResourceProvider_DEFINED
      9 #define GrResourceProvider_DEFINED
     10 
     11 #include "GrBuffer.h"
     12 #include "GrPathRange.h"
     13 #include "SkImageInfo.h"
     14 #include "SkScalerContext.h"
     15 
     16 class GrBackendRenderTarget;
     17 class GrBackendSemaphore;
     18 class GrBackendTexture;
     19 class GrGpu;
     20 class GrPath;
     21 class GrRenderTarget;
     22 class GrSemaphore;
     23 class GrSingleOwner;
     24 class GrStencilAttachment;
     25 class GrSurfaceProxy;
     26 class GrTexture;
     27 class GrTextureProxy;
     28 
     29 class GrStyle;
     30 class SkDescriptor;
     31 class SkPath;
     32 class SkTypeface;
     33 
     34 /**
     35  * A factory for arbitrary resource types. This class is intended for use within the Gr code base.
     36  *
     37  * Some members force callers to make a flags (pendingIO) decision. This can be relaxed once
     38  * https://bug.skia.org/4156 is fixed.
     39  */
     40 class GrResourceProvider {
     41 public:
     42     GrResourceProvider(GrGpu* gpu, GrResourceCache* cache, GrSingleOwner* owner);
     43 
     44     template <typename T> T* findAndRefTByUniqueKey(const GrUniqueKey& key) {
     45         return static_cast<T*>(this->findAndRefResourceByUniqueKey(key));
     46     }
     47 
     48     ///////////////////////////////////////////////////////////////////////////
     49     // Textures
     50 
     51     /** Assigns a unique key to the texture. The texture will be findable via this key using
     52     findTextureByUniqueKey(). If an existing texture has this key, it's key will be removed. */
     53     void assignUniqueKeyToProxy(const GrUniqueKey& key, GrTextureProxy*);
     54 
     55     /** Finds a texture by unique key. If the texture is found it is ref'ed and returned. */
     56     sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey& key);
     57 
     58     /**
     59      * Finds a texture that approximately matches the descriptor. Will be at least as large in width
     60      * and height as desc specifies. If desc specifies that the texture should be a render target
     61      * then result will be a render target. Format and sample count will always match the request.
     62      * The contents of the texture are undefined.
     63      */
     64     sk_sp<GrTexture> createApproxTexture(const GrSurfaceDesc&, uint32_t flags);
     65 
     66     /** Create an exact fit texture with no initial data to upload.
     67      */
     68     sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, SkBudgeted, uint32_t flags = 0);
     69 
     70     sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, SkBudgeted,
     71                                    const GrMipLevel texels[], int mipLevelCount,
     72                                    SkDestinationSurfaceColorMode mipColorMode);
     73 
     74     sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel&);
     75 
     76     ///////////////////////////////////////////////////////////////////////////
     77     // Wrapped Backend Surfaces
     78 
     79     /**
     80      * Wraps an existing texture with a GrTexture object.
     81      *
     82      * OpenGL: if the object is a texture Gr may change its GL texture params
     83      *         when it is drawn.
     84      *
     85      * @return GrTexture object or NULL on failure.
     86      */
     87     sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture& tex,
     88                                         GrSurfaceOrigin origin,
     89                                         GrBackendTextureFlags flags,
     90                                         int sampleCnt,
     91                                         GrWrapOwnership = kBorrow_GrWrapOwnership);
     92 
     93     /**
     94      * Wraps an existing render target with a GrRenderTarget object. It is
     95      * similar to wrapBackendTexture but can be used to draw into surfaces
     96      * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
     97      * the client will resolve to a texture). Currently wrapped render targets
     98      * always use the kBorrow_GrWrapOwnership semantics.
     99      *
    100      * @return GrRenderTarget object or NULL on failure.
    101      */
    102     sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin);
    103 
    104     static const uint32_t kMinScratchTextureSize;
    105 
    106     /**
    107      * Either finds and refs, or creates an index buffer with a repeating pattern for drawing
    108      * contiguous vertices of a repeated mesh. If the return is non-null, the caller owns a ref on
    109      * the returned GrBuffer.
    110      *
    111      * @param pattern     the pattern of indices to repeat
    112      * @param patternSize size in bytes of the pattern
    113      * @param reps        number of times to repeat the pattern
    114      * @param vertCount   number of vertices the pattern references
    115      * @param key         Key to be assigned to the index buffer.
    116      *
    117      * @return The index buffer if successful, otherwise nullptr.
    118      */
    119     const GrBuffer* findOrCreatePatternedIndexBuffer(const uint16_t* pattern,
    120                                                      int patternSize,
    121                                                      int reps,
    122                                                      int vertCount,
    123                                                      const GrUniqueKey& key) {
    124         if (GrBuffer* buffer = this->findAndRefTByUniqueKey<GrBuffer>(key)) {
    125             return buffer;
    126         }
    127         return this->createPatternedIndexBuffer(pattern, patternSize, reps, vertCount, key);
    128     }
    129 
    130     /**
    131      * Returns an index buffer that can be used to render quads.
    132      * Six indices per quad: 0, 1, 2, 0, 2, 3, etc.
    133      * The max number of quads is the buffer's index capacity divided by 6.
    134      * Draw with GrPrimitiveType::kTriangles
    135      * @ return the quad index buffer
    136      */
    137     const GrBuffer* refQuadIndexBuffer() {
    138         if (GrBuffer* buffer =
    139             this->findAndRefTByUniqueKey<GrBuffer>(fQuadIndexBufferKey)) {
    140             return buffer;
    141         }
    142         return this->createQuadIndexBuffer();
    143     }
    144 
    145     /**
    146      * Factories for GrPath and GrPathRange objects. It's an error to call these if path rendering
    147      * is not supported.
    148      */
    149     sk_sp<GrPath> createPath(const SkPath&, const GrStyle&);
    150     sk_sp<GrPathRange> createPathRange(GrPathRange::PathGenerator*, const GrStyle&);
    151     sk_sp<GrPathRange> createGlyphs(const SkTypeface*, const SkScalerContextEffects&,
    152                                     const SkDescriptor*, const GrStyle&);
    153 
    154     /** These flags govern which scratch resources we are allowed to return */
    155     enum Flags {
    156         kExact_Flag           = 0x1,
    157 
    158         /** If the caller intends to do direct reads/writes to/from the CPU then this flag must be
    159          *  set when accessing resources during a GrOpList flush. This includes the execution of
    160          *  GrOp objects. The reason is that these memory operations are done immediately and
    161          *  will occur out of order WRT the operations being flushed.
    162          *  Make this automatic: https://bug.skia.org/4156
    163          */
    164         kNoPendingIO_Flag     = 0x2,
    165 
    166         kNoCreate_Flag        = 0x4,
    167 
    168         /** Normally the caps may indicate a preference for client-side buffers. Set this flag when
    169          *  creating a buffer to guarantee it resides in GPU memory.
    170          */
    171         kRequireGpuMemory_Flag = 0x8,
    172     };
    173 
    174     /**
    175      * Returns a buffer.
    176      *
    177      * @param size            minimum size of buffer to return.
    178      * @param intendedType    hint to the graphics subsystem about what the buffer will be used for.
    179      * @param GrAccessPattern hint to the graphics subsystem about how the data will be accessed.
    180      * @param flags           see Flags enum.
    181      * @param data            optional data with which to initialize the buffer.
    182      *
    183      * @return the buffer if successful, otherwise nullptr.
    184      */
    185     GrBuffer* createBuffer(size_t size, GrBufferType intendedType, GrAccessPattern, uint32_t flags,
    186                            const void* data = nullptr);
    187 
    188 
    189     /**
    190      * If passed in render target already has a stencil buffer, return it. Otherwise attempt to
    191      * attach one.
    192      */
    193     GrStencilAttachment* attachStencilAttachment(GrRenderTarget* rt);
    194 
    195      /**
    196       * Wraps an existing texture with a GrRenderTarget object. This is useful when the provided
    197       * texture has a format that cannot be textured from by Skia, but we want to raster to it.
    198       *
    199       * The texture is wrapped as borrowed. The texture object will not be freed once the
    200       * render target is destroyed.
    201       *
    202       * @return GrRenderTarget object or NULL on failure.
    203       */
    204      sk_sp<GrRenderTarget> wrapBackendTextureAsRenderTarget(const GrBackendTexture&,
    205                                                             GrSurfaceOrigin origin,
    206                                                             int sampleCnt);
    207 
    208     /**
    209      * Assigns a unique key to a resource. If the key is associated with another resource that
    210      * association is removed and replaced by this resource.
    211      */
    212     void assignUniqueKeyToResource(const GrUniqueKey&, GrGpuResource*);
    213 
    214     /**
    215      * Finds a resource in the cache, based on the specified key. This is intended for use in
    216      * conjunction with addResourceToCache(). The return value will be NULL if not found. The
    217      * caller must balance with a call to unref().
    218      */
    219     GrGpuResource* findAndRefResourceByUniqueKey(const GrUniqueKey&);
    220 
    221     sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true);
    222 
    223     sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore&,
    224                                             GrWrapOwnership = kBorrow_GrWrapOwnership);
    225 
    226     // Takes the GrSemaphore and sets the ownership of the semaphore to the GrGpu object used by
    227     // this class. This call is only used when passing a GrSemaphore from one context to another.
    228     void takeOwnershipOfSemaphore(sk_sp<GrSemaphore>);
    229     // Takes the GrSemaphore and resets the ownership of the semaphore so that it is not owned by
    230     // any GrGpu. A follow up call to takeOwnershipofSemaphore must be made so that the underlying
    231     // semaphore can be deleted. This call is only used when passing a GrSemaphore from one context
    232     // to another.
    233     void releaseOwnershipOfSemaphore(sk_sp<GrSemaphore>);
    234 
    235     void abandon() {
    236         fCache = nullptr;
    237         fGpu = nullptr;
    238     }
    239 
    240     // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
    241     // determine if it is going to need a texture domain or a full clear.
    242     static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
    243 
    244     const GrCaps* caps() const { return fCaps.get(); }
    245 
    246 private:
    247     GrTexture* findAndRefTextureByUniqueKey(const GrUniqueKey& key);
    248     void assignUniqueKeyToTexture(const GrUniqueKey& key, GrTexture* texture);
    249 
    250     sk_sp<GrTexture> refScratchTexture(const GrSurfaceDesc&, uint32_t scratchTextureFlags);
    251 
    252     /*
    253      * Try to find an existing scratch texture that exactly matches 'desc'. If successful
    254      * update the budgeting accordingly.
    255      */
    256     sk_sp<GrTexture> getExactScratch(const GrSurfaceDesc&, SkBudgeted, uint32_t flags);
    257 
    258     GrResourceCache* cache() { return fCache; }
    259     const GrResourceCache* cache() const { return fCache; }
    260 
    261     GrGpu* gpu() { return fGpu; }
    262     const GrGpu* gpu() const { return fGpu; }
    263 
    264     bool isAbandoned() const {
    265         SkASSERT(SkToBool(fGpu) == SkToBool(fCache));
    266         return !SkToBool(fCache);
    267     }
    268 
    269     const GrBuffer* createPatternedIndexBuffer(const uint16_t* pattern,
    270                                                int patternSize,
    271                                                int reps,
    272                                                int vertCount,
    273                                                const GrUniqueKey& key);
    274 
    275     const GrBuffer* createQuadIndexBuffer();
    276 
    277     GrResourceCache*    fCache;
    278     GrGpu*              fGpu;
    279     sk_sp<const GrCaps> fCaps;
    280     GrUniqueKey         fQuadIndexBufferKey;
    281 
    282     // In debug builds we guard against improper thread handling
    283     SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
    284 };
    285 
    286 #endif
    287