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