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 ...@@ -298,6 +298,9 @@ static_assert(static_cast<gl::PrimitiveMode>(10) == gl::PrimitiveMode::TriangleS
static_assert(static_cast<gl::PrimitiveMode>(11) == gl::PrimitiveMode::EnumCount, static_assert(static_cast<gl::PrimitiveMode>(11) == gl::PrimitiveMode::EnumCount,
"gl::PrimitiveMode enum values have changed, update kMinimumPrimitiveCounts."); "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 } // anonymous namespace
namespace gl namespace gl
...@@ -347,6 +350,9 @@ Context::Context(rx::EGLImplFactory *implFactory, ...@@ -347,6 +350,9 @@ Context::Context(rx::EGLImplFactory *implFactory,
mWebGLContext(GetWebGLContext(attribs)), mWebGLContext(GetWebGLContext(attribs)),
mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)), mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
mMemoryProgramCache(memoryProgramCache), mMemoryProgramCache(memoryProgramCache),
mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
mScratchBuffer(1000u), mScratchBuffer(1000u),
mZeroFilledBuffer(1000u) mZeroFilledBuffer(1000u)
{ {
...@@ -634,15 +640,15 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface) ...@@ -634,15 +640,15 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
// Update default framebuffer, the binding of the previous default // Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr. // framebuffer (or lack of) will have a nullptr.
{ {
mState.mFramebuffers->setDefaultFramebuffer(newDefault);
if (mGLState.getReadFramebuffer() == nullptr) if (mGLState.getReadFramebuffer() == nullptr)
{ {
mGLState.setReadFramebufferBinding(newDefault); bindReadFramebuffer(0);
} }
if (mGLState.getDrawFramebuffer() == nullptr) if (mGLState.getDrawFramebuffer() == nullptr)
{ {
mGLState.setDrawFramebufferBinding(newDefault); bindDrawFramebuffer(0);
} }
mState.mFramebuffers->setDefaultFramebuffer(newDefault);
} }
// Notify the renderer of a context switch // Notify the renderer of a context switch
...@@ -658,11 +664,13 @@ egl::Error Context::releaseSurface(const egl::Display *display) ...@@ -658,11 +664,13 @@ egl::Error Context::releaseSurface(const egl::Display *display)
if (mGLState.getReadFramebuffer() == defaultFramebuffer) if (mGLState.getReadFramebuffer() == defaultFramebuffer)
{ {
mGLState.setReadFramebufferBinding(nullptr); mGLState.setReadFramebufferBinding(nullptr);
mReadFramebufferObserverBinding.bind(nullptr);
} }
if (mGLState.getDrawFramebuffer() == defaultFramebuffer) if (mGLState.getDrawFramebuffer() == defaultFramebuffer)
{ {
mGLState.setDrawFramebufferBinding(nullptr); mGLState.setDrawFramebufferBinding(nullptr);
mDrawFramebufferObserverBinding.bind(nullptr);
} }
if (defaultFramebuffer) if (defaultFramebuffer)
...@@ -1083,6 +1091,7 @@ void Context::bindReadFramebuffer(GLuint framebufferHandle) ...@@ -1083,6 +1091,7 @@ void Context::bindReadFramebuffer(GLuint framebufferHandle)
Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation( Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
mImplementation.get(), mCaps, framebufferHandle); mImplementation.get(), mCaps, framebufferHandle);
mGLState.setReadFramebufferBinding(framebuffer); mGLState.setReadFramebufferBinding(framebuffer);
mReadFramebufferObserverBinding.bind(framebuffer);
} }
void Context::bindDrawFramebuffer(GLuint framebufferHandle) void Context::bindDrawFramebuffer(GLuint framebufferHandle)
...@@ -1090,12 +1099,14 @@ void Context::bindDrawFramebuffer(GLuint framebufferHandle) ...@@ -1090,12 +1099,14 @@ void Context::bindDrawFramebuffer(GLuint framebufferHandle)
Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation( Framebuffer *framebuffer = mState.mFramebuffers->checkFramebufferAllocation(
mImplementation.get(), mCaps, framebufferHandle); mImplementation.get(), mCaps, framebufferHandle);
mGLState.setDrawFramebufferBinding(framebuffer); mGLState.setDrawFramebufferBinding(framebuffer);
mDrawFramebufferObserverBinding.bind(framebuffer);
} }
void Context::bindVertexArray(GLuint vertexArrayHandle) void Context::bindVertexArray(GLuint vertexArrayHandle)
{ {
VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle); VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
mGLState.setVertexArrayBinding(this, vertexArray); mGLState.setVertexArrayBinding(this, vertexArray);
mVertexArrayObserverBinding.bind(vertexArray);
mStateCache.updateActiveAttribsMask(this); mStateCache.updateActiveAttribsMask(this);
} }
...@@ -7547,6 +7558,31 @@ bool Context::isGLES1() const ...@@ -7547,6 +7558,31 @@ bool Context::isGLES1() const
return mState.getClientVersion() < Version(2, 0); 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 implementation.
ErrorSet::ErrorSet(Context *context) : mContext(context) ErrorSet::ErrorSet(Context *context) : mContext(context)
{ {
......
...@@ -107,7 +107,7 @@ class StateCache final : angle::NonCopyable ...@@ -107,7 +107,7 @@ class StateCache final : angle::NonCopyable
bool mCachedHasAnyEnabledClientAttrib; bool mCachedHasAnyEnabledClientAttrib;
}; };
class Context final : public egl::LabeledObject, angle::NonCopyable class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface
{ {
public: public:
Context(rx::EGLImplFactory *implFactory, Context(rx::EGLImplFactory *implFactory,
...@@ -1521,6 +1521,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1521,6 +1521,10 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
const StateCache &getStateCache() const { return mStateCache; } const StateCache &getStateCache() const { return mStateCache; }
void onSubjectStateChange(const Context *context,
angle::SubjectIndex index,
angle::SubjectMessage message) override;
private: private:
void initialize(); void initialize();
...@@ -1658,6 +1662,11 @@ class Context final : public egl::LabeledObject, angle::NonCopyable ...@@ -1658,6 +1662,11 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
Workarounds mWorkarounds; 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. // Not really a property of context state. The size and contexts change per-api-call.
mutable angle::ScratchBuffer mScratchBuffer; mutable angle::ScratchBuffer mScratchBuffer;
mutable angle::ScratchBuffer mZeroFilledBuffer; mutable angle::ScratchBuffer mZeroFilledBuffer;
......
...@@ -1851,7 +1851,7 @@ void Framebuffer::onSubjectStateChange(const Context *context, ...@@ -1851,7 +1851,7 @@ void Framebuffer::onSubjectStateChange(const Context *context,
{ {
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index)); ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
mDirtyBits.set(index); mDirtyBits.set(index);
context->getGLState().setFramebufferDirty(this); onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
return; return;
} }
......
...@@ -138,7 +138,9 @@ class FramebufferState final : angle::NonCopyable ...@@ -138,7 +138,9 @@ class FramebufferState final : angle::NonCopyable
angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit; 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: public:
// Constructor to build application-defined framebuffers // Constructor to build application-defined framebuffers
......
...@@ -2794,26 +2794,6 @@ void State::setObjectDirty(GLenum target) ...@@ -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) void State::onProgramExecutableChange(Program *program)
{ {
// OpenGL Spec: // OpenGL Spec:
......
...@@ -453,8 +453,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -453,8 +453,6 @@ class State : public angle::ObserverInterface, angle::NonCopyable
Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset); Error syncDirtyObjects(const Context *context, const DirtyObjects &bitset);
Error syncDirtyObject(const Context *context, GLenum target); Error syncDirtyObject(const Context *context, GLenum target);
void setObjectDirty(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. // This actually clears the current value dirty bits.
// TODO(jmadill): Pass mutable dirty bits into Impl. // TODO(jmadill): Pass mutable dirty bits into Impl.
...@@ -621,7 +619,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable ...@@ -621,7 +619,7 @@ class State : public angle::ObserverInterface, angle::NonCopyable
GLES1State mGLES1State; GLES1State mGLES1State;
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
mutable DirtyObjects mDirtyObjects; DirtyObjects mDirtyObjects;
mutable AttributesMask mDirtyCurrentValues; mutable AttributesMask mDirtyCurrentValues;
}; };
......
...@@ -438,7 +438,7 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context, ...@@ -438,7 +438,7 @@ void VertexArray::setDependentDirtyBit(const gl::Context *context,
DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index); DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit)); ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
mDirtyBits.set(dirtyBit); mDirtyBits.set(dirtyBit);
context->getGLState().setVertexArrayDirty(this); onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
} }
void VertexArray::updateObserverBinding(size_t bindingIndex) void VertexArray::updateObserverBinding(size_t bindingIndex)
......
...@@ -88,7 +88,9 @@ class VertexArrayState final : angle::NonCopyable ...@@ -88,7 +88,9 @@ class VertexArrayState final : angle::NonCopyable
gl::AttributesMask mNullPointerClientMemoryAttribsMask; gl::AttributesMask mNullPointerClientMemoryAttribsMask;
}; };
class VertexArray final : public angle::ObserverInterface, public LabeledObject class VertexArray final : public angle::ObserverInterface,
public LabeledObject,
public angle::Subject
{ {
public: public:
VertexArray(rx::GLImplFactory *factory, GLuint id, size_t maxAttribs, size_t maxAttribBindings); 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