Commit ca49e6dc by Geoff Lang Committed by Commit Bot

Reset the default framebuffer if ContextImpl::onMakeCurrent fails.

Context has the invariant that if it is not current anywhere, mCurrentSuface is null. If makeCurrent fails in ContextImpl::onMakeCurrent, the surface is not reset, breaking this invariant. BUG=angleproject:3414 Change-Id: Icb13c8e2d1edd98d87a8af091a3fbacebadb395c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1592064Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 3c6a36b0
...@@ -605,68 +605,24 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface) ...@@ -605,68 +605,24 @@ egl::Error Context::makeCurrent(egl::Display *display, egl::Surface *surface)
mState.setAllDirtyBits(); mState.setAllDirtyBits();
mState.setAllDirtyObjects(); mState.setAllDirtyObjects();
ASSERT(mCurrentSurface == nullptr); ANGLE_TRY(setDefaultFramebuffer(surface));
Framebuffer *newDefault = nullptr; // Notify the renderer of a context switch.
if (surface != nullptr) angle::Result implResult = mImplementation->onMakeCurrent(this);
{
ANGLE_TRY(surface->setIsCurrent(this, true));
mCurrentSurface = surface;
newDefault = surface->createDefaultFramebuffer(this);
}
else
{
newDefault = new Framebuffer(mImplementation.get());
}
// Update default framebuffer, the binding of the previous default // If the implementation fails onMakeCurrent, unset the default framebuffer.
// framebuffer (or lack of) will have a nullptr. if (implResult != angle::Result::Continue)
{ {
mState.mFramebufferManager->setDefaultFramebuffer(newDefault); ANGLE_TRY(unsetDefaultFramebuffer());
if (mState.getReadFramebuffer() == nullptr) return angle::ResultToEGL(implResult);
{
bindReadFramebuffer(0);
}
if (mState.getDrawFramebuffer() == nullptr)
{
bindDrawFramebuffer(0);
}
} }
// Notify the renderer of a context switch. return egl::NoError();
return angle::ResultToEGL(mImplementation->onMakeCurrent(this));
} }
egl::Error Context::unMakeCurrent(const egl::Display *display) egl::Error Context::unMakeCurrent(const egl::Display *display)
{ {
gl::Framebuffer *defaultFramebuffer = mState.mFramebufferManager->getFramebuffer(0); ANGLE_TRY(unsetDefaultFramebuffer());
// Remove the default framebuffer
if (mState.getReadFramebuffer() == defaultFramebuffer)
{
mState.setReadFramebufferBinding(nullptr);
mReadFramebufferObserverBinding.bind(nullptr);
}
if (mState.getDrawFramebuffer() == defaultFramebuffer)
{
mState.setDrawFramebufferBinding(nullptr);
mDrawFramebufferObserverBinding.bind(nullptr);
}
if (defaultFramebuffer)
{
defaultFramebuffer->onDestroy(this);
delete defaultFramebuffer;
}
mState.mFramebufferManager->setDefaultFramebuffer(nullptr);
if (mCurrentSurface)
{
ANGLE_TRY(mCurrentSurface->setIsCurrent(this, false));
mCurrentSurface = nullptr;
}
return angle::ResultToEGL(mImplementation->onUnMakeCurrent(this)); return angle::ResultToEGL(mImplementation->onUnMakeCurrent(this));
} }
...@@ -8235,6 +8191,75 @@ angle::Result Context::onProgramLink(Program *programObject) ...@@ -8235,6 +8191,75 @@ angle::Result Context::onProgramLink(Program *programObject)
return angle::Result::Continue; return angle::Result::Continue;
} }
egl::Error Context::setDefaultFramebuffer(egl::Surface *surface)
{
ASSERT(mCurrentSurface == nullptr);
Framebuffer *newDefault = nullptr;
if (surface != nullptr)
{
ANGLE_TRY(surface->setIsCurrent(this, true));
mCurrentSurface = surface;
newDefault = surface->createDefaultFramebuffer(this);
}
else
{
newDefault = new Framebuffer(mImplementation.get());
}
// Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr.
{
mState.mFramebufferManager->setDefaultFramebuffer(newDefault);
if (mState.getReadFramebuffer() == nullptr)
{
bindReadFramebuffer(0);
}
if (mState.getDrawFramebuffer() == nullptr)
{
bindDrawFramebuffer(0);
}
}
return egl::NoError();
}
egl::Error Context::unsetDefaultFramebuffer()
{
gl::Framebuffer *defaultFramebuffer = mState.mFramebufferManager->getFramebuffer(0);
// Remove the default framebuffer
if (mState.getReadFramebuffer() == defaultFramebuffer)
{
mState.setReadFramebufferBinding(nullptr);
mReadFramebufferObserverBinding.bind(nullptr);
}
if (mState.getDrawFramebuffer() == defaultFramebuffer)
{
mState.setDrawFramebufferBinding(nullptr);
mDrawFramebufferObserverBinding.bind(nullptr);
}
if (defaultFramebuffer)
{
defaultFramebuffer->onDestroy(this);
delete defaultFramebuffer;
}
mState.mFramebufferManager->setDefaultFramebuffer(nullptr);
// Always unset the current surface, even if setIsCurrent fails.
egl::Surface *surface = mCurrentSurface;
mCurrentSurface = nullptr;
if (surface)
{
ANGLE_TRY(surface->setIsCurrent(this, false));
}
return egl::NoError();
}
// ErrorSet implementation. // ErrorSet implementation.
ErrorSet::ErrorSet(Context *context) : mContext(context) {} ErrorSet::ErrorSet(Context *context) : mContext(context) {}
......
...@@ -1914,6 +1914,9 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl ...@@ -1914,6 +1914,9 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
// A small helper method to facilitate using the ANGLE_CONTEXT_TRY macro. // A small helper method to facilitate using the ANGLE_CONTEXT_TRY macro.
void tryGenPaths(GLsizei range, GLuint *createdOut); void tryGenPaths(GLsizei range, GLuint *createdOut);
egl::Error setDefaultFramebuffer(egl::Surface *surface);
egl::Error unsetDefaultFramebuffer();
void initRendererString(); void initRendererString();
void initVersionStrings(); void initVersionStrings();
void initExtensionStrings(); void initExtensionStrings();
......
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