aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrProxyProvider.h
blob: 89f9518e469ffb42595e74c3a40f33de7f4b49d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrProxyProvider_DEFINED
#define GrProxyProvider_DEFINED

#include "GrCaps.h"
#include "GrResourceKey.h"
#include "GrTextureProxy.h"
#include "GrTypes.h"
#include "SkRefCnt.h"
#include "SkTDynamicHash.h"

class GrResourceProvider;
class GrSingleOwner;
class GrBackendRenderTarget;
class SkBitmap;
class SkImage;

/*
 * A factory for creating GrSurfaceProxy-derived objects.
 */
class GrProxyProvider {
public:
    GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp<const GrCaps>, GrSingleOwner*);
    GrProxyProvider(uint32_t contextUniqueID, sk_sp<const GrCaps>, GrSingleOwner*);

    ~GrProxyProvider();

    /*
     * Assigns a unique key to a proxy. The proxy will be findable via this key using
     * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
     */
    bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);

    /*
     * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
     * have a valid unique key.
     */
    void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);

    /*
     * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
     * also remove the unique key from the target GrSurface.
     */
    void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);

    /*
     * Finds a proxy by unique key.
     */
    sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);

    /*
     * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
     * key.
     */
    sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);

    /*
     * Create a texture proxy that is backed by an instantiated GrSurface. This is almost entirely
     * used by Skia's testing code.
     * DDL TODO: remove the remaining Skia-internal use of this method and make it truly
     * testing-only.
     */
    sk_sp<GrTextureProxy> createInstantiatedProxy(const GrSurfaceDesc&, GrSurfaceOrigin,
                                                  SkBackingFit, SkBudgeted,
                                                  GrSurfaceDescFlags = kNone_GrSurfaceFlags);

    /*
     * Create an un-mipmapped texture proxy with data.
     * DDL TODO: need to refine ownership semantics of 'srcData' if we're in completely
     * deferred mode
     */
    sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted, const void* srcData,
                                             size_t rowBytes);

    /*
     * Create an un-mipmapped texture proxy with data. The SkImage must be a raster backend image.
     * Since the SkImage is ref counted, we simply take a ref on it to keep the data alive until we
     * actually upload the data to the gpu.
     */
    sk_sp<GrTextureProxy> createTextureProxy(sk_sp<SkImage> srcImage,
                                             GrSurfaceDescFlags descFlags,
                                             int sampleCnt,
                                             SkBudgeted budgeted,
                                             SkBackingFit fit);

    /*
     * Create a mipmapped texture proxy without any data.
     *
     * Like the call above but there are no texels to upload. A texture proxy is returned that
     * simply has space allocated for the mips. We will allocated the full amount of mip levels
     * based on the width and height in the GrSurfaceDesc.
     */
    sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, GrSurfaceOrigin, SkBudgeted);

    /*
     * Creates a new mipmapped texture proxy for the bitmap with mip levels generated by the cpu.
     */
    sk_sp<GrTextureProxy> createMipMapProxyFromBitmap(const SkBitmap& bitmap);

    /*
     * Create a GrSurfaceProxy without any data.
     */
    sk_sp<GrTextureProxy> createProxy(const GrSurfaceDesc&, GrSurfaceOrigin, GrMipMapped,
                                      SkBackingFit, SkBudgeted, GrInternalSurfaceFlags);

    sk_sp<GrTextureProxy> createProxy(
                            const GrSurfaceDesc& desc, GrSurfaceOrigin origin,
                            SkBackingFit fit, SkBudgeted budgeted,
                            GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone) {
        return this->createProxy(desc, origin, GrMipMapped::kNo, fit, budgeted, surfaceFlags);
    }

    // These match the definitions in SkImage & GrTexture.h, for whence they came
    typedef void* ReleaseContext;
    typedef void (*ReleaseProc)(ReleaseContext);

    /*
     * Create a texture proxy that wraps a (non-renderable) backend texture.
     */
    sk_sp<GrTextureProxy> wrapBackendTexture(const GrBackendTexture&, GrSurfaceOrigin,
                                             GrWrapOwnership = kBorrow_GrWrapOwnership,
                                             ReleaseProc = nullptr, ReleaseContext = nullptr);

    /*
     * Create a texture proxy that wraps a backend texture and is both texture-able and renderable
     */
    sk_sp<GrTextureProxy> wrapRenderableBackendTexture(const GrBackendTexture&,
                                                       GrSurfaceOrigin,
                                                       int sampleCnt,
                                                       GrWrapOwnership = kBorrow_GrWrapOwnership);

    /*
     * Create a render target proxy that wraps a backend rendertarget
     */
    sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&, GrSurfaceOrigin);

    /*
     * Create a render target proxy that wraps a backend texture
     */
    sk_sp<GrSurfaceProxy> wrapBackendTextureAsRenderTarget(const GrBackendTexture& backendTex,
                                                           GrSurfaceOrigin origin,
                                                           int sampleCnt);

    using LazyInstantiateCallback = std::function<sk_sp<GrSurface>(GrResourceProvider*)>;
    enum class Textureable : bool {
        kNo = false,
        kYes = true
    };

    enum class Renderable : bool {
        kNo = false,
        kYes = true
    };

    using LazyInstantiationType = GrSurfaceProxy::LazyInstantiationType;
    /**
     * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
     * (Stencil is not supported by this method.) The width and height must either both be greater
     * than 0 or both less than or equal to zero. A non-positive value is a signal that the width
     * and height are currently unknown.
     *
     * When called, the callback must be able to cleanup any resources that it captured at creation.
     * It also must support being passed in a null GrResourceProvider. When this happens, the
     * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
     */
    sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
                                          GrSurfaceOrigin, GrMipMapped, GrInternalSurfaceFlags,
                                          SkBackingFit, SkBudgeted, LazyInstantiationType);

    sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
                                          GrSurfaceOrigin, GrMipMapped, GrInternalSurfaceFlags,
                                          SkBackingFit, SkBudgeted);

    sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
                                          GrSurfaceOrigin, GrMipMapped, SkBackingFit, SkBudgeted);
    sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
                                                           const GrSurfaceDesc&,
                                                           GrSurfaceOrigin origin,
                                                           GrInternalSurfaceFlags, Textureable,
                                                           GrMipMapped, SkBackingFit, SkBudgeted);

    /**
     * Fully lazy proxies have unspecified width and height. Methods that rely on those values
     * (e.g., width, height, getBoundsRect) should be avoided.
     */
    static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&, Renderable,
                                                    GrSurfaceOrigin, GrPixelConfig, const GrCaps&);

    // 'proxy' is about to be used as a texture src or drawn to. This query can be used to
    // determine if it is going to need a texture domain or a full clear.
    static bool IsFunctionallyExact(GrSurfaceProxy* proxy);

    /**
     * Either the proxy attached to the unique key is being deleted (in which case we
     * don't want it cluttering up the hash table) or the client has indicated that
     * it will never refer to the unique key again. In either case, remove the key
     * from the hash table.
     * Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
     */
    void processInvalidProxyUniqueKey(const GrUniqueKey&);

    /**
     * Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
     * GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
     * also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
     */
    void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);

    uint32_t contextUniqueID() const { return fContextUniqueID; }
    const GrCaps* caps() const { return fCaps.get(); }
    sk_sp<const GrCaps> refCaps() const { return fCaps; }

    void abandon() {
        fResourceCache = nullptr;
        fResourceProvider = nullptr;
        fAbandoned = true;
    }

    bool isAbandoned() const {
#ifdef SK_DEBUG
        if (fAbandoned) {
            SkASSERT(!fResourceCache && !fResourceProvider);
        }
#endif
        return fAbandoned;
    }

    int numUniqueKeyProxies_TestOnly() const;

    void removeAllUniqueKeys();

    /**
     * Are we currently recording a DDL?
     */
    bool recordingDDL() const { return !SkToBool(fResourceProvider); }

private:
    friend class GrAHardwareBufferImageGenerator; // for createWrapped

    sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);

    struct UniquelyKeyedProxyHashTraits {
        static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }

        static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
    };
    typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;

    // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
    // on these proxies but they must send a message to the resourceCache when they are deleted.
    UniquelyKeyedProxyHash fUniquelyKeyedProxies;

    GrResourceProvider*    fResourceProvider;
    GrResourceCache*       fResourceCache;
    bool                   fAbandoned;
    sk_sp<const GrCaps>    fCaps;
    // If this provider is owned by a DDLContext then this is the DirectContext's ID.
    uint32_t               fContextUniqueID;

    // In debug builds we guard against improper thread handling
    SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
};

#endif