xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrResourceProvider.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/SkTypes.h"
13 #include "include/private/base/SkDebug.h"
14 #include "include/private/base/SkTemplates.h"
15 #include "include/private/base/SkTo.h"
16 #include "include/private/gpu/ganesh/GrTypesPriv.h"
17 #include "src/gpu/BufferWriter.h"
18 #include "src/gpu/ganesh/GrCaps.h"
19 #include "src/gpu/ganesh/GrGpuBuffer.h"
20 #include "src/gpu/ganesh/GrGpuResource.h"
21 #include "src/gpu/ganesh/GrResourceCache.h"
22 
23 #include <cstddef>
24 #include <cstdint>
25 #include <memory>
26 #include <string_view>
27 #include <type_traits>
28 
29 class GrAttachment;
30 class GrBackendFormat;
31 class GrBackendRenderTarget;
32 class GrBackendSemaphore;
33 class GrBackendTexture;
34 class GrGpu;
35 class GrRenderTarget;
36 class GrResourceProviderPriv;
37 class GrSemaphore;
38 class GrTexture;
39 class SkData;
40 
41 enum class SkBackingFit;
42 struct GrVkDrawableInfo;
43 struct SkImageInfo;
44 struct SkISize;
45 
46 namespace skgpu {
47 class ScratchKey;
48 class SingleOwner;
49 class UniqueKey;
50 enum class Budgeted : bool;
51 enum class Mipmapped : bool;
52 enum class Protected : bool;
53 enum class Renderable : 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                                          skgpu::Renderable renderable,
87                                          int renderTargetSampleCnt,
88                                          skgpu::Protected 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                                    skgpu::Renderable renderable,
96                                    int renderTargetSampleCnt,
97                                    skgpu::Mipmapped mipmapped,
98                                    skgpu::Budgeted budgeted,
99                                    skgpu::Protected 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                                    skgpu::Renderable renderable,
112                                    int renderTargetSampleCnt,
113                                    skgpu::Budgeted budgeted,
114                                    skgpu::Mipmapped mipmapped,
115                                    skgpu::Protected 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                                    skgpu::Renderable,
129                                    int renderTargetSampleCnt,
130                                    skgpu::Budgeted,
131                                    SkBackingFit,
132                                    skgpu::Protected,
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                                               skgpu::Renderable,
145                                               int renderTargetSampleCnt,
146                                               skgpu::Mipmapped,
147                                               skgpu::Protected,
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                                              skgpu::Protected,
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     /**
210      * Either finds and refs a buffer with the given unique key, or creates a new new, fills its
211      * contents with the InitializeBufferDataFn() callback, and assigns it the unique key.
212      *
213      * @param intendedType        hint to the graphics subsystem about how the buffer will be used.
214      * @param size                minimum size of buffer to return.
215      * @param key                 Key to be assigned to the buffer.
216      * @param InitializeBufferFn  callback with which to initialize the buffer.
217      *
218      * @return The buffer if successful, otherwise nullptr.
219      */
220     using InitializeBufferFn = void(*)(skgpu::VertexWriter, size_t bufferSize);
221     sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType,
222                                                     size_t size,
223                                                     const skgpu::UniqueKey& key,
224                                                     InitializeBufferFn);
225 
226     /**
227      * Either finds and refs, or creates a static buffer with the given parameters and contents.
228      *
229      * @param intendedType    hint to the graphics subsystem about what the buffer will be used for.
230      * @param size            minimum size of buffer to return.
231      * @param data            optional data with which to initialize the buffer.
232      * @param key             Key to be assigned to the buffer.
233      *
234      * @return The buffer if successful, otherwise nullptr.
235      */
236     sk_sp<const GrGpuBuffer> findOrMakeStaticBuffer(GrGpuBufferType intendedType,
237                                                     size_t size,
238                                                     const void* staticData,
239                                                     const skgpu::UniqueKey& key);
240 
241     /**
242      * Either finds and refs, or creates an index buffer with a repeating pattern for drawing
243      * contiguous vertices of a repeated mesh. If the return is non-null, the caller owns a ref on
244      * the returned GrBuffer.
245      *
246      * @param pattern     the pattern of indices to repeat
247      * @param patternSize size in bytes of the pattern
248      * @param reps        number of times to repeat the pattern
249      * @param vertCount   number of vertices the pattern references
250      * @param key         Key to be assigned to the index buffer.
251      *
252      * @return The index buffer if successful, otherwise nullptr.
253      */
findOrCreatePatternedIndexBuffer(const uint16_t * pattern,int patternSize,int reps,int vertCount,const skgpu::UniqueKey & key)254     sk_sp<const GrGpuBuffer> findOrCreatePatternedIndexBuffer(const uint16_t* pattern,
255                                                               int patternSize,
256                                                               int reps,
257                                                               int vertCount,
258                                                               const skgpu::UniqueKey& key) {
259         if (auto buffer = this->findByUniqueKey<const GrGpuBuffer>(key)) {
260             return buffer;
261         }
262         return this->createPatternedIndexBuffer(pattern, patternSize, reps, vertCount, &key);
263     }
264 
265     /**
266      * Returns an index buffer that can be used to render non-antialiased quads.
267      * Each quad consumes 6 indices (0, 1, 2, 2, 1, 3) and 4 vertices.
268      * Call MaxNumNonAAQuads to get the max allowed number of non-AA quads.
269      * Draw with GrPrimitiveType::kTriangles
270      * @ return the non-AA quad index buffer
271      */
refNonAAQuadIndexBuffer()272     sk_sp<const GrGpuBuffer> refNonAAQuadIndexBuffer() {
273         if (!fNonAAQuadIndexBuffer) {
274             fNonAAQuadIndexBuffer = this->createNonAAQuadIndexBuffer();
275         }
276         return fNonAAQuadIndexBuffer;
277     }
278 
279     static int MaxNumNonAAQuads();
280     static int NumVertsPerNonAAQuad();
281     static int NumIndicesPerNonAAQuad();
282 
283     /**
284      * Returns an index buffer that can be used to render antialiased quads.
285      * Each quad consumes 30 indices and 8 vertices.
286      * Call MaxNumAAQuads to get the max allowed number of AA quads.
287      * Draw with GrPrimitiveType::kTriangles
288      * @ return the AA quad index buffer
289      */
refAAQuadIndexBuffer()290     sk_sp<const GrGpuBuffer> refAAQuadIndexBuffer() {
291         if (!fAAQuadIndexBuffer) {
292             fAAQuadIndexBuffer = this->createAAQuadIndexBuffer();
293         }
294         return fAAQuadIndexBuffer;
295     }
296 
297     static int MaxNumAAQuads();
298     static int NumVertsPerAAQuad();
299     static int NumIndicesPerAAQuad();
300 
301     enum class ZeroInit : bool { kNo = false, kYes = true };
302 
303     /**
304      * Returns a buffer.
305      *
306      * @param size            minimum size of buffer to return.
307      * @param GrGpuBufferType hint to the graphics subsystem about what the buffer will be used for.
308      * @param GrAccessPattern hint to the graphics subsystem about how the data will be accessed.
309      * @param ZeroInit        if kYes zero-initialize the buffer. Otherwise, contents are undefined.
310      *
311      * @return the buffer if successful, otherwise nullptr.
312      */
313     sk_sp<GrGpuBuffer> createBuffer(size_t size, GrGpuBufferType, GrAccessPattern, ZeroInit);
314 
315     /** Same as above but also fills the buffer from data. */
316     sk_sp<GrGpuBuffer> createBuffer(const void* data,
317                                     size_t size,
318                                     GrGpuBufferType type,
319                                     GrAccessPattern pattern);
320 
321     /**
322      * If passed in render target already has a stencil buffer on the specified surface, return
323      * true. Otherwise attempt to attach one and return true on success.
324      */
325     bool attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface);
326 
327     sk_sp<GrAttachment> makeMSAAAttachment(SkISize dimensions,
328                                            const GrBackendFormat& format,
329                                            int sampleCnt,
330                                            skgpu::Protected isProtected,
331                                            GrMemoryless isMemoryless);
332 
333     /**
334      * Gets a GrAttachment that can be used for MSAA rendering. This attachment may be shared by
335      * other users. Thus any renderpass that uses the attachment should not assume any specific
336      * data at the start and should not try to save written data at the end. Ideally the render pass
337      * should discard the data at the end.
338      */
339     sk_sp<GrAttachment> getDiscardableMSAAAttachment(SkISize dimensions,
340                                                      const GrBackendFormat& format,
341                                                      int sampleCnt,
342                                                      skgpu::Protected isProtected,
343                                                      GrMemoryless memoryless);
344 
345     /**
346      * Assigns a unique key to a resource. If the key is associated with another resource that
347      * association is removed and replaced by this resource.
348      */
349     void assignUniqueKeyToResource(const skgpu::UniqueKey&, GrGpuResource*);
350 
351     [[nodiscard]] std::unique_ptr<GrSemaphore> makeSemaphore(bool isOwned = true);
352 
353     std::unique_ptr<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore&,
354                                                       GrSemaphoreWrapType,
355                                                       GrWrapOwnership = kBorrow_GrWrapOwnership);
356 
abandon()357     void abandon() {
358         fCache = nullptr;
359         fGpu = nullptr;
360     }
361 
contextUniqueID()362     uint32_t contextUniqueID() const { return fCache->contextUniqueID(); }
caps()363     const GrCaps* caps() const { return fCaps.get(); }
overBudget()364     bool overBudget() const { return fCache->overBudget(); }
365 
366     inline GrResourceProviderPriv priv();
367     inline const GrResourceProviderPriv priv() const;  // NOLINT(readability-const-return-type)
368 
369 private:
370     sk_sp<GrGpuResource> findResourceByUniqueKey(const skgpu::UniqueKey&);
371 
372     /*
373      * Try to find an existing scratch texture that exactly matches 'desc'. If successful
374      * update the budgeting accordingly.
375      */
376     sk_sp<GrTexture> getExactScratch(SkISize dimensions,
377                                      const GrBackendFormat&,
378                                      GrTextureType,
379                                      skgpu::Renderable,
380                                      int renderTargetSampleCnt,
381                                      skgpu::Budgeted,
382                                      skgpu::Mipmapped,
383                                      skgpu::Protected,
384                                      std::string_view label);
385 
386     // Attempts to find a resource in the cache that exactly matches the SkISize. Failing that
387     // it returns null. If non-null, the resulting msaa attachment is always budgeted.
388     sk_sp<GrAttachment> refScratchMSAAAttachment(SkISize dimensions,
389                                                  const GrBackendFormat&,
390                                                  int sampleCnt,
391                                                  skgpu::Protected,
392                                                  GrMemoryless memoryless,
393                                                  std::string_view label);
394 
395     // Used to perform any conversions necessary to texel data before creating a texture with
396     // existing data or uploading to a scratch texture.
397     using TempLevels = skia_private::AutoSTArray<14, GrMipLevel>;
398     using TempLevelDatas = skia_private::AutoSTArray<14, std::unique_ptr<char[]>>;
399     GrColorType prepareLevels(const GrBackendFormat& format,
400                               GrColorType,
401                               SkISize baseSize,
402                               const GrMipLevel texels[],
403                               int mipLevelCount,
404                               TempLevels*,
405                               TempLevelDatas*) const;
406 
407     // GrResourceProvider may be asked to "create" a new texture with initial pixel data to populate
408     // it. In implementation it may pull an existing texture from GrResourceCache and then write the
409     // pixel data to the texture. It takes a width/height for the base level because we may be
410     // using an approximate-sized scratch texture. On success the texture is returned and nullptr
411     // on failure.
412     sk_sp<GrTexture> writePixels(sk_sp<GrTexture> texture,
413                                  GrColorType colorType,
414                                  SkISize baseSize,
415                                  const GrMipLevel texels[],
416                                  int mipLevelCount) const;
417 
cache()418     GrResourceCache* cache() { return fCache; }
cache()419     const GrResourceCache* cache() const { return fCache; }
420 
421     friend class GrResourceProviderPriv;
422 
423     // Method made available via GrResourceProviderPriv
gpu()424     GrGpu* gpu() { return fGpu; }
gpu()425     const GrGpu* gpu() const { return fGpu; }
426 
isAbandoned()427     bool isAbandoned() const {
428         SkASSERT(SkToBool(fGpu) == SkToBool(fCache));
429         return !SkToBool(fCache);
430     }
431 
432     sk_sp<const GrGpuBuffer> createPatternedIndexBuffer(const uint16_t* pattern,
433                                                         int patternSize,
434                                                         int reps,
435                                                         int vertCount,
436                                                         const skgpu::UniqueKey* key);
437 
438     sk_sp<const GrGpuBuffer> createNonAAQuadIndexBuffer();
439     sk_sp<const GrGpuBuffer> createAAQuadIndexBuffer();
440 
441     GrResourceCache* fCache;
442     GrGpu* fGpu;
443     sk_sp<const GrCaps> fCaps;
444     sk_sp<const GrGpuBuffer> fNonAAQuadIndexBuffer;
445     sk_sp<const GrGpuBuffer> fAAQuadIndexBuffer;
446 
447     // In debug builds we guard against improper thread handling
448     SkDEBUGCODE(mutable skgpu::SingleOwner* fSingleOwner;)
449 };
450 
451 #endif
452