Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / gpu / ganesh / GrGpuResource.h
1 /*
2  * Copyright 2014 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 GrGpuResource_DEFINED
9 #define GrGpuResource_DEFINED
10
11 #include "include/private/SkNoncopyable.h"
12 #include "include/private/gpu/ganesh/GrTypesPriv.h"
13 #include "src/gpu/ResourceKey.h"
14
15 class GrGpu;
16 class GrResourceCache;
17 class SkTraceMemoryDump;
18
19 /**
20  * Base class for GrGpuResource. Provides the hooks for resources to interact with the cache.
21  * Separated out as a base class to isolate the ref-cnting behavior and provide friendship without
22  * exposing all of GrGpuResource.
23  *
24  * PRIOR to the last ref being removed DERIVED::notifyARefCntWillBeZero() will be called
25  * (static poly morphism using CRTP). It is legal for additional ref's to be added
26  * during this time. AFTER the ref count reaches zero DERIVED::notifyARefCntIsZero() will be
27  * called.
28  */
29 template <typename DERIVED> class GrIORef : public SkNoncopyable {
30 public:
31     bool unique() const { return fRefCnt == 1; }
32
33     void ref() const {
34         // Only the cache should be able to add the first ref to a resource.
35         SkASSERT(this->getRefCnt() > 0);
36         // No barrier required.
37         (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
38     }
39
40     // This enum is used to notify the GrResourceCache which type of ref just dropped to zero.
41     enum class LastRemovedRef {
42         kMainRef,            // This refers to fRefCnt
43         kCommandBufferUsage, // This refers to fCommandBufferUsageCnt
44     };
45
46     void unref() const {
47         SkASSERT(this->getRefCnt() > 0);
48         if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
49             this->notifyWillBeZero(LastRemovedRef::kMainRef);
50         }
51     }
52
53     void addCommandBufferUsage() const {
54         // No barrier required.
55         (void)fCommandBufferUsageCnt.fetch_add(+1, std::memory_order_relaxed);
56     }
57
58     void removeCommandBufferUsage() const {
59         SkASSERT(!this->hasNoCommandBufferUsages());
60         if (1 == fCommandBufferUsageCnt.fetch_add(-1, std::memory_order_acq_rel)) {
61             this->notifyWillBeZero(LastRemovedRef::kCommandBufferUsage);
62         }
63     }
64
65 #if GR_TEST_UTILS
66     int32_t testingOnly_getRefCnt() const { return this->getRefCnt(); }
67 #endif
68
69 protected:
70     GrIORef() : fRefCnt(1), fCommandBufferUsageCnt(0) {}
71
72     bool internalHasRef() const { return SkToBool(this->getRefCnt()); }
73     bool internalHasNoCommandBufferUsages() const {
74         return SkToBool(this->hasNoCommandBufferUsages());
75     }
76
77     // Privileged method that allows going from ref count = 0 to ref count = 1.
78     void addInitialRef() const {
79         SkASSERT(fRefCnt >= 0);
80         // No barrier required.
81         (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
82     }
83
84 private:
85     void notifyWillBeZero(LastRemovedRef removedRef) const {
86         static_cast<const DERIVED*>(this)->notifyARefCntIsZero(removedRef);
87     }
88
89     int32_t getRefCnt() const { return fRefCnt.load(std::memory_order_relaxed); }
90
91     bool hasNoCommandBufferUsages() const {
92         if (0 == fCommandBufferUsageCnt.load(std::memory_order_acquire)) {
93             // The acquire barrier is only really needed if we return true.  It
94             // prevents code conditioned on the result of hasNoCommandBufferUsages() from running
95             // until previous owners are all totally done calling removeCommandBufferUsage().
96             return true;
97         }
98         return false;
99     }
100
101     mutable std::atomic<int32_t> fRefCnt;
102     mutable std::atomic<int32_t> fCommandBufferUsageCnt;
103
104     using INHERITED = SkNoncopyable;
105 };
106
107 /**
108  * Base class for objects that can be kept in the GrResourceCache.
109  */
110 class GrGpuResource : public GrIORef<GrGpuResource> {
111 public:
112     /**
113      * Tests whether a object has been abandoned or released. All objects will
114      * be in this state after their creating GrContext is destroyed or has
115      * contextLost called. It's up to the client to test wasDestroyed() before
116      * attempting to use an object if it holds refs on objects across
117      * ~GrContext, freeResources with the force flag, or contextLost.
118      *
119      * @return true if the object has been released or abandoned,
120      *         false otherwise.
121      */
122     bool wasDestroyed() const { return nullptr == fGpu; }
123
124     /**
125      * Retrieves the context that owns the object. Note that it is possible for
126      * this to return NULL. When objects have been release()ed or abandon()ed
127      * they no longer have an owning context. Destroying a GrDirectContext
128      * automatically releases all its resources.
129      */
130     const GrDirectContext* getContext() const;
131     GrDirectContext* getContext();
132
133     /**
134      * Retrieves the amount of GPU memory used by this resource in bytes. It is
135      * approximate since we aren't aware of additional padding or copies made
136      * by the driver.
137      *
138      * @return the amount of GPU memory used in bytes
139      */
140     size_t gpuMemorySize() const {
141         if (kInvalidGpuMemorySize == fGpuMemorySize) {
142             fGpuMemorySize = this->onGpuMemorySize();
143             SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);
144         }
145         return fGpuMemorySize;
146     }
147
148     class UniqueID {
149     public:
150         UniqueID() = default;
151
152         explicit UniqueID(uint32_t id) : fID(id) {}
153
154         uint32_t asUInt() const { return fID; }
155
156         bool operator==(const UniqueID& other) const { return fID == other.fID; }
157         bool operator!=(const UniqueID& other) const { return !(*this == other); }
158
159         void makeInvalid() { fID = SK_InvalidUniqueID; }
160         bool isInvalid() const { return  fID == SK_InvalidUniqueID; }
161
162     protected:
163         uint32_t fID = SK_InvalidUniqueID;
164     };
165
166     /**
167      * Gets an id that is unique for this GrGpuResource object. It is static in that it does
168      * not change when the content of the GrGpuResource object changes. This will never return
169      * 0.
170      */
171     UniqueID uniqueID() const { return fUniqueID; }
172
173     /** Returns the current unique key for the resource. It will be invalid if the resource has no
174         associated unique key. */
175     const skgpu::UniqueKey& getUniqueKey() const { return fUniqueKey; }
176
177     std::string_view getLabel() const { return fLabel; }
178
179     void setLabel(std::string_view label) { fLabel = label; }
180
181     /**
182      * Internal-only helper class used for manipulations of the resource by the cache.
183      */
184     class CacheAccess;
185     inline CacheAccess cacheAccess();
186     inline const CacheAccess cacheAccess() const;  // NOLINT(readability-const-return-type)
187
188     /**
189      * Internal-only helper class used for manipulations of the resource by GrSurfaceProxy.
190      */
191     class ProxyAccess;
192     inline ProxyAccess proxyAccess();
193
194     /**
195      * Internal-only helper class used for manipulations of the resource by internal code.
196      */
197     class ResourcePriv;
198     inline ResourcePriv resourcePriv();
199     inline const ResourcePriv resourcePriv() const;  // NOLINT(readability-const-return-type)
200
201     /**
202      * Dumps memory usage information for this GrGpuResource to traceMemoryDump.
203      * Typically, subclasses should not need to override this, and should only
204      * need to override setMemoryBacking.
205      **/
206     virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
207
208     /**
209      * Describes the type of gpu resource that is represented by the implementing
210      * class (e.g. texture, buffer object, stencil).  This data is used for diagnostic
211      * purposes by dumpMemoryStatistics().
212      *
213      * The value returned is expected to be long lived and will not be copied by the caller.
214      */
215     virtual const char* getResourceType() const = 0;
216
217     static uint32_t CreateUniqueID();
218
219 protected:
220     // This must be called by every non-wrapped GrGpuObject. It should be called once the object is
221     // fully initialized (i.e. only from the constructors of the final class).
222     void registerWithCache(SkBudgeted);
223
224     // This must be called by every GrGpuObject that references any wrapped backend objects. It
225     // should be called once the object is fully initialized (i.e. only from the constructors of the
226     // final class).
227     void registerWithCacheWrapped(GrWrapCacheable);
228
229     GrGpuResource(GrGpu*, std::string_view label);
230     virtual ~GrGpuResource();
231
232     GrGpu* getGpu() const { return fGpu; }
233
234     /** Overridden to free GPU resources in the backend API. */
235     virtual void onRelease() { }
236     /** Overridden to abandon any internal handles, ptrs, etc to backend API resources.
237         This may be called when the underlying 3D context is no longer valid and so no
238         backend API calls should be made. */
239     virtual void onAbandon() { }
240
241     /**
242      * Allows subclasses to add additional backing information to the SkTraceMemoryDump.
243      **/
244     virtual void setMemoryBacking(SkTraceMemoryDump*, const SkString&) const {}
245
246     /**
247      * Returns a string that uniquely identifies this resource.
248      */
249     SkString getResourceName() const;
250
251     /**
252      * A helper for subclasses that override dumpMemoryStatistics(). This method using a format
253      * consistent with the default implementation of dumpMemoryStatistics() but allows the caller
254      * to customize various inputs.
255      */
256     void dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump, const SkString& resourceName,
257                                   const char* type, size_t size) const;
258
259
260 private:
261     bool isPurgeable() const;
262     bool hasRef() const;
263     bool hasNoCommandBufferUsages() const;
264
265     /**
266      * Called by the registerWithCache if the resource is available to be used as scratch.
267      * Resource subclasses should override this if the instances should be recycled as scratch
268      * resources and populate the scratchKey with the key.
269      * By default resources are not recycled as scratch.
270      **/
271     virtual void computeScratchKey(skgpu::ScratchKey*) const {}
272
273     /**
274      * Removes references to objects in the underlying 3D API without freeing them.
275      * Called by CacheAccess.
276      */
277     void abandon();
278
279     /**
280      * Frees the object in the underlying 3D API. Called by CacheAccess.
281      */
282     void release();
283
284     virtual size_t onGpuMemorySize() const = 0;
285
286     // See comments in CacheAccess and ResourcePriv.
287     void setUniqueKey(const skgpu::UniqueKey&);
288     void removeUniqueKey();
289     void notifyARefCntIsZero(LastRemovedRef removedRef) const;
290     void removeScratchKey();
291     void makeBudgeted();
292     void makeUnbudgeted();
293
294 #ifdef SK_DEBUG
295     friend class GrGpu;  // for assert in GrGpu to access getGpu
296 #endif
297
298     // An index into a heap when this resource is purgeable or an array when not. This is maintained
299     // by the cache.
300     int fCacheArrayIndex;
301     // This value reflects how recently this resource was accessed in the cache. This is maintained
302     // by the cache.
303     uint32_t fTimestamp;
304     GrStdSteadyClock::time_point fTimeWhenBecamePurgeable;
305
306     static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
307     skgpu::ScratchKey fScratchKey;
308     skgpu::UniqueKey fUniqueKey;
309
310     // This is not ref'ed but abandon() or release() will be called before the GrGpu object
311     // is destroyed. Those calls will set this to NULL.
312     GrGpu* fGpu;
313     mutable size_t fGpuMemorySize = kInvalidGpuMemorySize;
314
315     GrBudgetedType fBudgetedType = GrBudgetedType::kUnbudgetedUncacheable;
316     bool fRefsWrappedObjects = false;
317     const UniqueID fUniqueID;
318     std::string fLabel;
319
320     using INHERITED = GrIORef<GrGpuResource>;
321     friend class GrIORef<GrGpuResource>; // to access notifyRefCntWillBeZero and
322                                          // notifyARefCntIsZero.
323 };
324
325 class GrGpuResource::ProxyAccess {
326 private:
327     ProxyAccess(GrGpuResource* resource) : fResource(resource) {}
328
329     /** Proxies are allowed to take a resource from no refs to one ref. */
330     void ref(GrResourceCache* cache);
331
332     // No taking addresses of this type.
333     const CacheAccess* operator&() const = delete;
334     CacheAccess* operator&() = delete;
335
336     GrGpuResource* fResource;
337
338     friend class GrGpuResource;
339     friend class GrSurfaceProxy;
340 };
341
342 inline GrGpuResource::ProxyAccess GrGpuResource::proxyAccess() { return ProxyAccess(this); }
343
344 #endif