xref: /aosp_15_r20/external/angle/src/libANGLE/RefCountObject.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // RefCountObject.h: Defines the gl::RefCountObject base class that provides
8*8975f5c5SAndroid Build Coastguard Worker // lifecycle support for GL objects using the traditional BindObject scheme, but
9*8975f5c5SAndroid Build Coastguard Worker // that need to be reference counted for correct cross-context deletion.
10*8975f5c5SAndroid Build Coastguard Worker // (Concretely, textures, buffers and renderbuffers.)
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_REFCOUNTOBJECT_H_
13*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_REFCOUNTOBJECT_H_
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker #include "angle_gl.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "common/PackedEnums.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Error.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Observer.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/serial_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker #include <cstddef>
23*8975f5c5SAndroid Build Coastguard Worker 
24*8975f5c5SAndroid Build Coastguard Worker namespace angle
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker 
27*8975f5c5SAndroid Build Coastguard Worker template <typename ContextT, typename ErrorT>
28*8975f5c5SAndroid Build Coastguard Worker class RefCountObject : angle::NonCopyable
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker   public:
31*8975f5c5SAndroid Build Coastguard Worker     using ContextType = ContextT;
32*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = ErrorT;
33*8975f5c5SAndroid Build Coastguard Worker 
RefCountObject()34*8975f5c5SAndroid Build Coastguard Worker     RefCountObject() : mRefCount(0) {}
35*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const ContextType * context)36*8975f5c5SAndroid Build Coastguard Worker     virtual void onDestroy(const ContextType *context) {}
37*8975f5c5SAndroid Build Coastguard Worker 
addRef()38*8975f5c5SAndroid Build Coastguard Worker     void addRef() const { ++mRefCount; }
39*8975f5c5SAndroid Build Coastguard Worker 
release(const ContextType * context)40*8975f5c5SAndroid Build Coastguard Worker     ANGLE_INLINE void release(const ContextType *context)
41*8975f5c5SAndroid Build Coastguard Worker     {
42*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRefCount > 0);
43*8975f5c5SAndroid Build Coastguard Worker         if (--mRefCount == 0)
44*8975f5c5SAndroid Build Coastguard Worker         {
45*8975f5c5SAndroid Build Coastguard Worker             onDestroy(context);
46*8975f5c5SAndroid Build Coastguard Worker             delete this;
47*8975f5c5SAndroid Build Coastguard Worker         }
48*8975f5c5SAndroid Build Coastguard Worker     }
49*8975f5c5SAndroid Build Coastguard Worker 
getRefCount()50*8975f5c5SAndroid Build Coastguard Worker     size_t getRefCount() const { return mRefCount; }
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker   protected:
~RefCountObject()53*8975f5c5SAndroid Build Coastguard Worker     virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
54*8975f5c5SAndroid Build Coastguard Worker 
55*8975f5c5SAndroid Build Coastguard Worker     mutable size_t mRefCount;
56*8975f5c5SAndroid Build Coastguard Worker };
57*8975f5c5SAndroid Build Coastguard Worker 
58*8975f5c5SAndroid Build Coastguard Worker // Alternative base class to RefCountObject using atomics to track the reference count.
59*8975f5c5SAndroid Build Coastguard Worker // Interchangable with RefCountObject for usage with BindingPointer and other wrappers.
60*8975f5c5SAndroid Build Coastguard Worker template <typename ContextT, typename ErrorT>
61*8975f5c5SAndroid Build Coastguard Worker class ThreadSafeRefCountObject : angle::NonCopyable
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker   public:
64*8975f5c5SAndroid Build Coastguard Worker     using ContextType = ContextT;
65*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = ErrorT;
66*8975f5c5SAndroid Build Coastguard Worker 
ThreadSafeRefCountObject()67*8975f5c5SAndroid Build Coastguard Worker     ThreadSafeRefCountObject() : mRefCount(0) {}
68*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const ContextType * context)69*8975f5c5SAndroid Build Coastguard Worker     virtual void onDestroy(const ContextType *context) {}
70*8975f5c5SAndroid Build Coastguard Worker 
addRef()71*8975f5c5SAndroid Build Coastguard Worker     void addRef() const { mRefCount.fetch_add(1, std::memory_order_relaxed); }
72*8975f5c5SAndroid Build Coastguard Worker 
release(const ContextType * context)73*8975f5c5SAndroid Build Coastguard Worker     ANGLE_INLINE void release(const ContextType *context)
74*8975f5c5SAndroid Build Coastguard Worker     {
75*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mRefCount > 0);
76*8975f5c5SAndroid Build Coastguard Worker         if (mRefCount.fetch_sub(1, std::memory_order_acq_rel) == 1)
77*8975f5c5SAndroid Build Coastguard Worker         {
78*8975f5c5SAndroid Build Coastguard Worker             onDestroy(context);
79*8975f5c5SAndroid Build Coastguard Worker             delete this;
80*8975f5c5SAndroid Build Coastguard Worker         }
81*8975f5c5SAndroid Build Coastguard Worker     }
82*8975f5c5SAndroid Build Coastguard Worker 
getRefCount()83*8975f5c5SAndroid Build Coastguard Worker     size_t getRefCount() const { return mRefCount; }
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker   protected:
~ThreadSafeRefCountObject()86*8975f5c5SAndroid Build Coastguard Worker     virtual ~ThreadSafeRefCountObject() { ASSERT(mRefCount == 0); }
87*8975f5c5SAndroid Build Coastguard Worker 
88*8975f5c5SAndroid Build Coastguard Worker     mutable std::atomic<size_t> mRefCount;
89*8975f5c5SAndroid Build Coastguard Worker };
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType, typename ContextT, typename ErrorT = angle::Result>
92*8975f5c5SAndroid Build Coastguard Worker class RefCountObjectReleaser : angle::NonCopyable
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker   public:
95*8975f5c5SAndroid Build Coastguard Worker     using ContextType = ContextT;
96*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = ErrorT;
97*8975f5c5SAndroid Build Coastguard Worker 
RefCountObjectReleaser()98*8975f5c5SAndroid Build Coastguard Worker     RefCountObjectReleaser() {}
RefCountObjectReleaser(const ContextType * context,ObjectType * object)99*8975f5c5SAndroid Build Coastguard Worker     RefCountObjectReleaser(const ContextType *context, ObjectType *object)
100*8975f5c5SAndroid Build Coastguard Worker         : mContext(context), mObject(object)
101*8975f5c5SAndroid Build Coastguard Worker     {}
102*8975f5c5SAndroid Build Coastguard Worker 
RefCountObjectReleaser(RefCountObjectReleaser && other)103*8975f5c5SAndroid Build Coastguard Worker     RefCountObjectReleaser(RefCountObjectReleaser &&other)
104*8975f5c5SAndroid Build Coastguard Worker         : mContext(other.mContext), mObject(other.mObject)
105*8975f5c5SAndroid Build Coastguard Worker     {
106*8975f5c5SAndroid Build Coastguard Worker         other.mContext = nullptr;
107*8975f5c5SAndroid Build Coastguard Worker         other.mObject  = nullptr;
108*8975f5c5SAndroid Build Coastguard Worker     }
109*8975f5c5SAndroid Build Coastguard Worker 
110*8975f5c5SAndroid Build Coastguard Worker     RefCountObjectReleaser &operator=(RefCountObjectReleaser &&other)
111*8975f5c5SAndroid Build Coastguard Worker     {
112*8975f5c5SAndroid Build Coastguard Worker         std::swap(mContext, other.mContext);
113*8975f5c5SAndroid Build Coastguard Worker         std::swap(mObject, other.mObject);
114*8975f5c5SAndroid Build Coastguard Worker         return *this;
115*8975f5c5SAndroid Build Coastguard Worker     }
116*8975f5c5SAndroid Build Coastguard Worker 
~RefCountObjectReleaser()117*8975f5c5SAndroid Build Coastguard Worker     ~RefCountObjectReleaser()
118*8975f5c5SAndroid Build Coastguard Worker     {
119*8975f5c5SAndroid Build Coastguard Worker         if (mObject)
120*8975f5c5SAndroid Build Coastguard Worker         {
121*8975f5c5SAndroid Build Coastguard Worker             mObject->release(mContext);
122*8975f5c5SAndroid Build Coastguard Worker             mObject = nullptr;
123*8975f5c5SAndroid Build Coastguard Worker         }
124*8975f5c5SAndroid Build Coastguard Worker     }
125*8975f5c5SAndroid Build Coastguard Worker 
126*8975f5c5SAndroid Build Coastguard Worker   private:
127*8975f5c5SAndroid Build Coastguard Worker     const ContextType *mContext = nullptr;
128*8975f5c5SAndroid Build Coastguard Worker     ObjectType *mObject         = nullptr;
129*8975f5c5SAndroid Build Coastguard Worker };
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType, typename ContextT, typename ErrorT = angle::Result>
132*8975f5c5SAndroid Build Coastguard Worker class BindingPointer
133*8975f5c5SAndroid Build Coastguard Worker {
134*8975f5c5SAndroid Build Coastguard Worker   public:
135*8975f5c5SAndroid Build Coastguard Worker     using ContextType = ContextT;
136*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = ErrorT;
137*8975f5c5SAndroid Build Coastguard Worker 
BindingPointer()138*8975f5c5SAndroid Build Coastguard Worker     BindingPointer() : mObject(nullptr) {}
139*8975f5c5SAndroid Build Coastguard Worker 
BindingPointer(ObjectType * object)140*8975f5c5SAndroid Build Coastguard Worker     BindingPointer(ObjectType *object) : mObject(object)
141*8975f5c5SAndroid Build Coastguard Worker     {
142*8975f5c5SAndroid Build Coastguard Worker         if (mObject)
143*8975f5c5SAndroid Build Coastguard Worker         {
144*8975f5c5SAndroid Build Coastguard Worker             mObject->addRef();
145*8975f5c5SAndroid Build Coastguard Worker         }
146*8975f5c5SAndroid Build Coastguard Worker     }
147*8975f5c5SAndroid Build Coastguard Worker 
BindingPointer(const BindingPointer & other)148*8975f5c5SAndroid Build Coastguard Worker     BindingPointer(const BindingPointer &other) : mObject(other.mObject)
149*8975f5c5SAndroid Build Coastguard Worker     {
150*8975f5c5SAndroid Build Coastguard Worker         if (mObject)
151*8975f5c5SAndroid Build Coastguard Worker         {
152*8975f5c5SAndroid Build Coastguard Worker             mObject->addRef();
153*8975f5c5SAndroid Build Coastguard Worker         }
154*8975f5c5SAndroid Build Coastguard Worker     }
155*8975f5c5SAndroid Build Coastguard Worker 
156*8975f5c5SAndroid Build Coastguard Worker     BindingPointer &operator=(BindingPointer &&other)
157*8975f5c5SAndroid Build Coastguard Worker     {
158*8975f5c5SAndroid Build Coastguard Worker         std::swap(mObject, other.mObject);
159*8975f5c5SAndroid Build Coastguard Worker         return *this;
160*8975f5c5SAndroid Build Coastguard Worker     }
161*8975f5c5SAndroid Build Coastguard Worker 
~BindingPointer()162*8975f5c5SAndroid Build Coastguard Worker     virtual ~BindingPointer()
163*8975f5c5SAndroid Build Coastguard Worker     {
164*8975f5c5SAndroid Build Coastguard Worker         // Objects have to be released before the resource manager is destroyed, so they must be
165*8975f5c5SAndroid Build Coastguard Worker         // explicitly cleaned up.
166*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mObject == nullptr);
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker 
set(const ContextType * context,ObjectType * newObject)169*8975f5c5SAndroid Build Coastguard Worker     RefCountObjectReleaser<ObjectType, ContextType, ErrorT> set(const ContextType *context,
170*8975f5c5SAndroid Build Coastguard Worker                                                                 ObjectType *newObject)
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker         // addRef first in case newObject == mObject and this is the last reference to it.
173*8975f5c5SAndroid Build Coastguard Worker         if (newObject != nullptr)
174*8975f5c5SAndroid Build Coastguard Worker         {
175*8975f5c5SAndroid Build Coastguard Worker             newObject->addRef();
176*8975f5c5SAndroid Build Coastguard Worker         }
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker         // Store the old pointer in a temporary so we can set the pointer before calling release.
179*8975f5c5SAndroid Build Coastguard Worker         // Otherwise the object could still be referenced when its destructor is called.
180*8975f5c5SAndroid Build Coastguard Worker         ObjectType *oldObject = mObject;
181*8975f5c5SAndroid Build Coastguard Worker         mObject               = newObject;
182*8975f5c5SAndroid Build Coastguard Worker         return RefCountObjectReleaser<ObjectType, ContextType, ErrorT>(context, oldObject);
183*8975f5c5SAndroid Build Coastguard Worker     }
184*8975f5c5SAndroid Build Coastguard Worker 
assign(ObjectType * object)185*8975f5c5SAndroid Build Coastguard Worker     void assign(ObjectType *object) { mObject = object; }
186*8975f5c5SAndroid Build Coastguard Worker 
get()187*8975f5c5SAndroid Build Coastguard Worker     ObjectType *get() const { return mObject; }
188*8975f5c5SAndroid Build Coastguard Worker     ObjectType *operator->() const { return mObject; }
189*8975f5c5SAndroid Build Coastguard Worker 
190*8975f5c5SAndroid Build Coastguard Worker     bool operator==(const BindingPointer &other) const { return mObject == other.mObject; }
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker     bool operator!=(const BindingPointer &other) const { return !(*this == other); }
193*8975f5c5SAndroid Build Coastguard Worker 
194*8975f5c5SAndroid Build Coastguard Worker   protected:
setImpl(ObjectType * obj)195*8975f5c5SAndroid Build Coastguard Worker     ANGLE_INLINE void setImpl(ObjectType *obj) { mObject = obj; }
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker   private:
198*8975f5c5SAndroid Build Coastguard Worker     ObjectType *mObject;
199*8975f5c5SAndroid Build Coastguard Worker };
200*8975f5c5SAndroid Build Coastguard Worker }  // namespace angle
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker namespace gl
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker class Context;
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType>
207*8975f5c5SAndroid Build Coastguard Worker class BindingPointer;
208*8975f5c5SAndroid Build Coastguard Worker 
209*8975f5c5SAndroid Build Coastguard Worker using RefCountObjectNoID           = angle::RefCountObject<Context, angle::Result>;
210*8975f5c5SAndroid Build Coastguard Worker using ThreadSafeRefCountObjectNoID = angle::ThreadSafeRefCountObject<Context, angle::Result>;
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker template <typename IDType, typename RC = RefCountObjectNoID>
213*8975f5c5SAndroid Build Coastguard Worker class RefCountObject : public RC
214*8975f5c5SAndroid Build Coastguard Worker {
215*8975f5c5SAndroid Build Coastguard Worker   public:
RefCountObject(rx::UniqueSerial serial,IDType id)216*8975f5c5SAndroid Build Coastguard Worker     explicit RefCountObject(rx::UniqueSerial serial, IDType id) : mSerial(serial), mId(id) {}
217*8975f5c5SAndroid Build Coastguard Worker 
serial()218*8975f5c5SAndroid Build Coastguard Worker     rx::UniqueSerial serial() const { return mSerial; }
id()219*8975f5c5SAndroid Build Coastguard Worker     IDType id() const { return mId; }
220*8975f5c5SAndroid Build Coastguard Worker 
221*8975f5c5SAndroid Build Coastguard Worker   protected:
~RefCountObject()222*8975f5c5SAndroid Build Coastguard Worker     ~RefCountObject() override {}
223*8975f5c5SAndroid Build Coastguard Worker 
224*8975f5c5SAndroid Build Coastguard Worker   private:
225*8975f5c5SAndroid Build Coastguard Worker     // Unique serials are used to identify resources for frame capture.
226*8975f5c5SAndroid Build Coastguard Worker     rx::UniqueSerial mSerial;
227*8975f5c5SAndroid Build Coastguard Worker     IDType mId;
228*8975f5c5SAndroid Build Coastguard Worker };
229*8975f5c5SAndroid Build Coastguard Worker template <typename IDType>
230*8975f5c5SAndroid Build Coastguard Worker using ThreadSafeRefCountObject = RefCountObject<IDType, ThreadSafeRefCountObjectNoID>;
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType>
233*8975f5c5SAndroid Build Coastguard Worker class BindingPointer : public angle::BindingPointer<ObjectType, Context>
234*8975f5c5SAndroid Build Coastguard Worker {
235*8975f5c5SAndroid Build Coastguard Worker   public:
236*8975f5c5SAndroid Build Coastguard Worker     using ContextType = typename angle::BindingPointer<ObjectType, Context>::ContextType;
237*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = typename angle::BindingPointer<ObjectType, Context>::ErrorType;
238*8975f5c5SAndroid Build Coastguard Worker 
BindingPointer()239*8975f5c5SAndroid Build Coastguard Worker     BindingPointer() {}
240*8975f5c5SAndroid Build Coastguard Worker 
BindingPointer(ObjectType * object)241*8975f5c5SAndroid Build Coastguard Worker     BindingPointer(ObjectType *object) : angle::BindingPointer<ObjectType, Context>(object) {}
242*8975f5c5SAndroid Build Coastguard Worker 
id()243*8975f5c5SAndroid Build Coastguard Worker     typename ResourceTypeToID<ObjectType>::IDType id() const
244*8975f5c5SAndroid Build Coastguard Worker     {
245*8975f5c5SAndroid Build Coastguard Worker         ObjectType *obj = this->get();
246*8975f5c5SAndroid Build Coastguard Worker         if (obj)
247*8975f5c5SAndroid Build Coastguard Worker             return obj->id();
248*8975f5c5SAndroid Build Coastguard Worker         return {0};
249*8975f5c5SAndroid Build Coastguard Worker     }
250*8975f5c5SAndroid Build Coastguard Worker };
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType>
253*8975f5c5SAndroid Build Coastguard Worker class OffsetBindingPointer : public BindingPointer<ObjectType>
254*8975f5c5SAndroid Build Coastguard Worker {
255*8975f5c5SAndroid Build Coastguard Worker   public:
256*8975f5c5SAndroid Build Coastguard Worker     using ContextType = typename BindingPointer<ObjectType>::ContextType;
257*8975f5c5SAndroid Build Coastguard Worker     using ErrorType   = typename BindingPointer<ObjectType>::ErrorType;
258*8975f5c5SAndroid Build Coastguard Worker 
OffsetBindingPointer()259*8975f5c5SAndroid Build Coastguard Worker     OffsetBindingPointer() : mOffset(0), mSize(0) {}
260*8975f5c5SAndroid Build Coastguard Worker 
set(const ContextType * context,ObjectType * newObject,GLintptr offset,GLsizeiptr size)261*8975f5c5SAndroid Build Coastguard Worker     void set(const ContextType *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
262*8975f5c5SAndroid Build Coastguard Worker     {
263*8975f5c5SAndroid Build Coastguard Worker         set(context, newObject);
264*8975f5c5SAndroid Build Coastguard Worker         updateOffsetAndSize(newObject, offset, size);
265*8975f5c5SAndroid Build Coastguard Worker     }
266*8975f5c5SAndroid Build Coastguard Worker 
getOffset()267*8975f5c5SAndroid Build Coastguard Worker     GLintptr getOffset() const { return mOffset; }
getSize()268*8975f5c5SAndroid Build Coastguard Worker     GLsizeiptr getSize() const { return mSize; }
269*8975f5c5SAndroid Build Coastguard Worker 
270*8975f5c5SAndroid Build Coastguard Worker     bool operator==(const OffsetBindingPointer<ObjectType> &other) const
271*8975f5c5SAndroid Build Coastguard Worker     {
272*8975f5c5SAndroid Build Coastguard Worker         return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize;
273*8975f5c5SAndroid Build Coastguard Worker     }
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker     bool operator!=(const OffsetBindingPointer<ObjectType> &other) const
276*8975f5c5SAndroid Build Coastguard Worker     {
277*8975f5c5SAndroid Build Coastguard Worker         return !(*this == other);
278*8975f5c5SAndroid Build Coastguard Worker     }
279*8975f5c5SAndroid Build Coastguard Worker 
assign(ObjectType * newObject,GLintptr offset,GLsizeiptr size)280*8975f5c5SAndroid Build Coastguard Worker     void assign(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
281*8975f5c5SAndroid Build Coastguard Worker     {
282*8975f5c5SAndroid Build Coastguard Worker         assign(newObject);
283*8975f5c5SAndroid Build Coastguard Worker         updateOffsetAndSize(newObject, offset, size);
284*8975f5c5SAndroid Build Coastguard Worker     }
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker   private:
updateOffsetAndSize(ObjectType * newObject,GLintptr offset,GLsizeiptr size)287*8975f5c5SAndroid Build Coastguard Worker     ANGLE_INLINE void updateOffsetAndSize(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
288*8975f5c5SAndroid Build Coastguard Worker     {
289*8975f5c5SAndroid Build Coastguard Worker         if (newObject)
290*8975f5c5SAndroid Build Coastguard Worker         {
291*8975f5c5SAndroid Build Coastguard Worker             mOffset = offset;
292*8975f5c5SAndroid Build Coastguard Worker             mSize   = size;
293*8975f5c5SAndroid Build Coastguard Worker         }
294*8975f5c5SAndroid Build Coastguard Worker         else
295*8975f5c5SAndroid Build Coastguard Worker         {
296*8975f5c5SAndroid Build Coastguard Worker             mOffset = 0;
297*8975f5c5SAndroid Build Coastguard Worker             mSize   = 0;
298*8975f5c5SAndroid Build Coastguard Worker         }
299*8975f5c5SAndroid Build Coastguard Worker     }
300*8975f5c5SAndroid Build Coastguard Worker 
301*8975f5c5SAndroid Build Coastguard Worker     // Delete the unparameterized functions. This forces an explicit offset and size.
302*8975f5c5SAndroid Build Coastguard Worker     using BindingPointer<ObjectType>::set;
303*8975f5c5SAndroid Build Coastguard Worker     using BindingPointer<ObjectType>::assign;
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker     GLintptr mOffset;
306*8975f5c5SAndroid Build Coastguard Worker     GLsizeiptr mSize;
307*8975f5c5SAndroid Build Coastguard Worker };
308*8975f5c5SAndroid Build Coastguard Worker 
309*8975f5c5SAndroid Build Coastguard Worker template <typename SubjectT>
310*8975f5c5SAndroid Build Coastguard Worker class SubjectBindingPointer : protected BindingPointer<SubjectT>, public angle::ObserverBindingBase
311*8975f5c5SAndroid Build Coastguard Worker {
312*8975f5c5SAndroid Build Coastguard Worker   public:
SubjectBindingPointer(angle::ObserverInterface * observer,angle::SubjectIndex index)313*8975f5c5SAndroid Build Coastguard Worker     SubjectBindingPointer(angle::ObserverInterface *observer, angle::SubjectIndex index)
314*8975f5c5SAndroid Build Coastguard Worker         : ObserverBindingBase(observer, index)
315*8975f5c5SAndroid Build Coastguard Worker     {}
~SubjectBindingPointer()316*8975f5c5SAndroid Build Coastguard Worker     ~SubjectBindingPointer() override {}
317*8975f5c5SAndroid Build Coastguard Worker     SubjectBindingPointer(const SubjectBindingPointer &other)            = default;
318*8975f5c5SAndroid Build Coastguard Worker     SubjectBindingPointer &operator=(const SubjectBindingPointer &other) = default;
319*8975f5c5SAndroid Build Coastguard Worker 
bind(const Context * context,SubjectT * subject)320*8975f5c5SAndroid Build Coastguard Worker     void bind(const Context *context, SubjectT *subject)
321*8975f5c5SAndroid Build Coastguard Worker     {
322*8975f5c5SAndroid Build Coastguard Worker         // AddRef first in case subject == get()
323*8975f5c5SAndroid Build Coastguard Worker         if (subject)
324*8975f5c5SAndroid Build Coastguard Worker         {
325*8975f5c5SAndroid Build Coastguard Worker             subject->addObserver(this);
326*8975f5c5SAndroid Build Coastguard Worker             subject->addRef();
327*8975f5c5SAndroid Build Coastguard Worker         }
328*8975f5c5SAndroid Build Coastguard Worker 
329*8975f5c5SAndroid Build Coastguard Worker         if (get())
330*8975f5c5SAndroid Build Coastguard Worker         {
331*8975f5c5SAndroid Build Coastguard Worker             get()->removeObserver(this);
332*8975f5c5SAndroid Build Coastguard Worker             get()->release(context);
333*8975f5c5SAndroid Build Coastguard Worker         }
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker         this->setImpl(subject);
336*8975f5c5SAndroid Build Coastguard Worker     }
337*8975f5c5SAndroid Build Coastguard Worker 
338*8975f5c5SAndroid Build Coastguard Worker     using BindingPointer<SubjectT>::get;
339*8975f5c5SAndroid Build Coastguard Worker     using BindingPointer<SubjectT>::operator->;
340*8975f5c5SAndroid Build Coastguard Worker 
341*8975f5c5SAndroid Build Coastguard Worker     friend class State;
342*8975f5c5SAndroid Build Coastguard Worker };
343*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
344*8975f5c5SAndroid Build Coastguard Worker 
345*8975f5c5SAndroid Build Coastguard Worker namespace egl
346*8975f5c5SAndroid Build Coastguard Worker {
347*8975f5c5SAndroid Build Coastguard Worker class Display;
348*8975f5c5SAndroid Build Coastguard Worker 
349*8975f5c5SAndroid Build Coastguard Worker using RefCountObject           = angle::RefCountObject<Display, Error>;
350*8975f5c5SAndroid Build Coastguard Worker using ThreadSafeRefCountObject = angle::ThreadSafeRefCountObject<Display, Error>;
351*8975f5c5SAndroid Build Coastguard Worker 
352*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType>
353*8975f5c5SAndroid Build Coastguard Worker using RefCountObjectReleaser = angle::RefCountObjectReleaser<ObjectType, Display, Error>;
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker template <class ObjectType>
356*8975f5c5SAndroid Build Coastguard Worker using BindingPointer = angle::BindingPointer<ObjectType, Display, Error>;
357*8975f5c5SAndroid Build Coastguard Worker 
358*8975f5c5SAndroid Build Coastguard Worker }  // namespace egl
359*8975f5c5SAndroid Build Coastguard Worker 
360*8975f5c5SAndroid Build Coastguard Worker #endif  // LIBANGLE_REFCOUNTOBJECT_H_
361