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