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/1153399
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Frank Henigman <fjhenigman@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index 4c9d49d..578ee3d 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -298,6 +298,9 @@
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 @@
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 @@
// 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 @@
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 @@
Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
mImplementation.get(), mCaps, framebufferHandle);
mGLState.setReadFramebufferBinding(framebuffer);
+ mReadFramebufferObserverBinding.bind(framebuffer);
}
void Context::bindDrawFramebuffer(GLuint framebufferHandle)
@@ -1090,12 +1099,14 @@
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 @@
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)
{