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 "include/gpu/GrTypes.h" |
12 | #include "include/private/GrResourceKey.h" |
13 | #include "src/core/SkTDynamicHash.h" |
14 | #include "src/gpu/GrTextureProxy.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 | using UseAllocator = GrSurfaceProxy::UseAllocator; |
27 | |
28 | GrProxyProvider(GrImageContext*); |
29 | |
30 | ~GrProxyProvider(); |
31 | |
32 | /* |
33 | * Assigns a unique key to a proxy. The proxy will be findable via this key using |
34 | * findProxyByUniqueKey(). It is an error if an existing proxy already has a key. |
35 | */ |
36 | bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*); |
37 | |
38 | /* |
39 | * Sets the unique key of the provided proxy to the unique key of the surface. The surface must |
40 | * have a valid unique key. |
41 | */ |
42 | void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*); |
43 | |
44 | /* |
45 | * Removes a unique key from a proxy. If the proxy has already been instantiated, it will |
46 | * also remove the unique key from the target GrSurface. |
47 | */ |
48 | void removeUniqueKeyFromProxy(GrTextureProxy*); |
49 | |
50 | /* |
51 | * Finds a proxy by unique key. |
52 | */ |
53 | sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&); |
54 | |
55 | /* |
56 | * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique |
57 | * key. |
58 | */ |
59 | sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, |
60 | UseAllocator = UseAllocator::kYes); |
61 | |
62 | /** |
63 | * A helper that uses findOrCreateProxyByUniqueKey() to find a proxy and if found creates a view |
64 | *a view for the found proxy using the passed in origin and color type. It is assumed that if |
65 | * the proxy is renderable then it was created by GrRenderTargetContext::MakeWithFallback and |
66 | * the fallback color type will be used to create the view. |
67 | */ |
68 | GrSurfaceProxyView findCachedProxyWithColorTypeFallback(const GrUniqueKey&, |
69 | GrSurfaceOrigin, |
70 | GrColorType, |
71 | int sampleCnt); |
72 | |
73 | /* |
74 | * Creates a new texture proxy for the bitmap, optionally with mip levels generated by the cpu. |
75 | * The bitmap is uploaded to the texture proxy assuming a kTopLeft_GrSurfaceOrigin. |
76 | */ |
77 | sk_sp<GrTextureProxy> createProxyFromBitmap(const SkBitmap&, |
78 | GrMipMapped, |
79 | SkBackingFit, |
80 | SkBudgeted); |
81 | |
82 | /* |
83 | * Create a GrSurfaceProxy without any data. |
84 | */ |
85 | sk_sp<GrTextureProxy> createProxy(const GrBackendFormat&, |
86 | SkISize dimensions, |
87 | GrRenderable, |
88 | int renderTargetSampleCnt, |
89 | GrMipMapped, |
90 | SkBackingFit, |
91 | SkBudgeted, |
92 | GrProtected, |
93 | GrInternalSurfaceFlags = GrInternalSurfaceFlags::kNone, |
94 | UseAllocator useAllocator = UseAllocator::kYes); |
95 | |
96 | /* |
97 | * Create a texture proxy from compressed texture data. |
98 | */ |
99 | sk_sp<GrTextureProxy> createCompressedTextureProxy(SkISize dimensions, |
100 | SkBudgeted, |
101 | GrMipMapped, |
102 | GrProtected, |
103 | SkImage::CompressionType, |
104 | sk_sp<SkData> data); |
105 | |
106 | // These match the definitions in SkImage & GrTexture.h, for whence they came |
107 | typedef void* ReleaseContext; |
108 | typedef void (*ReleaseProc)(ReleaseContext); |
109 | |
110 | /* |
111 | * Create a texture proxy that wraps a (non-renderable) backend texture. GrIOType must be |
112 | * kRead or kRW. |
113 | */ |
114 | sk_sp<GrTextureProxy> wrapBackendTexture(const GrBackendTexture&, |
115 | GrWrapOwnership, |
116 | GrWrapCacheable, |
117 | GrIOType, |
118 | ReleaseProc = nullptr, |
119 | ReleaseContext = nullptr); |
120 | |
121 | sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership, |
122 | GrWrapCacheable, ReleaseProc = nullptr, |
123 | ReleaseContext = nullptr); |
124 | |
125 | /* |
126 | * Create a texture proxy that wraps a backend texture and is both texture-able and renderable |
127 | */ |
128 | sk_sp<GrTextureProxy> wrapRenderableBackendTexture(const GrBackendTexture&, |
129 | int sampleCnt, |
130 | GrWrapOwnership, |
131 | GrWrapCacheable, |
132 | ReleaseProc = nullptr, |
133 | ReleaseContext = nullptr); |
134 | |
135 | /* |
136 | * Create a render target proxy that wraps a backend render target |
137 | */ |
138 | sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, |
139 | ReleaseProc = nullptr, |
140 | ReleaseContext = nullptr); |
141 | |
142 | /* |
143 | * Create a render target proxy that wraps a backend texture |
144 | */ |
145 | sk_sp<GrSurfaceProxy> wrapBackendTextureAsRenderTarget(const GrBackendTexture&, int sampleCnt); |
146 | |
147 | sk_sp<GrRenderTargetProxy> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, |
148 | const GrVkDrawableInfo&); |
149 | |
150 | using LazyInstantiationKeyMode = GrSurfaceProxy::LazyInstantiationKeyMode; |
151 | using LazyCallbackResult = GrSurfaceProxy::LazyCallbackResult; |
152 | using LazyInstantiateCallback = GrSurfaceProxy::LazyInstantiateCallback; |
153 | |
154 | struct TextureInfo { |
155 | GrMipMapped fMipMapped; |
156 | GrTextureType fTextureType; |
157 | }; |
158 | |
159 | /** |
160 | * Creates a texture proxy that will be instantiated by a user-supplied callback during flush. |
161 | * (Stencil is not supported by this method.) The width and height must either both be greater |
162 | * than 0 or both less than or equal to zero. A non-positive value is a signal that the width |
163 | * and height are currently unknown. |
164 | * |
165 | * When called, the callback must be able to cleanup any resources that it captured at creation. |
166 | * It also must support being passed in a null GrResourceProvider. When this happens, the |
167 | * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>. |
168 | */ |
169 | sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, |
170 | const GrBackendFormat&, |
171 | SkISize dimensions, |
172 | GrRenderable, |
173 | int renderTargetSampleCnt, |
174 | GrMipMapped, |
175 | GrMipMapsStatus, |
176 | GrInternalSurfaceFlags, |
177 | SkBackingFit, |
178 | SkBudgeted, |
179 | GrProtected, |
180 | UseAllocator); |
181 | |
182 | /** A null TextureInfo indicates a non-textureable render target. */ |
183 | sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&, |
184 | const GrBackendFormat&, |
185 | SkISize dimensions, |
186 | int renderTargetSampleCnt, |
187 | GrInternalSurfaceFlags, |
188 | const TextureInfo*, |
189 | GrMipMapsStatus, |
190 | SkBackingFit, |
191 | SkBudgeted, |
192 | GrProtected, |
193 | bool wrapsVkSecondaryCB, |
194 | UseAllocator useAllocator); |
195 | |
196 | /** |
197 | * Fully lazy proxies have unspecified width and height. Methods that rely on those values |
198 | * (e.g., width, height, getBoundsRect) should be avoided. |
199 | */ |
200 | static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&, |
201 | const GrBackendFormat&, |
202 | GrRenderable, |
203 | int renderTargetSampleCnt, |
204 | GrProtected, |
205 | const GrCaps&, |
206 | UseAllocator); |
207 | |
208 | enum class InvalidateGPUResource : bool { kNo = false, kYes = true }; |
209 | |
210 | /* |
211 | * This method ensures that, if a proxy w/ the supplied unique key exists, it is removed from |
212 | * the proxy provider's map and its unique key is removed. If 'invalidateSurface' is true, it |
213 | * will independently ensure that the unique key is removed from any GrGpuResources that may |
214 | * have it. |
215 | * |
216 | * If 'proxy' is provided (as an optimization to stop re-looking it up), its unique key must be |
217 | * valid and match the provided unique key. |
218 | * |
219 | * This method is called if either the proxy attached to the unique key is being deleted |
220 | * (in which case we don't want it cluttering up the hash table) or the client has indicated |
221 | * that it will never refer to the unique key again. |
222 | */ |
223 | void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource); |
224 | |
225 | // TODO: remove these entry points - it is a bit sloppy to be getting context info from here |
226 | uint32_t contextID() const; |
227 | const GrCaps* caps() const; |
228 | sk_sp<const GrCaps> refCaps() const; |
229 | |
230 | int numUniqueKeyProxies_TestOnly() const; |
231 | |
232 | // This is called on a DDL's proxyprovider when the DDL is finished. The uniquely keyed |
233 | // proxies need to keep their unique key but cannot hold on to the proxy provider unique |
234 | // pointer. |
235 | void orphanAllUniqueKeys(); |
236 | // This is only used by GrContext::releaseResourcesAndAbandonContext() |
237 | void removeAllUniqueKeys(); |
238 | |
239 | /** |
240 | * Does the proxy provider have access to a GrDirectContext? If so, proxies will be |
241 | * instantiated immediately. |
242 | */ |
243 | bool renderingDirectly() const; |
244 | |
245 | #if GR_TEST_UTILS |
246 | /** |
247 | * Create a texture proxy that is backed by an instantiated GrSurface. |
248 | */ |
249 | sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions, |
250 | const GrBackendFormat& format, |
251 | GrRenderable renderable, |
252 | int renderTargetSampleCnt, |
253 | SkBackingFit fit, |
254 | SkBudgeted budgeted, |
255 | GrProtected isProtected); |
256 | |
257 | /** Version of above that picks the default format for the color type. */ |
258 | sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions, |
259 | GrColorType colorType, |
260 | GrRenderable renderable, |
261 | int renderTargetSampleCnt, |
262 | SkBackingFit fit, |
263 | SkBudgeted budgeted, |
264 | GrProtected isProtected); |
265 | |
266 | sk_sp<GrTextureProxy> testingOnly_createWrapped(sk_sp<GrTexture>); |
267 | #endif |
268 | |
269 | private: |
270 | friend class GrAHardwareBufferImageGenerator; // for createWrapped |
271 | friend class GrResourceProvider; // for createWrapped |
272 | |
273 | // processInvalidUniqueKey() with control over removing hash table entries, |
274 | // which is not safe while iterating with foreach(). |
275 | enum class RemoveTableEntry { kNo, kYes }; |
276 | void processInvalidUniqueKeyImpl(const GrUniqueKey&, GrTextureProxy*, |
277 | InvalidateGPUResource, RemoveTableEntry); |
278 | |
279 | bool isAbandoned() const; |
280 | |
281 | /* |
282 | * Create an un-mipmapped texture proxy for the bitmap. |
283 | */ |
284 | sk_sp<GrTextureProxy> createNonMippedProxyFromBitmap(const SkBitmap&, SkBackingFit, SkBudgeted); |
285 | /* |
286 | * Create an mipmapped texture proxy for the bitmap. |
287 | */ |
288 | sk_sp<GrTextureProxy> createMippedProxyFromBitmap(const SkBitmap&, |
289 | SkBudgeted); |
290 | |
291 | sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, UseAllocator useAllocator); |
292 | |
293 | struct UniquelyKeyedProxyHashTraits { |
294 | static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); } |
295 | |
296 | static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); } |
297 | }; |
298 | typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash; |
299 | |
300 | // This holds the texture proxies that have unique keys. The resourceCache does not get a ref |
301 | // on these proxies but they must send a message to the resourceCache when they are deleted. |
302 | UniquelyKeyedProxyHash fUniquelyKeyedProxies; |
303 | |
304 | GrImageContext* fImageContext; |
305 | }; |
306 | |
307 | #endif |
308 | |