aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrProxyProvider.h
blob: f0b1bbd1ed465b6032536568e5856691b13536de (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
/*
 * 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 "GrResourceKey.h"
#include "GrTextureProxy.h"
#include "GrTypes.h"
#include "SkRefCnt.h"
#include "SkTDynamicHash.h"

class GrCaps;
class GrResourceProvider;
class GrSingleOwner;
class GrBackendRenderTarget;

/*
 * A factory for creating GrSurfaceProxy-derived objects.
 */
class GrProxyProvider {
public:
    GrProxyProvider(GrResourceProvider*, GrResourceCache*, 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&, SkBackingFit, SkBudgeted,
                                                  uint32_t flags = 0);

    /*
     * 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 a mipmapped texture proxy with data.
     *
     * @param desc          Description of the texture properties.
     * @param budgeted      Does the texture count against the resource cache budget?
     * @param texels        A contiguous array of mipmap levels
     * @param mipLevelCount The amount of elements in the texels array
     */
    sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted,
                                            const GrMipLevel texels[], int mipLevelCount,
                                            SkDestinationSurfaceColorMode mipColorMode =
                                                            SkDestinationSurfaceColorMode::kLegacy);

    /*
     * 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&, SkBudgeted);

    /*
     * Create a GrSurfaceProxy without any data.
     */
    sk_sp<GrTextureProxy> createProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
                                      uint32_t flags = 0);

    // 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> createWrappedTextureProxy(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> createWrappedTextureProxy(const GrBackendTexture&,
                                                    GrSurfaceOrigin,
                                                    int sampleCnt);

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

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

    using LazyInstantiateCallback = std::function<sk_sp<GrTexture>(GrResourceProvider*,
                                                                   GrSurfaceOrigin* outOrigin)>;

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

    /**
     * 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&,
                                          GrMipMapped, SkBackingFit, SkBudgeted);

    sk_sp<GrTextureProxy> createFullyLazyProxy(LazyInstantiateCallback&&,
                                               Renderable, GrPixelConfig);

    // '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);

    const GrCaps* caps() const { return fCaps.get(); }

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

    bool isAbandoned() const {
        SkASSERT(SkToBool(fResourceCache) == SkToBool(fResourceProvider));
        return !SkToBool(fResourceCache);
    }

    int numUniqueKeyProxies_TestOnly() const;

    void removeAllUniqueKeys();

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;
    sk_sp<const GrCaps>    fCaps;

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

#endif