• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
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 GrRefCnt_DEFINED
9 #define GrRefCnt_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "src/gpu/GrGpuResource.h"
13 #include "src/gpu/GrManagedResource.h"
14 
15 // We have to use auto for the function pointers here because if the actual functions live on the
16 // base class of T we need the function here to be a pointer to a function of the base class and not
17 // a function on T. In C++17 RefBase and UnrefBase can be removed and the Ref and Unref paramenters
18 // can be "auto".
19 template <typename T,
20           typename RefBase                 = T,
21           typename UnrefBase               = RefBase,
22           void (RefBase::*Ref)() const     = RefBase::Ref,
23           void (UnrefBase::*Unref)() const = UnrefBase::Unref>
24 class gr_sp {
25 private:
SafeRef(T * obj)26     static inline T* SafeRef(T* obj) {
27         if (obj) {
28             (obj->*Ref)();
29         }
30         return obj;
31     }
32 
SafeUnref(T * obj)33     static inline void SafeUnref(T* obj) {
34         if (obj) {
35             (obj->*Unref)();
36         }
37     }
38 
39 public:
40     using element_type = T;
41 
gr_sp()42     constexpr gr_sp() : fPtr(nullptr) {}
gr_sp(std::nullptr_t)43     constexpr gr_sp(std::nullptr_t) : fPtr(nullptr) {}
44 
45     /**
46      * Shares the underlying object by calling Ref(), so that both the argument and the newly
47      * created gr_sp both have a reference to it.
48      */
gr_sp(const gr_sp & that)49     gr_sp(const gr_sp& that) : fPtr(SafeRef(that.get())) {}
50     template <typename U,
51               typename URefBase,
52               typename UUnrefBase,
53               typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
gr_sp(const gr_sp<U,URefBase,UUnrefBase,Ref,Unref> & that)54     gr_sp(const gr_sp<U, URefBase, UUnrefBase, Ref, Unref>& that) : fPtr(SafeRef(that.get())) {}
55 
gr_sp(const sk_sp<T> & that)56     gr_sp(const sk_sp<T>& that) : fPtr(SafeRef(that.get())) {}
57 
58 
59     /**
60      * Move the underlying object from the argument to the newly created gr_sp. Afterwards only the
61      * new gr_sp will have a reference to the object, and the argument will point to null.
62      * No call to Ref() or Unref() will be made.
63      */
gr_sp(gr_sp && that)64     gr_sp(gr_sp&& that) : fPtr(that.release()) {}
65 
66     /**
67      * Copies the underlying object pointer from the argument to the gr_sp. It will then call
68      * Ref() on the new object.
69      */
gr_sp(sk_sp<T> && that)70     gr_sp(sk_sp<T>&& that) : fPtr(SafeRef(that.get())) {}
71 
72     /**
73      *  Adopt the bare pointer into the newly created gr_sp.
74      *  No call to Ref() or Unref() will be made.
75      */
gr_sp(T * obj)76     explicit gr_sp(T* obj) : fPtr(obj) {}
77 
78     /**
79      * Calls Unref() on the underlying object pointer.
80      */
~gr_sp()81     ~gr_sp() {
82         SafeUnref(fPtr);
83         SkDEBUGCODE(fPtr = nullptr);
84     }
85 
86     gr_sp& operator=(std::nullptr_t) {
87         this->reset();
88         return *this;
89     }
90 
91     /**
92      * Shares the underlying object referenced by the argument by calling Ref() on it. If this gr_sp
93      * previously had a reference to an object (i.e. not null) it will call Unref() on that object.
94      */
95     gr_sp& operator=(const gr_sp& that) {
96         if (this != &that) {
97             this->reset(SafeRef(that.get()));
98         }
99         return *this;
100     }
101 
102     /**
103      * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously
104      * held a reference to another object, Unref() will be called on that object. It will then call
105      * Ref() on the new object.
106      */
107     gr_sp& operator=(const sk_sp<T>& that) {
108         this->reset(SafeRef(that.get()));
109         return *this;
110     }
111 
112     /**
113      * Move the underlying object from the argument to the gr_sp. If the gr_sp previously held
114      * a reference to another object, Unref() will be called on that object. No call to Ref() will
115      * be made.
116      */
117     gr_sp& operator=(gr_sp&& that) {
118         this->reset(that.release());
119         return *this;
120     }
121 
122     /**
123      * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously
124      * held a reference to another object, Unref() will be called on that object. It will then call
125      * Ref() on the new object.
126      */
127     gr_sp& operator=(sk_sp<T>&& that) {
128         this->reset(SafeRef(that.get()));
129         return *this;
130     }
131 
132     T& operator*() const {
133         SkASSERT(this->get() != nullptr);
134         return *this->get();
135     }
136 
137     explicit operator bool() const { return this->get() != nullptr; }
138 
get()139     T* get() const { return fPtr; }
140     T* operator->() const { return fPtr; }
141 
142     /**
143      * Adopt the new bare pointer, and call Unref() on any previously held object (if not null).
144      * No call to Ref() will be made.
145      */
146     void reset(T* ptr = nullptr) {
147         T* oldPtr = fPtr;
148         fPtr = ptr;
149         SafeUnref(oldPtr);
150     }
151 
152 private:
153     /**
154      * Return the bare pointer, and set the internal object pointer to nullptr.
155      * The caller must assume ownership of the object, and manage its reference count directly.
156      * No call to Unref() will be made.
157      */
release()158     T* SK_WARN_UNUSED_RESULT release() {
159         T* ptr = fPtr;
160         fPtr = nullptr;
161         return ptr;
162     }
163 
164     T* fPtr;
165 };
166 
167 ////////////////////////////////////////////////////////////////////////////////////////////////////
168 
169 /**
170  * Shared pointer class to wrap classes that support a addCommandBufferUsage() and
171  * removeCommandBufferUsage() interface.
172  *
173  * This class supports copying, moving, and assigning an sk_sp into it. In general these commands do
174  * not modify the sk_sp at all but just call addCommandBufferUsage() on the underlying object.
175  *
176  * This class is designed to be used by GrGpuResources that need to track when they are in use on
177  * gpu (usually via a command buffer) separately from tracking if there are any current logical
178  * usages in Ganesh. This allows for a scratch GrGpuResource to be reused for new draw calls even
179  * if it is in use on the GPU.
180  */
181 template <typename T>
182 using gr_cb = gr_sp<T,
183                     GrIORef<GrGpuResource>,
184                     GrIORef<GrGpuResource>,
185                     &T::addCommandBufferUsage,
186                     &T::removeCommandBufferUsage>;
187 
188 ////////////////////////////////////////////////////////////////////////////////////////////////////
189 
190 /**
191  * This class mimics sk_sp but instead of calling unref it calls recycle instead.
192  */
193 template <typename T>
194 using gr_rp = gr_sp<T, GrManagedResource, GrRecycledResource, &T::ref, &T::recycle>;
195 
196 /**
197  *  Returns a gr_rp wrapping the provided ptr AND calls ref on it (if not null).
198  *
199  *  This is different than the semantics of the constructor for gr_rp, which just wraps the ptr,
200  *  effectively "adopting" it.
201  */
gr_ref_rp(T * obj)202 template <typename T> gr_rp<T> gr_ref_rp(T* obj) { return gr_rp<T>(SkSafeRef(obj)); }
203 
gr_ref_rp(const T * obj)204 template <typename T> gr_rp<T> gr_ref_rp(const T* obj) {
205     return gr_rp<T>(const_cast<T*>(SkSafeRef(obj)));
206 }
207 #endif
208