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
16class GrImageContext;
17class GrBackendRenderTarget;
18class SkBitmap;
19class SkImage;
20
21/*
22 * A factory for creating GrSurfaceProxy-derived objects.
23 */
24class GrProxyProvider {
25public:
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 sk_sp<GrRefCntedCallback> = nullptr);
119
120 sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&,
121 GrWrapOwnership,
122 GrWrapCacheable,
123 sk_sp<GrRefCntedCallback> releaseHelper);
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 sk_sp<GrRefCntedCallback> releaseHelper);
133
134 /*
135 * Create a render target proxy that wraps a backend render target
136 */
137 sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&,
138 sk_sp<GrRefCntedCallback> releaseHelper);
139
140 /*
141 * Create a render target proxy that wraps a backend texture
142 */
143 sk_sp<GrSurfaceProxy> wrapBackendTextureAsRenderTarget(const GrBackendTexture&, int sampleCnt);
144
145 sk_sp<GrRenderTargetProxy> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&,
146 const GrVkDrawableInfo&);
147
148 using LazyInstantiationKeyMode = GrSurfaceProxy::LazyInstantiationKeyMode;
149 using LazySurfaceDesc = GrSurfaceProxy::LazySurfaceDesc;
150 using LazyCallbackResult = GrSurfaceProxy::LazyCallbackResult;
151 using LazyInstantiateCallback = GrSurfaceProxy::LazyInstantiateCallback;
152
153 struct TextureInfo {
154 GrMipmapped fMipmapped;
155 GrTextureType fTextureType;
156 };
157
158 /**
159 * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
160 * (Stencil is not supported by this method.) The width and height must either both be greater
161 * than 0 or both less than or equal to zero. A non-positive value is a signal that the width
162 * and height are currently unknown.
163 *
164 * When called, the callback must be able to cleanup any resources that it captured at creation.
165 * It also must support being passed in a null GrResourceProvider. When this happens, the
166 * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
167 */
168 sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&,
169 const GrBackendFormat&,
170 SkISize dimensions,
171 GrRenderable,
172 int renderTargetSampleCnt,
173 GrMipmapped,
174 GrMipmapStatus,
175 GrInternalSurfaceFlags,
176 SkBackingFit,
177 SkBudgeted,
178 GrProtected,
179 UseAllocator);
180
181 /** A null TextureInfo indicates a non-textureable render target. */
182 sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
183 const GrBackendFormat&,
184 SkISize dimensions,
185 int renderTargetSampleCnt,
186 GrInternalSurfaceFlags,
187 const TextureInfo*,
188 GrMipmapStatus,
189 SkBackingFit,
190 SkBudgeted,
191 GrProtected,
192 bool wrapsVkSecondaryCB,
193 UseAllocator useAllocator);
194
195 /**
196 * Fully lazy proxies have unspecified width and height. Methods that rely on those values
197 * (e.g., width, height, getBoundsRect) should be avoided.
198 */
199 static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&,
200 const GrBackendFormat&,
201 GrRenderable,
202 int renderTargetSampleCnt,
203 GrProtected,
204 const GrCaps&,
205 UseAllocator);
206
207 enum class InvalidateGPUResource : bool { kNo = false, kYes = true };
208
209 /*
210 * This method ensures that, if a proxy w/ the supplied unique key exists, it is removed from
211 * the proxy provider's map and its unique key is removed. If 'invalidateSurface' is true, it
212 * will independently ensure that the unique key is removed from any GrGpuResources that may
213 * have it.
214 *
215 * If 'proxy' is provided (as an optimization to stop re-looking it up), its unique key must be
216 * valid and match the provided unique key.
217 *
218 * This method is called if either the proxy attached to the unique key is being deleted
219 * (in which case we don't want it cluttering up the hash table) or the client has indicated
220 * that it will never refer to the unique key again.
221 */
222 void processInvalidUniqueKey(const GrUniqueKey&, GrTextureProxy*, InvalidateGPUResource);
223
224 GrDDLProvider isDDLProvider() const;
225
226 // TODO: remove these entry points - it is a bit sloppy to be getting context info from here
227 uint32_t contextID() const;
228 const GrCaps* caps() const;
229 sk_sp<const GrCaps> refCaps() const;
230
231 int numUniqueKeyProxies_TestOnly() const;
232
233 // This is called on a DDL's proxyprovider when the DDL is finished. The uniquely keyed
234 // proxies need to keep their unique key but cannot hold on to the proxy provider unique
235 // pointer.
236 void orphanAllUniqueKeys();
237 // This is only used by GrContext::releaseResourcesAndAbandonContext()
238 void removeAllUniqueKeys();
239
240 /**
241 * Does the proxy provider have access to a GrDirectContext? If so, proxies will be
242 * instantiated immediately.
243 */
244 bool renderingDirectly() const;
245
246#if GR_TEST_UTILS
247 /**
248 * Create a texture proxy that is backed by an instantiated GrSurface.
249 */
250 sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions,
251 const GrBackendFormat& format,
252 GrRenderable renderable,
253 int renderTargetSampleCnt,
254 SkBackingFit fit,
255 SkBudgeted budgeted,
256 GrProtected isProtected);
257
258 /** Version of above that picks the default format for the color type. */
259 sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions,
260 GrColorType colorType,
261 GrRenderable renderable,
262 int renderTargetSampleCnt,
263 SkBackingFit fit,
264 SkBudgeted budgeted,
265 GrProtected isProtected);
266
267 sk_sp<GrTextureProxy> testingOnly_createWrapped(sk_sp<GrTexture>);
268#endif
269
270private:
271 friend class GrAHardwareBufferImageGenerator; // for createWrapped
272 friend class GrResourceProvider; // for createWrapped
273
274 // processInvalidUniqueKey() with control over removing hash table entries,
275 // which is not safe while iterating with foreach().
276 enum class RemoveTableEntry { kNo, kYes };
277 void processInvalidUniqueKeyImpl(const GrUniqueKey&, GrTextureProxy*,
278 InvalidateGPUResource, RemoveTableEntry);
279
280 bool isAbandoned() const;
281
282 /*
283 * Create an un-mipmapped texture proxy for the bitmap.
284 */
285 sk_sp<GrTextureProxy> createNonMippedProxyFromBitmap(const SkBitmap&, SkBackingFit, SkBudgeted);
286 /*
287 * Create an mipmapped texture proxy for the bitmap.
288 */
289 sk_sp<GrTextureProxy> createMippedProxyFromBitmap(const SkBitmap&,
290 SkBudgeted);
291
292 sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, UseAllocator useAllocator);
293
294 struct UniquelyKeyedProxyHashTraits {
295 static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
296
297 static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
298 };
299 typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
300
301 // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
302 // on these proxies but they must send a message to the resourceCache when they are deleted.
303 UniquelyKeyedProxyHash fUniquelyKeyedProxies;
304
305 GrImageContext* fImageContext;
306};
307
308#endif
309