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