Commit a11819de by Jamie Madill Committed by Commit Bot

Context: Use Observer pattern for container objects.

Container objects in this case are the Vertex Array and Read and Draw Framebuffers. Instead of using a mutable dirty bit state with a const function to notify of dirty bits we can use the Observer/Subject pattern. This more cleanly allows us to do cache updates. Bug: angleproject:1391 Change-Id: I88f863894ec3efa00322038f323a84850166107d Reviewed-on: https://chromium-review.googlesource.com/1153399Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarFrank Henigman <fjhenigman@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 08f1a3cd
......@@ -298,6 +298,9 @@ static_assert(static_cast<gl::PrimitiveMode>(10) == gl::PrimitiveMode::TriangleS
static_assert(static_cast<gl::PrimitiveMode>(11) == gl::PrimitiveMode::EnumCount,
"gl::PrimitiveMode enum values have changed, update kMinimumPrimitiveCounts.");
constexpr angle::SubjectIndex kVertexArraySubjectIndex = 0;
constexpr angle::SubjectIndex kReadFramebufferSubjectIndex = 1;
constexpr angle::SubjectIndex kDrawFramebufferSubjectIndex = 2;
} // anonymous namespace
namespace gl
......@@ -347,6 +350,9 @@ Context::Context(rx::EGLImplFactory *implFactory,
mWebGLContext(GetWebGLContext(attribs)),
mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
mMemoryProgramCache(memoryProgramCache),
mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
mScratchBuffer(1000u),
mZeroFilledBuffer(1000u)
{
......@@ -634,15 +640,15 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
// Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr.
{
mState.mFramebuffers->setDefaultFramebuffer(newDefault);
if (mGLState.getReadFramebuffer() == nullptr)
{
mGLState.setReadFramebufferBinding(newDefault);
bindReadFramebuffer(0);
}
if (mGLState.getDrawFramebuffer() == nullptr)
{
mGLState.setDrawFramebufferBinding(newDefault);
bindDrawFramebuffer(0);
}
mState.mFramebuffers->setDefaultFramebuffer(newDefault);
}
// Notify the renderer of a context switch
......@@ -658,11 +664,13 @@ egl::Error Context::releaseSurface(const egl::Display *display)
if (mGLState.getReadFramebuffer() == defaultFramebuffer)
{
mGLState.setReadFramebufferBinding(nullptr);
mReadFramebufferObserverBinding.bind(nullptr);
}
if (mGLState.getDrawFramebuffer() == defaultFramebuffer)
{
mGLState.setDrawFramebufferBinding(nullptr);
mDrawFramebufferObserverBinding.bind(nullptr);
}
if (defaultFramebuffer)
......@@ -1083,6 +1091,7 @@ void Context::bindReadFramebuffer(GLuint framebufferHandle)
Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
mImplementation.get(), mCaps, framebufferHandle);
mGLState.setReadFramebufferBinding(framebuffer);
mReadFramebufferObserverBinding.bind(framebuffer);
}
void Context::bindDrawFramebuffer(GLuint framebufferHandle)
......@@ -1090,12 +1099,14 @@ void Context::bindDrawFramebuffer(GLuint framebufferHandle)
Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
mImplementation.get(), mCaps, framebufferHandle);
mGLState.setDrawFramebufferBinding(framebuffer);
mDrawFramebufferObserverBinding.bind(framebuffer);
}
void Context::bindVertexArray(GLuint vertexArrayHandle)
{
VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
mGLState.setVertexArrayBinding(this, vertexArray);
mVertexArrayObserverBinding.bind(vertexArray);
mStateCache.updateActiveAttribsMask(this);
}
......@@ -7547,6 +7558,31 @@ bool Context::isGLES1() const
return mState.getClientVersion() < Version(2, 0);
}
void Context::onSubjectStateChange(const Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message)
{
ASSERT(message == angle::SubjectMessage::CONTENTS_CHANGED);
switch (index)
{
case kVertexArraySubjectIndex:
mGLState.setObjectDirty(GL_VERTEX_ARRAY);
break;
case kReadFramebufferSubjectIndex:
mGLState.setObjectDirty(GL_READ_FRAMEBUFFER);
break;
case kDrawFramebufferSubjectIndex:
mGLState.setObjectDirty(GL_DRAW_FRAMEBUFFER);
break;
default:
UNREACHABLE();
break;
}
}
// ErrorSet implementation.
ErrorSet::ErrorSet(Context *context) : mContext(context)
{
......
......@@ -107,7 +107,7 @@ class StateCache final : angle::NonCopyable
bool mCachedHasAnyEnabledClientAttrib;
};
class Context final : public egl::LabeledObject, angle::NonCopyable
class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface
{
public:
Context(rx::EGLImplFactory *implFactory,
......@@ -1521,6 +1521,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
const StateCache &getStateCache() const { return mStateCache; }
void onSubjectStateChange(const Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
private:
void initialize();
......@@ -1658,6 +1662,11 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
Workarounds mWorkarounds;
// Binding to container objects that use dependent state updates.
angle::ObserverBinding mVertexArrayObserverBinding;
angle::ObserverBinding mDrawFramebufferObserverBinding;
angle::ObserverBinding mReadFramebufferObserverBinding;
// Not really a property of context state. The size and contexts change per-api-call.
mutable angle::ScratchBuffer mScratchBuffer;
mutable angle::ScratchBuffer mZeroFilledBuffer;
......
......@@ -1851,7 +1851,7 @@ void Framebuffer::onSubjectStateChange(const Context *context,
{
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
mDirtyBits.set(index);
context->getGLState().setFramebufferDirty(this);
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return;
}
......
......@@ -138,7 +138,9 @@ class FramebufferState final : angle::NonCopyable
angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
};
class Framebuffer final : public angle::ObserverInterface, public LabeledObject
class Framebuffer final : public angle::ObserverInterface,
public LabeledObject,
public angle::Subject
{
public:
// Constructor to build application-defined framebuffers
......
......@@ -2794,26 +2794,6 @@ void State::setObjectDirty(GLenum target)
}
}
void State::setFramebufferDirty(const Framebuffer *framebuffer) const
{
if (framebuffer == mReadFramebuffer)
{
mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
}
if (framebuffer == mDrawFramebuffer)
{
mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
}
}
void State::setVertexArrayDirty(const VertexArray *vertexArray) const
{
if (vertexArray == mVertexArray)
{
mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
}
}
void State::onProgramExecutableChange(Program *program)
{
// OpenGL Spec:
......
......@@ -453,8 +453,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
Error syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(GLenum target);
void setFramebufferDirty(const Framebuffer *framebuffer) const;
void setVertexArrayDirty(const VertexArray *vertexArray) const;
// This actually clears the current value dirty bits.
// TODO(jmadill): Pass mutable dirty bits into Impl.
......@@ -621,7 +619,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable
GLES1State mGLES1State;
DirtyBits mDirtyBits;
mutable DirtyObjects mDirtyObjects;
DirtyObjects mDirtyObjects;
mutable AttributesMask mDirtyCurrentValues;
};
......
......@@ -438,7 +438,7 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context,
DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
mDirtyBits.set(dirtyBit);
context->getGLState().setVertexArrayDirty(this);
onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
}
void VertexArray::updateObserverBinding(size_t bindingIndex)
......
......@@ -88,7 +88,9 @@ class VertexArrayState final : angle::NonCopyable
gl::AttributesMask mNullPointerClientMemoryAttribsMask;
};
class VertexArray final : public angle::ObserverInterface, public LabeledObject
class VertexArray final : public angle::ObserverInterface,
public LabeledObject,
public angle::Subject
{
public:
VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings);
......
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