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