Commit 3c8f6094 by Jonah Ryan-Davis Committed by Commit Bot

EGL: Add basic multithreading support

Adds first step to allowing multithreaded contexts: letting multiple threads use ANGLE as long as only one thread has a current context at a time. Bug: angleproject:4724 Bug: angleproject:4725 Change-Id: I4f606bdb15386cff9e3cb84d4120781e24e15fe4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2269864Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
parent acbe145c
......@@ -278,6 +278,8 @@ void DisplayEGL::terminate()
mRenderer.reset();
mCurrentNativeContexts.clear();
egl::Error result = mEGL->terminate();
if (result.isError())
{
......@@ -554,6 +556,8 @@ egl::Error DisplayEGL::makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context)
{
CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()];
EGLSurface newSurface = EGL_NO_SURFACE;
if (drawSurface)
{
......@@ -568,9 +572,14 @@ egl::Error DisplayEGL::makeCurrent(egl::Surface *drawSurface,
newContext = contextEGL->getContext();
}
if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
if (newSurface != currentContext.surface || newContext != currentContext.context)
{
return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
{
return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
}
currentContext.surface = newSurface;
currentContext.context = newContext;
}
return DisplayGL::makeCurrent(drawSurface, readSurface, context);
......@@ -583,6 +592,17 @@ gl::Version DisplayEGL::getMaxSupportedESVersion() const
void DisplayEGL::destroyNativeContext(EGLContext context)
{
// If this context is current, remove it from the tracking of current contexts to make sure we
// don't try to make it current again.
for (auto &currentContext : mCurrentNativeContexts)
{
if (currentContext.second.context == context)
{
currentContext.second.surface = EGL_NO_SURFACE;
currentContext.second.context = EGL_NO_CONTEXT;
}
}
mEGL->destroyContext(context);
}
......@@ -689,6 +709,10 @@ egl::Error DisplayEGL::createRenderer(EGLContext shareContext,
<< "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
}
CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()];
currentContext.surface = EGL_NO_SURFACE;
currentContext.context = context;
std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
functionsGL->initialize(mDisplayAttributes);
......
......@@ -11,6 +11,7 @@
#include <map>
#include <string>
#include <thread>
#include <vector>
#include "libANGLE/renderer/gl/DisplayGL.h"
......@@ -128,6 +129,13 @@ class DisplayEGL : public DisplayGL
egl::AttributeMap mDisplayAttributes;
std::vector<EGLint> mConfigAttribList;
struct CurrentNativeContext
{
EGLSurface surface = EGL_NO_SURFACE;
EGLContext context = EGL_NO_CONTEXT;
};
std::unordered_map<std::thread::id, CurrentNativeContext> mCurrentNativeContexts;
private:
void generateCaps(egl::Caps *outCaps) const override;
......
......@@ -188,7 +188,6 @@ void DisplayAndroid::terminate()
}
mRenderer.reset();
mCurrentNativeContext.clear();
egl::Error result = mEGL->terminate();
if (result.isError())
......@@ -273,7 +272,7 @@ egl::Error DisplayAndroid::makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context)
{
CurrentNativeContext &currentContext = mCurrentNativeContext[std::this_thread::get_id()];
CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()];
EGLSurface newSurface = EGL_NO_SURFACE;
if (drawSurface)
......@@ -331,17 +330,6 @@ egl::Error DisplayAndroid::makeCurrent(egl::Surface *drawSurface,
void DisplayAndroid::destroyNativeContext(EGLContext context)
{
DisplayEGL::destroyNativeContext(context);
// If this context is current, remove it from the tracking of current contexts to make sure we
// don't try to make it current again.
for (auto &currentContext : mCurrentNativeContext)
{
if (currentContext.second.context == context)
{
currentContext.second.surface = EGL_NO_SURFACE;
currentContext.second.context = EGL_NO_CONTEXT;
}
}
}
void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) const
......@@ -373,7 +361,7 @@ egl::Error DisplayAndroid::createRenderer(EGLContext shareContext,
outRenderer->reset(
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
CurrentNativeContext &currentContext = mCurrentNativeContext[std::this_thread::get_id()];
CurrentNativeContext &currentContext = mCurrentNativeContexts[std::this_thread::get_id()];
if (makeNewContextCurrent)
{
currentContext.surface = mDummyPbuffer;
......
......@@ -11,7 +11,6 @@
#include <map>
#include <string>
#include <thread>
#include <vector>
#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
......@@ -69,13 +68,6 @@ class DisplayAndroid : public DisplayEGL
bool mSupportsSurfaceless;
EGLSurface mDummyPbuffer;
struct CurrentNativeContext
{
EGLSurface surface = EGL_NO_SURFACE;
EGLContext context = EGL_NO_CONTEXT;
};
std::unordered_map<std::thread::id, CurrentNativeContext> mCurrentNativeContext;
};
} // namespace rx
......
......@@ -205,7 +205,7 @@ TEST_P(MultithreadingTest, MultiContextDraw)
TEST_P(MultithreadingTest, MultiCreateContext)
{
// Supported by CGL, GLX, and WGL (https://anglebug.com/4725)
ANGLE_SKIP_TEST_IF(!(IsWindows() || (IsLinux() && !IsOzone()) || IsOSX()));
ANGLE_SKIP_TEST_IF(!(IsWindows() || IsLinux() || IsOSX()));
EGLWindow *window = getEGLWindow();
EGLDisplay dpy = window->getDisplay();
......
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