1 /*
2  * Copyright 2018 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 GrProxyProvider_DEFINED
9 #define GrProxyProvider_DEFINED
10 
11 #include "GrResourceKey.h"
12 #include "GrTextureProxy.h"
13 #include "GrTypes.h"
14 #include "SkTDynamicHash.h"
15 
16 class GrImageContext;
17 class GrBackendRenderTarget;
18 class SkBitmap;
19 class SkImage;
20 
21 /*
22  * A factory for creating GrSurfaceProxy-derived objects.
23  */
24 class GrProxyProvider {
25 public:
26     GrProxyProvider(GrImageContext*);
27 
28     ~GrProxyProvider();
29 
30     /*
31      * Assigns a unique key to a proxy. The proxy will be findable via this key using
32      * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
33      */
34     bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
35 
36     /*
37      * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
38      * have a valid unique key.
39      */
40     void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);
41 
42     /*
43      * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
44      * also remove the unique key from the target GrSurface.
45      */
46     void removeUniqueKeyFromProxy(GrTextureProxy*);
47 
48     /*
49      * Finds a proxy by unique key.
50      */
51     sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
52 
53     /*
54      * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
55      * key.
56      */
57     sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
58 
59     /*
60      * Create an un-mipmapped texture proxy with data. The SkImage must be a raster backend image.
61      * Since the SkImage is ref counted, we simply take a ref on it to keep the data alive until we
62      * actually upload the data to the gpu.
63      */
64     sk_sp<GrTextureProxy> createTextureProxy(
65             sk_sp<SkImage> srcImage, GrSurfaceDescFlags, int sampleCnt, SkBudgeted, SkBackingFit,
66             GrInternalSurfaceFlags = GrInternalSurfaceFlags::kNone);
67 
68     /*
69      * Create a mipmapped texture proxy without any data.
70      *
71      * Like the call above but there are no texels to upload. A texture proxy is returned that
72      * simply has space allocated for the mips. We will allocated the full amount of mip levels
73      * based on the width and height in the GrSurfaceDesc.
74      */
75     sk_sp<GrTextureProxy> createMipMapProxy(const GrBackendFormat&, const GrSurfaceDesc&,
76                                             GrSurfaceOrigin, SkBudgeted);
77 
78     /*
79      * Creates a new mipmapped texture proxy for the bitmap with mip levels generated by the cpu.
80      */
81     sk_sp<GrTextureProxy> createMipMapProxyFromBitmap(const SkBitmap& bitmap);
82 
83     /*
84      * Create a GrSurfaceProxy without any data.
85      */
86     sk_sp<GrTextureProxy> createProxy(const GrBackendFormat&, const GrSurfaceDesc&, GrSurfaceOrigin,
87                                       GrMipMapped, SkBackingFit, SkBudgeted,
88                                       GrInternalSurfaceFlags);
89 
90     sk_sp<GrTextureProxy> createProxy(
91                             const GrBackendFormat& format, const GrSurfaceDesc& desc,
92                             GrSurfaceOrigin origin, SkBackingFit fit, SkBudgeted budgeted,
93                             GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone) {
94         return this->createProxy(format, desc, origin, GrMipMapped::kNo, fit, budgeted,
95                                  surfaceFlags);
96     }
97 
98     /*
99      * Create a texture proxy with data. It's assumed that the data is packed tightly.
100      */
101     sk_sp<GrTextureProxy> createProxy(sk_sp<SkData>, const GrSurfaceDesc& desc);
102 
103     // These match the definitions in SkImage & GrTexture.h, for whence they came
104     typedef void* ReleaseContext;
105     typedef void (*ReleaseProc)(ReleaseContext);
106 
107     /*
108      * Create a texture proxy that wraps a (non-renderable) backend texture. GrIOType must be
109      * kRead or kRW.
110      */
111     sk_sp<GrTextureProxy> wrapBackendTexture(const GrBackendTexture&, GrSurfaceOrigin,
112                                              GrWrapOwnership, GrWrapCacheable, GrIOType,
113                                              ReleaseProc = nullptr, ReleaseContext = nullptr);
114 
115     /*
116      * Create a texture proxy that wraps a backend texture and is both texture-able and renderable
117      */
118     sk_sp<GrTextureProxy> wrapRenderableBackendTexture(const GrBackendTexture&, GrSurfaceOrigin,
119                                                        int sampleCnt, GrWrapOwnership,
120                                                        GrWrapCacheable, ReleaseProc,
121                                                        ReleaseContext);
122 
123     /*
124      * Create a render target proxy that wraps a backend render target
125      */
126     sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin,
127                                                   ReleaseProc, ReleaseContext);
128 
129     /*
130      * Create a render target proxy that wraps a backend texture
131      */
132     sk_sp<GrSurfaceProxy> wrapBackendTextureAsRenderTarget(const GrBackendTexture& backendTex,
133                                                            GrSurfaceOrigin origin,
134                                                            int sampleCnt);
135 
136     sk_sp<GrRenderTargetProxy> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&,
137                                                                    const GrVkDrawableInfo&);
138 
139     using LazyInstantiateCallback = std::function<sk_sp<GrSurface>(GrResourceProvider*)>;
140 
141     enum class Renderable : bool {
142         kNo = false,
143         kYes = true
144     };
145 
146     struct TextureInfo {
147         GrMipMapped fMipMapped;
148         GrTextureType fTextureType;
149     };
150 
151     using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
152     /**
153      * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
154      * (Stencil is not supported by this method.) The width and height must either both be greater
155      * than 0 or both less than or equal to zero. A non-positive value is a signal that the width
156      * and height are currently unknown.
157      *
158      * When called, the callback must be able to cleanup any resources that it captured at creation.
159      * It also must support being passed in a null GrResourceProvider. When this happens, the
160      * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
161      */
162     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
163                                           const GrSurfaceDesc&, GrSurfaceOrigin, GrMipMapped,
164                                           GrInternalSurfaceFlags, SkBackingFit, SkBudgeted,
165                                           LazyInstantiationType);
166 
167     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
168                                           const GrSurfaceDesc&, GrSurfaceOrigin, GrMipMapped,
169                                           GrInternalSurfaceFlags, SkBackingFit, SkBudgeted);
170 
171     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrBackendFormat&,
172                                           const GrSurfaceDesc&, GrSurfaceOrigin, GrMipMapped,
173                                           SkBackingFit, SkBudgeted);
174 
175     /** A null TextureInfo indicates a non-textureable render target. */
176     sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
177                                                            const GrBackendFormat&,
178                                                            const GrSurfaceDesc&,
179                                                            GrSurfaceOrigin origin,
180                                                            GrInternalSurfaceFlags,
181                                                            const TextureInfo*,
182                                                            SkBackingFit,
183                                                            SkBudgeted,
184                                                            bool wrapsVkSecondaryCB);
185 
186     /**
187      * Fully lazy proxies have unspecified width and height. Methods that rely on those values
188      * (e.g., width, height, getBoundsRect) should be avoided.
189      */
190     static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&,
191                                                     const GrBackendFormat&, Renderable,
192                                                     GrSurfaceOrigin, GrPixelConfig, const GrCaps&);
193 
194     // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
195     // determine if it is going to need a texture domain or a full clear.
196     static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
197 
198     enum class InvalidateGPUResource : bool { kNo = false, kYes = true };
199 
200     /*
201      * This method ensures that, if a proxy w/ the supplied unique key exists, it is removed from
202      * the proxy provider's map and its unique key is removed. If 'invalidateSurface' is true, it
203      * will independently ensure that the unique key is removed from any GrGpuResources that may
204      * have it.
205      *
206      * If 'proxy' is provided (as an optimization to stop re-looking it up), its unique key must be
207      * valid and match the provided unique key.
208      *
209      * This method is called if either the proxy attached to the unique key is being deleted
210      * (in which case we don't want it cluttering up the hash table) or the client has indicated
211      * that it will never refer to the unique key again.
212      */
213     void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource);
214 
215     // TODO: remove these entry points - it is a bit sloppy to be getting context info from here
216     uint32_t contextID() const;
217     const GrCaps* caps() const;
218     sk_sp<const GrCaps> refCaps() const;
219 
220     int numUniqueKeyProxies_TestOnly() const;
221 
222     // This is called on a DDL's proxyprovider when the DDL is finished. The uniquely keyed
223     // proxies need to keep their unique key but cannot hold on to the proxy provider unique
224     // pointer.
225     void orphanAllUniqueKeys();
226     // This is only used by GrContext::releaseResourcesAndAbandonContext()
227     void removeAllUniqueKeys();
228 
229     /**
230      * Does the proxy provider have access to a GrDirectContext? If so, proxies will be
231      * instantiated immediately.
232      */
233     bool renderingDirectly() const;
234 
235 #if GR_TEST_UTILS
236     /*
237      * Create a texture proxy that is backed by an instantiated GrSurface.
238      */
239     sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(const GrSurfaceDesc&, GrSurfaceOrigin,
240                                                               SkBackingFit, SkBudgeted);
241     sk_sp<GrTextureProxy> testingOnly_createWrapped(sk_sp<GrTexture>, GrSurfaceOrigin);
242 #endif
243 
244 private:
245     friend class GrAHardwareBufferImageGenerator; // for createWrapped
246     friend class GrResourceProvider; // for createWrapped
247 
248     bool isAbandoned() const;
249 
250     sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);
251 
252     struct UniquelyKeyedProxyHashTraits {
GetKeyUniquelyKeyedProxyHashTraits253         static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
254 
HashUniquelyKeyedProxyHashTraits255         static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
256     };
257     typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
258 
259     // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
260     // on these proxies but they must send a message to the resourceCache when they are deleted.
261     UniquelyKeyedProxyHash fUniquelyKeyedProxies;
262 
263     GrImageContext*        fImageContext;
264 };
265 
266 #endif
267