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
bool operator==(const Error &other) const;
bool operator!=(const Error &other) const;
static inline Error NoError();
private:
void createMessageString() const;
......@@ -140,7 +142,7 @@ using InvalidFramebufferOperation = priv::ErrorStream<GL_INVALID_FRAMEBUFFER_OPE
inline Error NoError()
{
return Error(GL_NO_ERROR);
return Error::NoError();
}
using LinkResult = ErrorOrResult<bool>;
......@@ -173,6 +175,8 @@ class ANGLE_NO_DISCARD Error final
const std::string &getMessage() const;
static inline Error NoError();
private:
void createMessageString() const;
......@@ -214,7 +218,7 @@ using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>;
inline Error NoError()
{
return Error(EGL_SUCCESS);
return Error::NoError();
}
} // namespace egl
......
......@@ -97,6 +97,12 @@ bool Error::isError() const
return (mCode != GL_NO_ERROR);
}
// static
Error Error::NoError()
{
return Error(GL_NO_ERROR);
}
} // namespace gl
namespace egl
......@@ -186,4 +192,10 @@ bool Error::isError() const
return (mCode != EGL_SUCCESS);
}
// Static
Error Error::NoError()
{
return Error(EGL_SUCCESS);
}
}
......@@ -18,35 +18,23 @@
#include <cstddef>
namespace gl
namespace angle
{
class Context;
class RefCountObjectNoID : angle::NonCopyable
template <typename ContextT, typename ErrorT>
class RefCountObject : angle::NonCopyable
{
public:
RefCountObjectNoID() : mRefCount(0) {}
virtual Error onDestroy(const Context *context);
void addRef() const { ++mRefCount; }
using ContextType = ContextT;
using ErrorType = ErrorT;
void release() const
{
ASSERT(mRefCount > 0);
RefCountObject() : mRefCount(0) {}
if (--mRefCount == 0)
{
delete this;
}
}
virtual ErrorType onDestroy(const ContextType *context) { return ErrorType::NoError(); }
size_t getRefCount() const { return mRefCount; }
protected:
virtual ~RefCountObjectNoID();
void addRef() const { ++mRefCount; }
// A specialized release method for objects which need a destroy context.
void release(const gl::Context *context)
void release(const ContextType *context)
{
ASSERT(mRefCount > 0);
if (--mRefCount == 0)
......@@ -56,54 +44,35 @@ class RefCountObjectNoID : angle::NonCopyable
}
}
template <class ObjectType>
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;
size_t getRefCount() const { return mRefCount; }
protected:
~RefCountObject() override {}
virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
private:
GLuint mId;
mutable size_t mRefCount;
};
template <class ObjectType>
template <class ObjectType, typename ContextT, typename ErrorT>
class BindingPointer
{
public:
using ContextType = ContextT;
using ErrorType = ErrorT;
BindingPointer()
: 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)
{
......@@ -111,7 +80,7 @@ class BindingPointer
}
}
BindingPointer &operator=(BindingPointer<ObjectType> &&other)
BindingPointer &operator=(BindingPointer &&other)
{
std::swap(mObject, other.mObject);
return *this;
......@@ -123,48 +92,96 @@ class BindingPointer
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.
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.
// Otherwise the object could still be referenced when its destructor is called.
ObjectType *oldObject = mObject;
mObject = newObject;
if (oldObject != nullptr)
reinterpret_cast<RefCountObjectNoID *>(oldObject)->release(context);
{
reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(oldObject)->release(context);
}
}
ObjectType *get() 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
{
return mObject == other.mObject;
}
bool operator!=(const BindingPointer<ObjectType> &other) const { return !(*this == other); }
bool operator!=(const BindingPointer &other) const { return !(*this == other); }
private:
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>
class OffsetBindingPointer : public BindingPointer<ObjectType>
class BindingPointer : public angle::BindingPointer<ObjectType, Context, Error>
{
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) { }
void set(const Context *context, ObjectType *newObject) override
void set(const ContextType *context, ObjectType *newObject) override
{
BindingPointer<ObjectType>::set(context, newObject);
mOffset = 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);
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