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)
mState.setAllDirtyBits();
mState.setAllDirtyObjects();
ASSERT(mCurrentSurface == nullptr);
ANGLE_TRY(setDefaultFramebuffer(surface));
Framebuffer *newDefault = nullptr;
if (surface != nullptr)
{
ANGLE_TRY(surface->setIsCurrent(this, true));
mCurrentSurface = surface;
newDefault = surface->createDefaultFramebuffer(this);
}
else
{
newDefault = new Framebuffer(mImplementation.get());
}
// Notify the renderer of a context switch.
angle::Result implResult = mImplementation->onMakeCurrent(this);
// Update default framebuffer, the binding of the previous default
// framebuffer (or lack of) will have a nullptr.
// If the implementation fails onMakeCurrent, unset the default framebuffer.
if (implResult != angle::Result::Continue)
{
mState.mFramebufferManager->setDefaultFramebuffer(newDefault);
if (mState.getReadFramebuffer() == nullptr)
{
bindReadFramebuffer(0);
}
if (mState.getDrawFramebuffer() == nullptr)
{
bindDrawFramebuffer(0);
}
ANGLE_TRY(unsetDefaultFramebuffer());
return angle::ResultToEGL(implResult);
}
// Notify the renderer of a context switch.
return angle::ResultToEGL(mImplementation->onMakeCurrent(this));
return egl::NoError();
}
egl::Error Context::unMakeCurrent(const egl::Display *display)
{
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);
if (mCurrentSurface)
{
ANGLE_TRY(mCurrentSurface->setIsCurrent(this, false));
mCurrentSurface = nullptr;
}
ANGLE_TRY(unsetDefaultFramebuffer());
return angle::ResultToEGL(mImplementation->onUnMakeCurrent(this));
}
......@@ -8235,6 +8191,75 @@ angle::Result Context::onProgramLink(Program *programObject)
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::ErrorSet(Context *context) : mContext(context) {}
......
......@@ -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.
void tryGenPaths(GLsizei range, GLuint *createdOut);
egl::Error setDefaultFramebuffer(egl::Surface *surface);
egl::Error unsetDefaultFramebuffer();
void initRendererString();
void initVersionStrings();
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