• 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. 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