|  | /* | 
|  | * Copyright 2020 Google LLC | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef GrRefCnt_DEFINED | 
|  | #define GrRefCnt_DEFINED | 
|  |  | 
|  | #include "include/core/SkRefCnt.h" | 
|  |  | 
|  | // We have to use auto for the function pointers here because if the actual functions live on the | 
|  | // base class of T we need the function here to be a pointer to a function of the base class and not | 
|  | // a function on T. Thus we can't have something like void(T::*Ref)() since we may need T or we may | 
|  | // need some base class of T. | 
|  | template <typename T, auto Ref, auto Unref> class gr_sp { | 
|  | private: | 
|  | static inline T* SafeRef(T* obj) { | 
|  | if (obj) { | 
|  | (obj->*Ref)(); | 
|  | } | 
|  | return obj; | 
|  | } | 
|  |  | 
|  | static inline void SafeUnref(T* obj) { | 
|  | if (obj) { | 
|  | (obj->*Unref)(); | 
|  | } | 
|  | } | 
|  |  | 
|  | public: | 
|  | using element_type = T; | 
|  |  | 
|  | constexpr gr_sp() : fPtr(nullptr) {} | 
|  | constexpr gr_sp(std::nullptr_t) : fPtr(nullptr) {} | 
|  |  | 
|  | /** | 
|  | * Shares the underlying object by calling Ref(), so that both the argument and the newly | 
|  | * created gr_sp both have a reference to it. | 
|  | */ | 
|  | gr_sp(const gr_sp<T, Ref, Unref>& that) : fPtr(SafeRef(that.get())) {} | 
|  | template <typename U, | 
|  | typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type> | 
|  | gr_sp(const gr_sp<U, Ref, Unref>& that) : fPtr(SafeRef(that.get())) {} | 
|  |  | 
|  | gr_sp(const sk_sp<T>& that) : fPtr(SafeRef(that.get())) {} | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Move the underlying object from the argument to the newly created gr_sp. Afterwards only the | 
|  | * new gr_sp will have a reference to the object, and the argument will point to null. | 
|  | * No call to Ref() or Unref() will be made. | 
|  | */ | 
|  | gr_sp(gr_sp<T, Ref, Unref>&& that) : fPtr(that.release()) {} | 
|  |  | 
|  | /** | 
|  | * Copies the underlying object pointer from the argument to the gr_sp. It will then call | 
|  | * Ref() on the new object. | 
|  | */ | 
|  | gr_sp(sk_sp<T>&& that) : fPtr(SafeRef(that.get())) {} | 
|  |  | 
|  | /** | 
|  | *  Adopt the bare pointer into the newly created gr_sp. | 
|  | *  No call to Ref() or Unref() will be made. | 
|  | */ | 
|  | explicit gr_sp(T* obj) : fPtr(obj) {} | 
|  |  | 
|  | /** | 
|  | * Calls Unref() on the underlying object pointer. | 
|  | */ | 
|  | ~gr_sp() { | 
|  | SafeUnref(fPtr); | 
|  | SkDEBUGCODE(fPtr = nullptr); | 
|  | } | 
|  |  | 
|  | gr_sp& operator=(std::nullptr_t) { | 
|  | this->reset(); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Shares the underlying object referenced by the argument by calling Ref() on it. If this gr_sp | 
|  | * previously had a reference to an object (i.e. not null) it will call Unref() on that object. | 
|  | */ | 
|  | gr_sp& operator=(const gr_sp<T, Ref, Unref>& that) { | 
|  | if (this != &that) { | 
|  | this->reset(SafeRef(that.get())); | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously | 
|  | * held a reference to another object, Unref() will be called on that object. It will then call | 
|  | * Ref() on the new object. | 
|  | */ | 
|  | gr_sp& operator=(const sk_sp<T>& that) { | 
|  | this->reset(SafeRef(that.get())); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Move the underlying object from the argument to the gr_sp. If the gr_sp previously held | 
|  | * a reference to another object, Unref() will be called on that object. No call to Ref() will | 
|  | * be made. | 
|  | */ | 
|  | gr_sp& operator=(gr_sp<T, Ref, Unref>&& that) { | 
|  | this->reset(that.release()); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously | 
|  | * held a reference to another object, Unref() will be called on that object. It will then call | 
|  | * Ref() on the new object. | 
|  | */ | 
|  | gr_sp& operator=(sk_sp<T>&& that) { | 
|  | this->reset(SafeRef(that.get())); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | T& operator*() const { | 
|  | SkASSERT(this->get() != nullptr); | 
|  | return *this->get(); | 
|  | } | 
|  |  | 
|  | explicit operator bool() const { return this->get() != nullptr; } | 
|  |  | 
|  | T* get() const { return fPtr; } | 
|  | T* operator->() const { return fPtr; } | 
|  |  | 
|  | private: | 
|  | /** | 
|  | * Adopt the new bare pointer, and call Unref() on any previously held object (if not null). | 
|  | * No call to Ref() will be made. | 
|  | */ | 
|  | void reset(T* ptr = nullptr) { | 
|  | T* oldPtr = fPtr; | 
|  | fPtr = ptr; | 
|  | SafeUnref(oldPtr); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Return the bare pointer, and set the internal object pointer to nullptr. | 
|  | * The caller must assume ownership of the object, and manage its reference count directly. | 
|  | * No call to Unref() will be made. | 
|  | */ | 
|  | T* SK_WARN_UNUSED_RESULT release() { | 
|  | T* ptr = fPtr; | 
|  | fPtr = nullptr; | 
|  | return ptr; | 
|  | } | 
|  |  | 
|  | T* fPtr; | 
|  | }; | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | /** | 
|  | * Shared pointer class to wrap classes that support a addCommandBufferUsage() and | 
|  | * removeCommandBufferUsage() interface. | 
|  | * | 
|  | * This class supports copying, moving, and assigning an sk_sp into it. In general these commands do | 
|  | * not modify the sk_sp at all but just call addCommandBufferUsage() on the underlying object. | 
|  | * | 
|  | * This class is designed to be used by GrGpuResources that need to track when they are in use on | 
|  | * gpu (usually via a command buffer) separately from tracking if there are any current logical | 
|  | * usages in Ganesh. This allows for a scratch GrGpuResource to be reused for new draw calls even | 
|  | * if it is in use on the GPU. | 
|  | */ | 
|  | template <typename T> using gr_cb = | 
|  | gr_sp<T, &T::addCommandBufferUsage, &T::removeCommandBufferUsage>; | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | /** | 
|  | * This class mimics sk_sp but instead of calling unref it calls recycle instead. | 
|  | */ | 
|  | template<typename T> using gr_rp = gr_sp<T, &T::ref, &T::recycle>; | 
|  |  | 
|  | /** | 
|  | *  Returns a gr_rp wrapping the provided ptr AND calls ref on it (if not null). | 
|  | * | 
|  | *  This is different than the semantics of the constructor for gr_rp, which just wraps the ptr, | 
|  | *  effectively "adopting" it. | 
|  | */ | 
|  | template <typename T> gr_rp<T> gr_ref_rp(T* obj) { return gr_rp<T>(SkSafeRef(obj)); } | 
|  |  | 
|  | template <typename T> gr_rp<T> gr_ref_rp(const T* obj) { | 
|  | return gr_rp<T>(const_cast<T*>(SkSafeRef(obj))); | 
|  | } | 
|  | #endif |