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