Commit 2dabb4a3 by Geoff Lang Committed by Commit Bot

Make a context current when destroying it.

The destructors of objects in a context assume that the context is current during destruction. If another context is current at this time, they can delete objects from other contexts. BUG=angleproject:2464 Change-Id: I813d092cc7f33a39c814edae5baa433733b4590c Reviewed-on: https://chromium-review.googlesource.com/1083371 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 9d69dd96
......@@ -1417,6 +1417,7 @@ class Context final : public egl::LabeledObject, angle::NonCopyable
// Notification for a state change in a Texture.
void onTextureChange(const Texture *texture);
bool hasBeenCurrent() const { return mHasBeenCurrent; }
egl::Display *getCurrentDisplay() const { return mCurrentDisplay; }
egl::Surface *getCurrentDrawSurface() const { return mCurrentSurface; }
egl::Surface *getCurrentReadSurface() const { return mCurrentSurface; }
......
......@@ -29,6 +29,7 @@
#include "libANGLE/ResourceManager.h"
#include "libANGLE/Stream.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Thread.h"
#include "libANGLE/histogram_macros.h"
#include "libANGLE/renderer/DeviceImpl.h"
#include "libANGLE/renderer/DisplayImpl.h"
......@@ -542,22 +543,22 @@ Error Display::initialize()
return NoError();
}
Error Display::terminate()
Error Display::terminate(const Thread *thread)
{
if (!mInitialized)
{
return NoError();
}
ANGLE_TRY(makeCurrent(nullptr, nullptr, nullptr));
mMemoryProgramCache.clear();
while (!mContextSet.empty())
{
ANGLE_TRY(destroyContext(*mContextSet.begin()));
ANGLE_TRY(destroyContext(thread, *mContextSet.begin()));
}
ANGLE_TRY(makeCurrent(nullptr, nullptr, nullptr));
// The global texture manager should be deleted with the last context that uses it.
ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
......@@ -885,8 +886,18 @@ void Display::destroyStream(egl::Stream *stream)
SafeDelete(stream);
}
Error Display::destroyContext(gl::Context *context)
Error Display::destroyContext(const Thread *thread, gl::Context *context)
{
gl::Context *currentContext = thread->getContext();
bool changeContextForDeletion = context != currentContext;
// Make the context being deleted current during it's deletion. This allows it to delete any
// resources it's holding.
if (changeContextForDeletion)
{
ANGLE_TRY(makeCurrent(nullptr, nullptr, context));
}
if (context->usingDisplayTextureShareGroup())
{
ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
......@@ -903,6 +914,14 @@ Error Display::destroyContext(gl::Context *context)
ANGLE_TRY(context->onDestroy(this));
mContextSet.erase(context);
SafeDelete(context);
// Set the previous context back to current
if (changeContextForDeletion)
{
ANGLE_TRY(makeCurrent(thread->getCurrentDrawSurface(), thread->getCurrentReadSurface(),
currentContext));
}
return NoError();
}
......
......@@ -65,7 +65,7 @@ class Display final : public LabeledObject, angle::NonCopyable
EGLLabelKHR getLabel() const override;
Error initialize();
Error terminate();
Error terminate(const Thread *thread);
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
......@@ -111,7 +111,7 @@ class Display final : public LabeledObject, angle::NonCopyable
Error destroySurface(Surface *surface);
void destroyImage(Image *image);
void destroyStream(Stream *stream);
Error destroyContext(gl::Context *context);
Error destroyContext(const Thread *thread, gl::Context *context);
bool isInitialized() const;
bool isValidConfig(const Config *config) const;
......
......@@ -116,7 +116,7 @@ EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
thread->setCurrent(nullptr);
}
Error error = display->terminate();
Error error = display->terminate(thread);
if (error.isError())
{
thread->setError(error, GetDebug(), "eglTerminate", GetDisplayIfValid(display));
......@@ -471,12 +471,9 @@ EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
return EGL_FALSE;
}
if (context == thread->getContext())
{
thread->setCurrent(nullptr);
}
bool contextWasCurrent = context == thread->getContext();
error = display->destroyContext(context);
error = display->destroyContext(thread, context);
if (error.isError())
{
thread->setError(error, GetDebug(), "eglDestroyContext",
......@@ -484,6 +481,11 @@ EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
return EGL_FALSE;
}
if (contextWasCurrent)
{
thread->setCurrent(nullptr);
}
thread->setSuccess();
return EGL_TRUE;
}
......
......@@ -160,7 +160,7 @@
2546 WIN : dEQP-EGL.functional.reusable_sync.invalid.* = SKIP
2546 WIN : dEQP-EGL.functional.color_clears.multi_thread.* = FAIL
2546 WIN : dEQP-EGL.functional.query_surface.simple.pbuffer.rgba8888_depth_stencil = FAIL
2546 WIN : dEQP-EGL.functional.thread_cleanup.* = FAIL
2546 WIN : dEQP-EGL.functional.thread_cleanup.* = SKIP
// Linux failures
2546 LINUX : dEQP-EGL.functional.color_clears.multi_context.gles1.rgba8888_pixmap = SKIP
......
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