• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkRefCnt.h"
15 #include "SkTDynamicHash.h"
16 
17 class GrCaps;
18 class GrResourceProvider;
19 class GrSingleOwner;
20 class GrBackendRenderTarget;
21 class SkImage;
22 
23 /*
24  * A factory for creating GrSurfaceProxy-derived objects.
25  */
26 class GrProxyProvider {
27 public:
28     GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp<const GrCaps>, GrSingleOwner*);
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(const GrUniqueKey&, GrTextureProxy*);
49 
50     /*
51      * Finds a proxy by unique key.
52      */
53     sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
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&, GrSurfaceOrigin);
60 
61     /*
62      * Create a texture proxy that is backed by an instantiated GrSurface. This is almost entirely
63      * used by Skia's testing code.
64      * DDL TODO: remove the remaining Skia-internal use of this method and make it truly
65      * testing-only.
66      */
67     sk_sp<GrTextureProxy> createInstantiatedProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
68                                                   uint32_t flags = 0);
69 
70     /*
71      * Create an un-mipmapped texture proxy with data.
72      * DDL TODO: need to refine ownership semantics of 'srcData' if we're in completely
73      * deferred mode
74      */
75     sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted,
76                                              const void* srcData, size_t rowBytes);
77 
78     /*
79      * Create an un-mipmapped texture proxy with data. The SkImage must be a raster backend image.
80      * Since the SkImage is ref counted, we simply take a ref on it to keep the data alive until we
81      * actually upload the data to the gpu.
82      */
83     sk_sp<GrTextureProxy> createTextureProxy(sk_sp<SkImage> srcImage,
84                                              GrSurfaceFlags flags,
85                                              GrSurfaceOrigin origin,
86                                              int sampleCnt,
87                                              SkBudgeted budgeted);
88 
89     /*
90      * Create a mipmapped texture proxy with data.
91      *
92      * @param desc          Description of the texture properties.
93      * @param budgeted      Does the texture count against the resource cache budget?
94      * @param texels        A contiguous array of mipmap levels
95      * @param mipLevelCount The amount of elements in the texels array
96      */
97     sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted,
98                                             const GrMipLevel texels[], int mipLevelCount,
99                                             SkDestinationSurfaceColorMode mipColorMode =
100                                                             SkDestinationSurfaceColorMode::kLegacy);
101 
102     /*
103      * Create a mipmapped texture proxy without any data.
104      *
105      * Like the call above but there are no texels to upload. A texture proxy is returned that
106      * simply has space allocated for the mips. We will allocated the full amount of mip levels
107      * based on the width and height in the GrSurfaceDesc.
108      */
109     sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted);
110 
111     /*
112      * Create a GrSurfaceProxy without any data.
113      */
114     sk_sp<GrTextureProxy> createProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
115                                       uint32_t flags = 0);
116 
117     // These match the definitions in SkImage & GrTexture.h, for whence they came
118     typedef void* ReleaseContext;
119     typedef void (*ReleaseProc)(ReleaseContext);
120 
121     /*
122      * Create a texture proxy that wraps a (non-renderable) backend texture.
123      */
124     sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&, GrSurfaceOrigin,
125                                                     GrWrapOwnership = kBorrow_GrWrapOwnership,
126                                                     ReleaseProc = nullptr,
127                                                     ReleaseContext = nullptr);
128 
129     /*
130      * Create a texture proxy that wraps a backend texture and is both texture-able and renderable
131      */
132     sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&,
133                                                     GrSurfaceOrigin,
134                                                     int sampleCnt);
135 
136     /*
137      * Create a render target proxy that wraps a backend rendertarget
138      */
139     sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendRenderTarget&,
140                                                          GrSurfaceOrigin);
141 
142     /*
143      * Create a render target proxy that wraps a backend texture?
144      */
145     sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendTexture& tex,
146                                                          GrSurfaceOrigin origin,
147                                                          int sampleCnt);
148 
149     using LazyInstantiateCallback = std::function<sk_sp<GrTexture>(GrResourceProvider*,
150                                                                    GrSurfaceOrigin* outOrigin)>;
151 
152     enum class Renderable : bool {
153         kNo = false,
154         kYes = true
155     };
156 
157     /**
158      * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
159      * (Stencil is not supported by this method.) The width and height must either both be greater
160      * than 0 or both less than or equal to zero. A non-positive value is a signal that the width
161      * and height are currently unknown.
162      *
163      * When called, the callback must be able to cleanup any resources that it captured at creation.
164      * It also must support being passed in a null GrResourceProvider. When this happens, the
165      * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
166      */
167     sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
168                                           GrMipMapped, SkBackingFit, SkBudgeted);
169 
170     sk_sp<GrTextureProxy> createFullyLazyProxy(LazyInstantiateCallback&&,
171                                                Renderable, GrPixelConfig);
172 
173     // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
174     // determine if it is going to need a texture domain or a full clear.
175     static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
176 
177     /**
178      * Either the proxy attached to the unique key is being deleted (in which case we
179      * don't want it cluttering up the hash table) or the client has indicated that
180      * it will never refer to the unique key again. In either case, remove the key
181      * from the hash table.
182      * Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
183      */
184     void processInvalidProxyUniqueKey(const GrUniqueKey&);
185 
186     /**
187      * Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
188      * GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
189      * also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
190      */
191     void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);
192 
caps()193     const GrCaps* caps() const { return fCaps.get(); }
194 
abandon()195     void abandon() {
196         fResourceCache = nullptr;
197         fResourceProvider = nullptr;
198         fAbandoned = true;
199     }
200 
isAbandoned()201     bool isAbandoned() const {
202 #ifdef SK_DEBUG
203         if (fAbandoned) {
204             SkASSERT(!fResourceCache && !fResourceProvider);
205         }
206 #endif
207         return fAbandoned;
208     }
209 
210     int numUniqueKeyProxies_TestOnly() const;
211 
212     void removeAllUniqueKeys();
213 
214 private:
215     friend class GrAHardwareBufferImageGenerator; // for createWrapped
216 
217     sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);
218 
219     struct UniquelyKeyedProxyHashTraits {
GetKeyUniquelyKeyedProxyHashTraits220         static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
221 
HashUniquelyKeyedProxyHashTraits222         static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
223     };
224     typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
225 
226     // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
227     // on these proxies but they must send a message to the resourceCache when they are deleted.
228     UniquelyKeyedProxyHash fUniquelyKeyedProxies;
229 
230     GrResourceProvider*    fResourceProvider;
231     GrResourceCache*       fResourceCache;
232     bool                   fAbandoned;
233     sk_sp<const GrCaps>    fCaps;
234 
235     // In debug builds we guard against improper thread handling
236     SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
237 };
238 
239 #endif
240