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 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
269private:
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