Commit 620a6895 by Geoff Lang Committed by Commit Bot

Refactor RefCountObject and Binding pointer into the angle namespace.

Make the onDestroy method generic to use different context and error types. This will allow us to have RefCountObjects for EGL that return EGL errors and destroy with egl::Displays. BUG=angleproject:2668 Change-Id: I77549cdc7119979d6eec96c7e6246242aed74830 Reviewed-on: https://chromium-review.googlesource.com/1153452 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bdc610ae
...@@ -106,6 +106,8 @@ class ANGLE_NO_DISCARD Error final ...@@ -106,6 +106,8 @@ class ANGLE_NO_DISCARD Error final
bool operator==(const Error &other) const; bool operator==(const Error &other) const;
bool operator!=(const Error &other) const; bool operator!=(const Error &other) const;
static inline Error NoError();
private: private:
void createMessageString() const; void createMessageString() const;
...@@ -140,7 +142,7 @@ using InvalidFramebufferOperation = priv::ErrorStream<GL_INVALID_FRAMEBUFFER_OPE ...@@ -140,7 +142,7 @@ using InvalidFramebufferOperation = priv::ErrorStream<GL_INVALID_FRAMEBUFFER_OPE
inline Error NoError() inline Error NoError()
{ {
return Error(GL_NO_ERROR); return Error::NoError();
} }
using LinkResult = ErrorOrResult<bool>; using LinkResult = ErrorOrResult<bool>;
...@@ -173,6 +175,8 @@ class ANGLE_NO_DISCARD Error final ...@@ -173,6 +175,8 @@ class ANGLE_NO_DISCARD Error final
const std::string &getMessage() const; const std::string &getMessage() const;
static inline Error NoError();
private: private:
void createMessageString() const; void createMessageString() const;
...@@ -214,7 +218,7 @@ using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>; ...@@ -214,7 +218,7 @@ using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>;
inline Error NoError() inline Error NoError()
{ {
return Error(EGL_SUCCESS); return Error::NoError();
} }
} // namespace egl } // namespace egl
......
...@@ -97,6 +97,12 @@ bool Error::isError() const ...@@ -97,6 +97,12 @@ bool Error::isError() const
return (mCode != GL_NO_ERROR); return (mCode != GL_NO_ERROR);
} }
// static
Error Error::NoError()
{
return Error(GL_NO_ERROR);
}
} // namespace gl } // namespace gl
namespace egl namespace egl
...@@ -186,4 +192,10 @@ bool Error::isError() const ...@@ -186,4 +192,10 @@ bool Error::isError() const
return (mCode != EGL_SUCCESS); return (mCode != EGL_SUCCESS);
} }
// Static
Error Error::NoError()
{
return Error(EGL_SUCCESS);
}
} }
...@@ -18,35 +18,23 @@ ...@@ -18,35 +18,23 @@
#include <cstddef> #include <cstddef>
namespace gl namespace angle
{ {
class Context;
class RefCountObjectNoID : angle::NonCopyable template <typename ContextT, typename ErrorT>
class RefCountObject : angle::NonCopyable
{ {
public: public:
RefCountObjectNoID() : mRefCount(0) {} using ContextType = ContextT;
virtual Error onDestroy(const Context *context); using ErrorType = ErrorT;
void addRef() const { ++mRefCount; }
void release() const RefCountObject() : mRefCount(0) {}
{
ASSERT(mRefCount > 0);
if (--mRefCount == 0) virtual ErrorType onDestroy(const ContextType *context) { return ErrorType::NoError(); }
{
delete this;
}
}
size_t getRefCount() const { return mRefCount; } void addRef() const { ++mRefCount; }
protected:
virtual ~RefCountObjectNoID();
// A specialized release method for objects which need a destroy context. void release(const ContextType *context)
void release(const gl::Context *context)
{ {
ASSERT(mRefCount > 0); ASSERT(mRefCount > 0);
if (--mRefCount == 0) if (--mRefCount == 0)
...@@ -56,54 +44,35 @@ class RefCountObjectNoID : angle::NonCopyable ...@@ -56,54 +44,35 @@ class RefCountObjectNoID : angle::NonCopyable
} }
} }
template <class ObjectType> size_t getRefCount() const { return mRefCount; }
friend class BindingPointer;
mutable std::size_t mRefCount;
};
inline RefCountObjectNoID::~RefCountObjectNoID()
{
ASSERT(mRefCount == 0);
}
inline Error RefCountObjectNoID::onDestroy(const Context *context)
{
return NoError();
}
template <class ObjectType>
class BindingPointer;
class RefCountObject : RefCountObjectNoID
{
public:
explicit RefCountObject(GLuint id) : mId(id) {}
GLuint id() const { return mId; }
using RefCountObjectNoID::release;
using RefCountObjectNoID::addRef;
using RefCountObjectNoID::getRefCount;
protected: protected:
~RefCountObject() override {} virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
private: mutable size_t mRefCount;
GLuint mId;
}; };
template <class ObjectType> template <class ObjectType, typename ContextT, typename ErrorT>
class BindingPointer class BindingPointer
{ {
public: public:
using ContextType = ContextT;
using ErrorType = ErrorT;
BindingPointer() BindingPointer()
: mObject(nullptr) : mObject(nullptr)
{ {
} }
BindingPointer(ObjectType *object) : mObject(object) { mObject->addRef(); } BindingPointer(ObjectType *object) : mObject(object)
{
if (mObject)
{
mObject->addRef();
}
}
BindingPointer(const BindingPointer<ObjectType> &other) : mObject(other.mObject) BindingPointer(const BindingPointer &other) : mObject(other.mObject)
{ {
if (mObject) if (mObject)
{ {
...@@ -111,7 +80,7 @@ class BindingPointer ...@@ -111,7 +80,7 @@ class BindingPointer
} }
} }
BindingPointer &operator=(BindingPointer<ObjectType> &&other) BindingPointer &operator=(BindingPointer &&other)
{ {
std::swap(mObject, other.mObject); std::swap(mObject, other.mObject);
return *this; return *this;
...@@ -123,48 +92,96 @@ class BindingPointer ...@@ -123,48 +92,96 @@ class BindingPointer
ASSERT(mObject == nullptr); ASSERT(mObject == nullptr);
} }
virtual void set(const Context *context, ObjectType *newObject) virtual void set(const ContextType *context, ObjectType *newObject)
{ {
// addRef first in case newObject == mObject and this is the last reference to it. // addRef first in case newObject == mObject and this is the last reference to it.
if (newObject != nullptr) reinterpret_cast<const RefCountObjectNoID*>(newObject)->addRef(); if (newObject != nullptr)
{
reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(newObject)->addRef();
}
// Store the old pointer in a temporary so we can set the pointer before calling release. // Store the old pointer in a temporary so we can set the pointer before calling release.
// Otherwise the object could still be referenced when its destructor is called. // Otherwise the object could still be referenced when its destructor is called.
ObjectType *oldObject = mObject; ObjectType *oldObject = mObject;
mObject = newObject; mObject = newObject;
if (oldObject != nullptr) if (oldObject != nullptr)
reinterpret_cast<RefCountObjectNoID *>(oldObject)->release(context); {
reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(oldObject)->release(context);
}
} }
ObjectType *get() const { return mObject; } ObjectType *get() const { return mObject; }
ObjectType *operator->() const { return mObject; } ObjectType *operator->() const { return mObject; }
GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } bool operator==(const BindingPointer &other) const { return mObject == other.mObject; }
bool operator==(const BindingPointer<ObjectType> &other) const bool operator!=(const BindingPointer &other) const { return !(*this == other); }
{
return mObject == other.mObject;
}
bool operator!=(const BindingPointer<ObjectType> &other) const { return !(*this == other); }
private: private:
ObjectType *mObject; ObjectType *mObject;
}; };
} // namespace angle
namespace gl
{
class Context;
template <class ObjectType>
class BindingPointer;
using RefCountObjectNoID = angle::RefCountObject<Context, Error>;
class RefCountObject : public gl::RefCountObjectNoID
{
public:
explicit RefCountObject(GLuint id) : mId(id) {}
GLuint id() const { return mId; }
protected:
~RefCountObject() override {}
private:
GLuint mId;
};
template <class ObjectType> template <class ObjectType>
class OffsetBindingPointer : public BindingPointer<ObjectType> class BindingPointer : public angle::BindingPointer<ObjectType, Context, Error>
{ {
public: public:
using ContextType = typename angle::BindingPointer<ObjectType, Context, Error>::ContextType;
using ErrorType = typename angle::BindingPointer<ObjectType, Context, Error>::ErrorType;
BindingPointer() {}
BindingPointer(ObjectType *object) : angle::BindingPointer<ObjectType, Context, Error>(object)
{
}
GLuint id() const
{
ObjectType *obj = this->get();
return obj ? obj->id() : 0;
}
};
template <class ObjectType>
class OffsetBindingPointer : public gl::BindingPointer<ObjectType>
{
public:
using ContextType = typename gl::BindingPointer<ObjectType>::ContextType;
using ErrorType = typename gl::BindingPointer<ObjectType>::ErrorType;
OffsetBindingPointer() : mOffset(0), mSize(0) { } OffsetBindingPointer() : mOffset(0), mSize(0) { }
void set(const Context *context, ObjectType *newObject) override void set(const ContextType *context, ObjectType *newObject) override
{ {
BindingPointer<ObjectType>::set(context, newObject); BindingPointer<ObjectType>::set(context, newObject);
mOffset = 0; mOffset = 0;
mSize = 0; mSize = 0;
} }
void set(const Context *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size) void set(const ContextType *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
{ {
BindingPointer<ObjectType>::set(context, newObject); BindingPointer<ObjectType>::set(context, newObject);
mOffset = offset; mOffset = offset;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment