• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/gpu/GrContextOptions.h"
12 #include "include/private/SkImageInfoPriv.h"
13 #include "src/gpu/GrGpuBuffer.h"
14 #include "src/gpu/GrResourceCache.h"
15 
16 class GrAttachment;
17 class GrBackendRenderTarget;
18 class GrBackendSemaphore;
19 class GrBackendTexture;
20 class GrGpu;
21 class GrMSAAAttachment;
22 class GrPath;
23 class GrRenderTarget;
24 class GrResourceProviderPriv;
25 class GrSemaphore;
26 class GrSingleOwner;
27 class GrTexture;
28 struct GrVkDrawableInfo;
29 
30 class GrStyle;
31 class SkDescriptor;
32 class SkPath;
33 class SkTypeface;
34 
35 namespace skgpu { struct VertexWriter; }
36 
37 /**
38  * A factory for arbitrary resource types.
39  */
40 class GrResourceProvider {
41 public:
42     GrResourceProvider(GrGpu*, GrResourceCache*, GrSingleOwner*);
43 
44     /**
45      * Finds a resource in the cache, based on the specified key. Prior to calling this, the caller
46      * must be sure that if a resource of exists in the cache with the given unique key then it is
47      * of type T.
48      */
49     template <typename T = GrGpuResource>
50     typename std::enable_if<std::is_base_of<GrGpuResource, T>::value, sk_sp<T>>::type
findByUniqueKey(const GrUniqueKey & key)51     findByUniqueKey(const GrUniqueKey& key) {
52         return sk_sp<T>(static_cast<T*>(this->findResourceByUniqueKey(key).release()));
53     }
54 
55     ///////////////////////////////////////////////////////////////////////////
56     // Textures
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 renderable is kYes then the GrTexture will also be a
61      * GrRenderTarget. The texture's format and sample count will always match the request.
62      * The contents of the texture are undefined.
63      */
64     sk_sp<GrTexture> createApproxTexture(SkISize dimensions,
65                                          const GrBackendFormat& format,
66                                          GrTextureType textureType,
67                                          GrRenderable renderable,
68                                          int renderTargetSampleCnt,
69                                          GrProtected isProtected);
70 
71     /** Create an exact fit texture with no initial data to upload. */
72     sk_sp<GrTexture> createTexture(SkISize dimensions,
73                                    const GrBackendFormat& format,
74                                    GrTextureType textureType,
75                                    GrRenderable renderable,
76                                    int renderTargetSampleCnt,
77                                    GrMipmapped mipMapped,
78                                    SkBudgeted budgeted,
79                                    GrProtected isProtected);
80 
81     /**
82      * Create an exact fit texture with initial data to upload. The color type must be valid
83      * for the format and also describe the texel data. This will ensure any conversions that
84      * need to get applied to the data before upload are applied.
85      */
86     sk_sp<GrTexture> createTexture(SkISize dimensions,
87                                    const GrBackendFormat& format,
88                                    GrTextureType textureType,
89                                    GrColorType colorType,
90                                    GrRenderable renderable,
91                                    int renderTargetSampleCnt,
92                                    SkBudgeted budgeted,
93                                    GrMipMapped mipMapped,
94                                    GrProtected isProtected,
95                                    const GrMipLevel texels[]);
96 
97     /**
98      * Create a potentially loose fit texture with the provided data. The color type must be valid
99      * for the format and also describe the texel data. This will ensure any conversions that
100      * need to get applied to the data before upload are applied.
101      */
102     sk_sp<GrTexture> createTexture(SkISize dimensions,
103                                    const GrBackendFormat&,
104                                    GrTextureType textureType,
105                                    GrColorType srcColorType,
106                                    GrRenderable,
107                                    int renderTargetSampleCnt,
108                                    SkBudgeted,
109                                    SkBackingFit,
110                                    GrProtected,
111                                    const GrMipLevel& mipLevel);
112 
113     /**
114      * Search the cache for a scratch texture matching the provided arguments. Failing that
115      * it returns null. If non-null, the resulting texture is always budgeted.
116      */
117     sk_sp<GrTexture> findAndRefScratchTexture(const GrScratchKey&);
118     sk_sp<GrTexture> findAndRefScratchTexture(SkISize dimensions,
119                                               const GrBackendFormat&,
120                                               GrTextureType textureType,
121                                               GrRenderable,
122                                               int renderTargetSampleCnt,
123                                               GrMipmapped,
124                                               GrProtected);
125 
126     /**
127      * Creates a compressed texture. The GrGpu must support the SkImageImage::Compression type.
128      * It will not be renderable.
129      */
130     sk_sp<GrTexture> createCompressedTexture(SkISize dimensions,
131                                              const GrBackendFormat&,
132                                              SkBudgeted,
133                                              GrMipmapped,
134                                              GrProtected,
135                                              SkData* data);
136 
137     ///////////////////////////////////////////////////////////////////////////
138     // Wrapped Backend Surfaces
139 
140     /**
141      * Wraps an existing texture with a GrTexture object.
142      *
143      * GrIOType must either be kRead or kRW. kRead blocks any operations that would modify the
144      * pixels (e.g. dst for a copy, regenerating MIP levels, write pixels).
145      *
146      * OpenGL: if the object is a texture Gr may change its GL texture params
147      *         when it is drawn.
148      *
149      * @return GrTexture object or NULL on failure.
150      */
151     sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture& tex,
152                                         GrWrapOwnership,
153                                         GrWrapCacheable,
154                                         GrIOType);
155 
156     sk_sp<GrTexture> wrapCompressedBackendTexture(const GrBackendTexture& tex,
157                                                   GrWrapOwnership,
158                                                   GrWrapCacheable);
159 
160     /**
161      * This makes the backend texture be renderable. If sampleCnt is > 1 and the underlying API
162      * uses separate MSAA render buffers then a MSAA render buffer is created that resolves
163      * to the texture.
164      */
165     sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture& tex,
166                                                   int sampleCnt,
167                                                   GrWrapOwnership,
168                                                   GrWrapCacheable);
169 
170     /**
171      * Wraps an existing render target with a GrRenderTarget object. It is
172      * similar to wrapBackendTexture but can be used to draw into surfaces
173      * that are not also textures (e.g. FBO 0 in OpenGL, or an MSAA buffer that
174      * the client will resolve to a texture). Currently wrapped render targets
175      * always use the kBorrow_GrWrapOwnership and GrWrapCacheable::kNo semantics.
176      *
177      * @return GrRenderTarget object or NULL on failure.
178      */
179     sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&);
180 
181     sk_sp<GrRenderTarget> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&,
182                                                               const GrVkDrawableInfo&);
183 
184     static const int kMinScratchTextureSize;
185 
186     /**
187      * Either finds and refs a buffer with the given unique key, or creates a new new, fills its
188      * contents with the InitializeBufferDataFn() callback, and assigns it the unique key.
189      *
190      * @param intendedType        hint to the graphics subsystem about how the buffer will be used.
191      * @param size                minimum size of buffer to return.
192      * @param key                 Key to be assigned to the buffer.
193      * @param InitializeBufferFn  callback with which to initialize the buffer.
194      *
195      * @return The buffer if successful, otherwise nullptr.
196      */
197     using InitializeBufferFn = void(*)(skgpu::VertexWriter, size_t bufferSize);
198     sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size,
199                                                     const GrUniqueKey& key, InitializeBufferFn);
200 
201     /**
202      * Either finds and refs, or creates a static buffer with the given parameters and contents.
203      *
204      * @param intendedType    hint to the graphics subsystem about what the buffer will be used for.
205      * @param size            minimum size of buffer to return.
206      * @param data            optional data with which to initialize the buffer.
207      * @param key             Key to be assigned to the buffer.
208      *
209      * @return The buffer if successful, otherwise nullptr.
210      */
211     sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType, size_t size,
212                                                     const void* staticData, const GrUniqueKey& key);
213 
214     /**
215      * Either finds and refs, or creates an index buffer with a repeating pattern for drawing
216      * contiguous vertices of a repeated mesh. If the return is non-null, the caller owns a ref on
217      * the returned GrBuffer.
218      *
219      * @param pattern     the pattern of indices to repeat
220      * @param patternSize size in bytes of the pattern
221      * @param reps        number of times to repeat the pattern
222      * @param vertCount   number of vertices the pattern references
223      * @param key         Key to be assigned to the index buffer.
224      *
225      * @return The index buffer if successful, otherwise nullptr.
226      */
findOrCreatePatternedIndexBuffer(const uint16_t * pattern,int patternSize,int reps,int vertCount,const GrUniqueKey & key)227     sk_sp<const GrGpuBuffer> findOrCreatePatternedIndexBuffer(const uint16_t* pattern,
228                                                               int patternSize,
229                                                               int reps,
230                                                               int vertCount,
231                                                               const GrUniqueKey& key) {
232         if (auto buffer = this->findByUniqueKey<const GrGpuBuffer>(key)) {
233             return buffer;
234         }
235         return this->createPatternedIndexBuffer(pattern, patternSize, reps, vertCount, &key);
236     }
237 
238     /**
239      * Returns an index buffer that can be used to render non-antialiased quads.
240      * Each quad consumes 6 indices (0, 1, 2, 2, 1, 3) and 4 vertices.
241      * Call MaxNumNonAAQuads to get the max allowed number of non-AA quads.
242      * Draw with GrPrimitiveType::kTriangles
243      * @ return the non-AA quad index buffer
244      */
refNonAAQuadIndexBuffer()245     sk_sp<const GrGpuBuffer> refNonAAQuadIndexBuffer() {
246         if (!fNonAAQuadIndexBuffer) {
247             fNonAAQuadIndexBuffer = this->createNonAAQuadIndexBuffer();
248         }
249         return fNonAAQuadIndexBuffer;
250     }
251 
252     static int MaxNumNonAAQuads();
253     static int NumVertsPerNonAAQuad();
254     static int NumIndicesPerNonAAQuad();
255 
256     /**
257      * Returns an index buffer that can be used to render antialiased quads.
258      * Each quad consumes 30 indices and 8 vertices.
259      * Call MaxNumAAQuads to get the max allowed number of AA quads.
260      * Draw with GrPrimitiveType::kTriangles
261      * @ return the AA quad index buffer
262      */
refAAQuadIndexBuffer()263     sk_sp<const GrGpuBuffer> refAAQuadIndexBuffer() {
264         if (!fAAQuadIndexBuffer) {
265             fAAQuadIndexBuffer = this->createAAQuadIndexBuffer();
266         }
267         return fAAQuadIndexBuffer;
268     }
269 
270     static int MaxNumAAQuads();
271     static int NumVertsPerAAQuad();
272     static int NumIndicesPerAAQuad();
273 
274     /**
275      * Returns a buffer.
276      *
277      * @param size            minimum size of buffer to return.
278      * @param intendedType    hint to the graphics subsystem about what the buffer will be used for.
279      * @param GrAccessPattern hint to the graphics subsystem about how the data will be accessed.
280      * @param flags           see Flags enum.
281      * @param data            optional data with which to initialize the buffer.
282      *
283      * @return the buffer if successful, otherwise nullptr.
284      */
285     sk_sp<GrGpuBuffer> createBuffer(size_t size,
286                                     GrGpuBufferType intendedType,
287                                     GrAccessPattern,
288                                     const void* data = nullptr);
289 
290     /**
291      * If passed in render target already has a stencil buffer on the specified surface, return
292      * true. Otherwise attempt to attach one and return true on success.
293      */
294     bool attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface);
295 
296     sk_sp<GrAttachment> makeMSAAAttachment(SkISize dimensions,
297                                            const GrBackendFormat& format,
298                                            int sampleCnt,
299                                            GrProtected isProtected,
300                                            GrMemoryless isMemoryless);
301 
302     /**
303      * Gets a GrAttachment that can be used for MSAA rendering. This attachment may be shared by
304      * other users. Thus any renderpass that uses the attachment should not assume any specific
305      * data at the start and should not try to save written data at the end. Ideally the render pass
306      * should discard the data at the end.
307      */
308     sk_sp<GrAttachment> getDiscardableMSAAAttachment(SkISize dimensions,
309                                                      const GrBackendFormat& format,
310                                                      int sampleCnt,
311                                                      GrProtected isProtected,
312                                                      GrMemoryless memoryless);
313 
314     /**
315      * Assigns a unique key to a resource. If the key is associated with another resource that
316      * association is removed and replaced by this resource.
317      */
318     void assignUniqueKeyToResource(const GrUniqueKey&, GrGpuResource*);
319 
320     std::unique_ptr<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true);
321 
322     std::unique_ptr<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore&,
323                                                       GrSemaphoreWrapType,
324                                                       GrWrapOwnership = kBorrow_GrWrapOwnership);
325 
abandon()326     void abandon() {
327         fCache = nullptr;
328         fGpu = nullptr;
329     }
330 
contextUniqueID()331     uint32_t contextUniqueID() const { return fCache->contextUniqueID(); }
caps()332     const GrCaps* caps() const { return fCaps.get(); }
overBudget()333     bool overBudget() const { return fCache->overBudget(); }
334 
335     static SkISize MakeApprox(SkISize);
336 
337     inline GrResourceProviderPriv priv();
338     inline const GrResourceProviderPriv priv() const;  // NOLINT(readability-const-return-type)
339 
340 private:
341     sk_sp<GrGpuResource> findResourceByUniqueKey(const GrUniqueKey&);
342 
343     /*
344      * Try to find an existing scratch texture that exactly matches 'desc'. If successful
345      * update the budgeting accordingly.
346      */
347     sk_sp<GrTexture> getExactScratch(SkISize dimensions,
348                                      const GrBackendFormat&,
349                                      GrTextureType,
350                                      GrRenderable,
351                                      int renderTargetSampleCnt,
352                                      SkBudgeted,
353                                      GrMipmapped,
354                                      GrProtected);
355 
356     // Attempts to find a resource in the cache that exactly matches the SkISize. Failing that
357     // it returns null. If non-null, the resulting msaa attachment is always budgeted.
358     sk_sp<GrAttachment> refScratchMSAAAttachment(SkISize dimensions,
359                                                  const GrBackendFormat&,
360                                                  int sampleCnt,
361                                                  GrProtected,
362                                                  GrMemoryless memoryless);
363 
364     // Used to perform any conversions necessary to texel data before creating a texture with
365     // existing data or uploading to a scratch texture.
366     using TempLevels = SkAutoSTArray<14, GrMipLevel>;
367     using TempLevelDatas = SkAutoSTArray<14, std::unique_ptr<char[]>>;
368     GrColorType prepareLevels(const GrBackendFormat& format,
369                               GrColorType,
370                               SkISize baseSize,
371                               const GrMipLevel texels[],
372                               int mipLevelCount,
373                               TempLevels*,
374                               TempLevelDatas*) const;
375 
376     // GrResourceProvider may be asked to "create" a new texture with initial pixel data to populate
377     // it. In implementation it may pull an existing texture from GrResourceCache and then write the
378     // pixel data to the texture. It takes a width/height for the base level because we may be
379     // using an approximate-sized scratch texture. On success the texture is returned and nullptr
380     // on failure.
381     sk_sp<GrTexture> writePixels(sk_sp<GrTexture> texture,
382                                  GrColorType colorType,
383                                  SkISize baseSize,
384                                  const GrMipLevel texels[],
385                                  int mipLevelCount) const;
386 
cache()387     GrResourceCache* cache() { return fCache; }
cache()388     const GrResourceCache* cache() const { return fCache; }
389 
390     friend class GrResourceProviderPriv;
391 
392     // Method made available via GrResourceProviderPriv
gpu()393     GrGpu* gpu() { return fGpu; }
gpu()394     const GrGpu* gpu() const { return fGpu; }
395 
isAbandoned()396     bool isAbandoned() const {
397         SkASSERT(SkToBool(fGpu) == SkToBool(fCache));
398         return !SkToBool(fCache);
399     }
400 
401     sk_sp<const GrGpuBuffer> createPatternedIndexBuffer(const uint16_t* pattern,
402                                                         int patternSize,
403                                                         int reps,
404                                                         int vertCount,
405                                                         const GrUniqueKey* key);
406 
407     sk_sp<const GrGpuBuffer> createNonAAQuadIndexBuffer();
408     sk_sp<const GrGpuBuffer> createAAQuadIndexBuffer();
409 
410     GrResourceCache* fCache;
411     GrGpu* fGpu;
412     sk_sp<const GrCaps> fCaps;
413     sk_sp<const GrGpuBuffer> fNonAAQuadIndexBuffer;
414     sk_sp<const GrGpuBuffer> fAAQuadIndexBuffer;
415 
416     // In debug builds we guard against improper thread handling
417     SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
418 };
419 
420 #endif
421