Commit 24ddc7a8 by Geoff Lang Committed by Commit Bot

WGL: Support unvirtualized contexts and unsafe multithreading.

When using unvirtualized contexts, DisplayWGL still creates a Renderer for managing any internal GL resources such as emulated back buffers for DXGISwapChainWindowSurfaceWGL or D3DTextureSurfaceWGL but also creates a new Renderer for each GL context. All created contexts share resources. BUG=angleproject:2464 Change-Id: I945502514079368e062beef70bed49c61ed44403 Reviewed-on: https://chromium-review.googlesource.com/1097459 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 5bdf8bd1
Name
ANGLE_platform_angle_context_virtualization
Name Strings
EGL_ANGLE_platform_angle_context_virtualization
Contributors
Geoff Lang, Google
Contacts
Geoff Lang, Google (geofflang 'at' chromium 'dot' org)
Status
Draft
Version
Version 1, 2018-06-11
Number
EGL Extension XXX
Extension Type
EGL client extension
Dependencies
Requires ANGLE_platform_angle.
Overview
This extension allows the client to request a Display that internally
virtualizes contexts. Requesting virtualized contexts may impact
performance or ability to render from multiple threads simultaneously.
New Types
None
New Procedures and Functions
None
New Tokens
Accepted as an attribute name in the <attrib_list> argument of
eglGetPlatformDisplayEXT:
EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
Additions to the EGL Specification
None.
New Behavior
To request a display that internally utilizes context virtualization,
use the attribute EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE.
EGL_TRUE enables context virtualization and EGL false disables it.
If it is set to EGL_DONT_CARE, the default setting depends on the
implementation. Any value other than these will result in an error.
The default value for EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE
is EGL_DONT_CARE. Display creation may fail if hardware limitations
prohibit the requested setting.
Issues
None
Revision History
Version 1, 2018-06-11 (Geoff Lang)
- Initial draft
...@@ -82,6 +82,11 @@ ...@@ -82,6 +82,11 @@
#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
#endif /* EGL_ANGLE_platform_angle_vulkan */ #endif /* EGL_ANGLE_platform_angle_vulkan */
#ifndef EGL_ANGLE_platform_angle_context_virtualization
#define EGL_ANGLE_platform_angle_context_virtualization 1
#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
#endif /* EGL_ANGLE_platform_angle_context_virtualization */
#ifndef EGL_ANGLE_x11_visual #ifndef EGL_ANGLE_x11_visual
#define EGL_ANGLE_x11_visual #define EGL_ANGLE_x11_visual
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3 #define EGL_X11_VISUAL_ID_ANGLE 0x33A3
......
...@@ -1389,13 +1389,14 @@ ClientExtensions::ClientExtensions() ...@@ -1389,13 +1389,14 @@ ClientExtensions::ClientExtensions()
platformANGLED3D(false), platformANGLED3D(false),
platformANGLEOpenGL(false), platformANGLEOpenGL(false),
platformANGLEVulkan(false), platformANGLEVulkan(false),
platformANGLEContextVirtualization(false),
deviceCreation(false), deviceCreation(false),
deviceCreationD3D11(false), deviceCreationD3D11(false),
x11Visual(false), x11Visual(false),
experimentalPresentPath(false), experimentalPresentPath(false),
clientGetAllProcAddresses(false), clientGetAllProcAddresses(false),
explicitContext(false), debug(false),
debug(false) explicitContext(false)
{ {
} }
...@@ -1406,22 +1407,23 @@ std::vector<std::string> ClientExtensions::getStrings() const ...@@ -1406,22 +1407,23 @@ std::vector<std::string> ClientExtensions::getStrings() const
std::vector<std::string> extensionStrings; std::vector<std::string> extensionStrings;
// clang-format off // clang-format off
// | Extension name | Supported flag | Output vector | // | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings); InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings); InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings); InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings); InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings); InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings); InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings); InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -813,6 +813,9 @@ struct ClientExtensions ...@@ -813,6 +813,9 @@ struct ClientExtensions
// EGL_ANGLE_platform_angle_vulkan // EGL_ANGLE_platform_angle_vulkan
bool platformANGLEVulkan; bool platformANGLEVulkan;
// EGL_ANGLE_platform_angle_context_virtualization
bool platformANGLEContextVirtualization;
// EGL_ANGLE_device_creation // EGL_ANGLE_device_creation
bool deviceCreation; bool deviceCreation;
...@@ -828,11 +831,11 @@ struct ClientExtensions ...@@ -828,11 +831,11 @@ struct ClientExtensions
// EGL_KHR_client_get_all_proc_addresses // EGL_KHR_client_get_all_proc_addresses
bool clientGetAllProcAddresses; bool clientGetAllProcAddresses;
// EGL_ANGLE_explicit_context
bool explicitContext;
// EGL_KHR_debug // EGL_KHR_debug
bool debug; bool debug;
// EGL_ANGLE_explicit_context
bool explicitContext;
}; };
} // namespace egl } // namespace egl
......
...@@ -1027,6 +1027,9 @@ static ClientExtensions GenerateClientExtensions() ...@@ -1027,6 +1027,9 @@ static ClientExtensions GenerateClientExtensions()
#if defined(ANGLE_ENABLE_OPENGL) #if defined(ANGLE_ENABLE_OPENGL)
extensions.platformANGLEOpenGL = true; extensions.platformANGLEOpenGL = true;
// Selecting context virtualization is currently only supported in the OpenGL backend.
extensions.platformANGLEContextVirtualization = true;
#endif #endif
#if defined(ANGLE_ENABLE_NULL) #if defined(ANGLE_ENABLE_NULL)
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "libANGLE/renderer/gl/wgl/RendererWGL.h" #include "libANGLE/renderer/gl/wgl/RendererWGL.h"
#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h" #include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h" #include "libANGLE/renderer/gl/wgl/wgl_utils.h"
#include "libANGLE/renderer/renderer_utils.h"
#include "platform/Platform.h" #include "platform/Platform.h"
...@@ -34,6 +35,9 @@ ...@@ -34,6 +35,9 @@
namespace rx namespace rx
{ {
// Use context virtualization by default because Chrome uses it.
static constexpr bool kDefaultWGLVirtualizedContexts = true;
class FunctionsGLWindows : public FunctionsGL class FunctionsGLWindows : public FunctionsGL
{ {
public: public:
...@@ -65,6 +69,7 @@ class FunctionsGLWindows : public FunctionsGL ...@@ -65,6 +69,7 @@ class FunctionsGLWindows : public FunctionsGL
DisplayWGL::DisplayWGL(const egl::DisplayState &state) DisplayWGL::DisplayWGL(const egl::DisplayState &state)
: DisplayGL(state), : DisplayGL(state),
mRenderer(nullptr), mRenderer(nullptr),
mVirtualizedContexts(kDefaultWGLVirtualizedContexts),
mCurrentData(), mCurrentData(),
mOpenGLModule(nullptr), mOpenGLModule(nullptr),
mFunctionsWGL(nullptr), mFunctionsWGL(nullptr),
...@@ -103,6 +108,9 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display) ...@@ -103,6 +108,9 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display)
{ {
mDisplayAttributes = display->getAttributeMap(); mDisplayAttributes = display->getAttributeMap();
mVirtualizedContexts =
ShouldUseVirtualizedContexts(mDisplayAttributes, kDefaultWGLVirtualizedContexts);
mOpenGLModule = LoadLibraryA("opengl32.dll"); mOpenGLModule = LoadLibraryA("opengl32.dll");
if (!mOpenGLModule) if (!mOpenGLModule)
{ {
...@@ -250,7 +258,7 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display) ...@@ -250,7 +258,7 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display)
<< "Failed to set the pixel format on the intermediate OpenGL window."; << "Failed to set the pixel format on the intermediate OpenGL window.";
} }
ANGLE_TRY(createRenderer(&mRenderer)); ANGLE_TRY(createRenderer(nullptr, true, &mRenderer));
const FunctionsGL *functionsGL = mRenderer->getFunctions(); const FunctionsGL *functionsGL = mRenderer->getFunctions();
mHasRobustness = functionsGL->getGraphicsResetStatus != nullptr; mHasRobustness = functionsGL->getGraphicsResetStatus != nullptr;
...@@ -439,7 +447,23 @@ SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state, ...@@ -439,7 +447,23 @@ SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
ContextImpl *DisplayWGL::createContext(const gl::ContextState &state) ContextImpl *DisplayWGL::createContext(const gl::ContextState &state)
{ {
return new ContextWGL(state, mRenderer); std::shared_ptr<RendererWGL> renderer;
if (mVirtualizedContexts)
{
renderer = mRenderer;
}
else
{
// Create a new renderer that shares with the Display-level one.
egl::Error error = createRenderer(mRenderer->getContext(), false, &renderer);
if (error.isError())
{
ERR() << "Failed to create a shared renderer: " << error.getMessage();
return nullptr;
}
}
return new ContextWGL(state, renderer);
} }
DeviceImpl *DisplayWGL::createDevice() DeviceImpl *DisplayWGL::createDevice()
...@@ -527,8 +551,11 @@ egl::ConfigSet DisplayWGL::generateConfigs() ...@@ -527,8 +551,11 @@ egl::ConfigSet DisplayWGL::generateConfigs()
bool DisplayWGL::testDeviceLost() bool DisplayWGL::testDeviceLost()
{ {
if (mHasRobustness) // Can only call Renderer::getResetStatus if we know that it's context is current. This is only
// guarenteed when we're using virtualized contexts.
if (mVirtualizedContexts && mHasRobustness)
{ {
ASSERT(mCurrentData.at(std::this_thread::get_id()).glrc == mRenderer->getContext());
return mRenderer->getResetStatus() != GL_NO_ERROR; return mRenderer->getResetStatus() != GL_NO_ERROR;
} }
...@@ -665,20 +692,45 @@ egl::Error DisplayWGL::makeCurrent(egl::Surface *drawSurface, ...@@ -665,20 +692,45 @@ egl::Error DisplayWGL::makeCurrent(egl::Surface *drawSurface,
{ {
CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()]; CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];
HDC newDC = currentContext.dc; HDC newDC = nullptr;
if (drawSurface) if (drawSurface)
{ {
SurfaceWGL *drawSurfaceWGL = GetImplAs<SurfaceWGL>(drawSurface); SurfaceWGL *drawSurfaceWGL = GetImplAs<SurfaceWGL>(drawSurface);
newDC = drawSurfaceWGL->getDC(); newDC = drawSurfaceWGL->getDC();
} }
HGLRC newContext = currentContext.glrc; HGLRC newContext = nullptr;
if (context) if (context)
{ {
ContextWGL *contextWGL = GetImplAs<ContextWGL>(context); ContextWGL *contextWGL = GetImplAs<ContextWGL>(context);
newContext = contextWGL->getContext(); newContext = contextWGL->getContext();
} }
// The context should never change when context virtualization is being used, even when a null
// context is being bound.
if (mVirtualizedContexts)
{
ASSERT(newContext == nullptr || currentContext.glrc == nullptr ||
newContext == currentContext.glrc);
newContext = mRenderer->getContext();
// When contexts are virtualized, only single-threaded rendering is supported. This allows
// us to leave the previous surface bound if a null surface is being bound and emulate the
// surfaceless functionality because we know that this surface can not be made current on
// another thread.
if (newDC == nullptr)
{
newDC = currentContext.dc;
}
}
// WGL sometimes fails to make current a null DC even though it should support surfaceless make
// current calls, bind root device context for the intermediate window in this case.
if (newDC == nullptr && newContext != nullptr)
{
newDC = mDeviceContext;
}
if (newDC != currentContext.dc || newContext != currentContext.glrc) if (newDC != currentContext.dc || newContext != currentContext.glrc)
{ {
if (!mFunctionsWGL->makeCurrent(newDC, newContext)) if (!mFunctionsWGL->makeCurrent(newDC, newContext))
...@@ -749,9 +801,19 @@ gl::Version DisplayWGL::getMaxSupportedESVersion() const ...@@ -749,9 +801,19 @@ gl::Version DisplayWGL::getMaxSupportedESVersion() const
void DisplayWGL::destroyNativeContext(HGLRC context) void DisplayWGL::destroyNativeContext(HGLRC context)
{ {
mFunctionsWGL->deleteContext(context); mFunctionsWGL->deleteContext(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.
CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];
if (currentContext.glrc == context)
{
currentContext.dc = nullptr;
currentContext.glrc = nullptr;
}
} }
HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttributes) const HGLRC DisplayWGL::initializeContextAttribs(HGLRC shareContext,
const egl::AttributeMap &eglAttributes) const
{ {
EGLint requestedDisplayType = static_cast<EGLint>( EGLint requestedDisplayType = static_cast<EGLint>(
eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)); eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
...@@ -770,7 +832,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute ...@@ -770,7 +832,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
{ {
profileMask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; profileMask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
} }
return createContextAttribs(requestedVersion, profileMask); return createContextAttribs(shareContext, requestedVersion, profileMask);
} }
// Try all the GL version in order as a workaround for Mesa context creation where the driver // Try all the GL version in order as a workaround for Mesa context creation where the driver
...@@ -787,7 +849,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute ...@@ -787,7 +849,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
profileFlag |= WGL_CONTEXT_ES_PROFILE_BIT_EXT; profileFlag |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
} }
HGLRC context = createContextAttribs(info.version, profileFlag); HGLRC context = createContextAttribs(shareContext, info.version, profileFlag);
if (context != nullptr) if (context != nullptr)
{ {
return context; return context;
...@@ -797,7 +859,9 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute ...@@ -797,7 +859,9 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
return nullptr; return nullptr;
} }
HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMask) const HGLRC DisplayWGL::createContextAttribs(HGLRC shareContext,
const gl::Version &version,
int profileMask) const
{ {
std::vector<int> attribs; std::vector<int> attribs;
...@@ -824,15 +888,17 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMa ...@@ -824,15 +888,17 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMa
attribs.push_back(0); attribs.push_back(0);
attribs.push_back(0); attribs.push_back(0);
return mFunctionsWGL->createContextAttribsARB(mDeviceContext, nullptr, &attribs[0]); return mFunctionsWGL->createContextAttribsARB(mDeviceContext, shareContext, &attribs[0]);
} }
egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer) egl::Error DisplayWGL::createRenderer(HGLRC shareContext,
bool makeNewContextCurrent,
std::shared_ptr<RendererWGL> *outRenderer)
{ {
HGLRC context = nullptr; HGLRC context = nullptr;
if (mFunctionsWGL->createContextAttribsARB) if (mFunctionsWGL->createContextAttribsARB)
{ {
context = initializeContextAttribs(mDisplayAttributes); context = initializeContextAttribs(shareContext, mDisplayAttributes);
} }
// If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
...@@ -840,6 +906,14 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer) ...@@ -840,6 +906,14 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
{ {
// Don't have control over GL versions // Don't have control over GL versions
context = mFunctionsWGL->createContext(mDeviceContext); context = mFunctionsWGL->createContext(mDeviceContext);
if (context && shareContext)
{
if (!mFunctionsWGL->shareLists(shareContext, context))
{
return egl::EglNotInitialized()
<< "Failed to share lists to newly created context.";
}
}
} }
if (!context) if (!context)
...@@ -852,9 +926,6 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer) ...@@ -852,9 +926,6 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
{ {
return egl::EglNotInitialized() << "Failed to make the intermediate WGL context current."; return egl::EglNotInitialized() << "Failed to make the intermediate WGL context current.";
} }
CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];
currentContext.dc = mDeviceContext;
currentContext.glrc = context;
std::unique_ptr<FunctionsGL> functionsGL( std::unique_ptr<FunctionsGL> functionsGL(
new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress)); new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress));
...@@ -862,6 +933,21 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer) ...@@ -862,6 +933,21 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
outRenderer->reset(new RendererWGL(std::move(functionsGL), mDisplayAttributes, this, context)); outRenderer->reset(new RendererWGL(std::move(functionsGL), mDisplayAttributes, this, context));
CurrentNativeContext &currentContext = mCurrentData[std::this_thread::get_id()];
if (makeNewContextCurrent)
{
currentContext.dc = mDeviceContext;
currentContext.glrc = context;
}
else
{
// Reset the current context back to the previous state
if (!mFunctionsWGL->makeCurrent(currentContext.dc, currentContext.glrc))
{
return egl::EglNotInitialized() << "Failed reset the current context.";
}
}
return egl::NoError(); return egl::NoError();
} }
} }
...@@ -87,12 +87,18 @@ class DisplayWGL : public DisplayGL ...@@ -87,12 +87,18 @@ class DisplayWGL : public DisplayGL
egl::Error makeCurrentSurfaceless(gl::Context *context) override; egl::Error makeCurrentSurfaceless(gl::Context *context) override;
HGLRC initializeContextAttribs(const egl::AttributeMap &eglAttributes) const; HGLRC initializeContextAttribs(HGLRC shareContext,
HGLRC createContextAttribs(const gl::Version &version, int profileMask) const; const egl::AttributeMap &eglAttributes) const;
HGLRC createContextAttribs(HGLRC shareContext,
const gl::Version &version,
int profileMask) const;
egl::Error createRenderer(std::shared_ptr<RendererWGL> *outRenderer); egl::Error createRenderer(HGLRC shareContext,
bool makeNewContextCurrent,
std::shared_ptr<RendererWGL> *outRenderer);
std::shared_ptr<RendererWGL> mRenderer; std::shared_ptr<RendererWGL> mRenderer;
bool mVirtualizedContexts;
struct CurrentNativeContext struct CurrentNativeContext
{ {
......
...@@ -442,6 +442,20 @@ bool ShouldUseDebugLayers(const egl::AttributeMap &attribs) ...@@ -442,6 +442,20 @@ bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
#endif // defined(ANGLE_ENABLE_ASSERTS) #endif // defined(ANGLE_ENABLE_ASSERTS)
} }
bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue)
{
EGLAttrib virtualizedContextRequest =
attribs.get(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE, EGL_DONT_CARE);
if (defaultValue)
{
return (virtualizedContextRequest != EGL_FALSE);
}
else
{
return (virtualizedContextRequest == EGL_TRUE);
}
}
void CopyImageCHROMIUM(const uint8_t *sourceData, void CopyImageCHROMIUM(const uint8_t *sourceData,
size_t sourceRowPitch, size_t sourceRowPitch,
size_t sourcePixelBytes, size_t sourcePixelBytes,
......
...@@ -209,6 +209,7 @@ struct LoadImageFunctionInfo ...@@ -209,6 +209,7 @@ struct LoadImageFunctionInfo
using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum); using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
bool ShouldUseDebugLayers(const egl::AttributeMap &attribs); bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
void CopyImageCHROMIUM(const uint8_t *sourceData, void CopyImageCHROMIUM(const uint8_t *sourceData,
size_t sourceRowPitch, size_t sourceRowPitch,
......
...@@ -409,6 +409,27 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform, ...@@ -409,6 +409,27 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform,
} }
break; break;
case EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE:
if (!clientExtensions.platformANGLEContextVirtualization)
{
return EglBadAttribute() << "EGL_ANGLE_platform_angle_context_"
"virtualization extension not active";
}
switch (value)
{
case EGL_DONT_CARE:
case EGL_FALSE:
case EGL_TRUE:
break;
default:
return EglBadAttribute() << "Invalid value for "
"EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_"
"ANGLE attrib";
}
break;
default: default:
break; break;
} }
......
...@@ -26,9 +26,10 @@ class MultithreadingTest : public ANGLETest ...@@ -26,9 +26,10 @@ class MultithreadingTest : public ANGLETest
setConfigGreenBits(8); setConfigGreenBits(8);
setConfigBlueBits(8); setConfigBlueBits(8);
setConfigAlphaBits(8); setConfigAlphaBits(8);
setContextVirtualization(false);
} }
bool platformSupportsMultithreading() const { return false; } bool platformSupportsMultithreading() const { return IsOpenGL() && IsWindows(); }
}; };
// Test that it's possible to make one context current on different threads // Test that it's possible to make one context current on different threads
...@@ -92,7 +93,7 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext) ...@@ -92,7 +93,7 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext)
std::array<std::thread, kThreadCount> threads; std::array<std::thread, kThreadCount> threads;
for (size_t thread = 0; thread < kThreadCount; thread++) for (size_t thread = 0; thread < kThreadCount; thread++)
{ {
threads[thread] = std::thread([&]() { threads[thread] = std::thread([&, thread]() {
EGLSurface pbuffer= EGL_NO_SURFACE; EGLSurface pbuffer= EGL_NO_SURFACE;
EGLConfig ctx= EGL_NO_CONTEXT; EGLConfig ctx= EGL_NO_CONTEXT;
...@@ -102,7 +103,6 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext) ...@@ -102,7 +103,6 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext)
// Initialize the pbuffer and context // Initialize the pbuffer and context
EGLint pbufferAttributes[] = { EGLint pbufferAttributes[] = {
EGL_WIDTH, kPBufferSize, EGL_HEIGHT, kPBufferSize, EGL_WIDTH, kPBufferSize, EGL_HEIGHT, kPBufferSize,
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE,
}; };
pbuffer = eglCreatePbufferSurface(dpy, config, pbufferAttributes); pbuffer = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
......
...@@ -897,6 +897,11 @@ void ANGLETestBase::setContextProgramCacheEnabled(bool enabled) ...@@ -897,6 +897,11 @@ void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)
mEGLWindow->setContextProgramCacheEnabled(enabled); mEGLWindow->setContextProgramCacheEnabled(enabled);
} }
void ANGLETestBase::setContextVirtualization(bool enabled)
{
mEGLWindow->setContextVirtualization(enabled);
}
void ANGLETestBase::setDeferContextInit(bool enabled) void ANGLETestBase::setDeferContextInit(bool enabled)
{ {
mDeferContextInit = enabled; mDeferContextInit = enabled;
......
...@@ -341,6 +341,7 @@ class ANGLETestBase ...@@ -341,6 +341,7 @@ class ANGLETestBase
void setClientArraysEnabled(bool enabled); void setClientArraysEnabled(bool enabled);
void setRobustResourceInit(bool enabled); void setRobustResourceInit(bool enabled);
void setContextProgramCacheEnabled(bool enabled); void setContextProgramCacheEnabled(bool enabled);
void setContextVirtualization(bool enabled);
// Some EGL extension tests would like to defer the Context init until the test body. // Some EGL extension tests would like to defer the Context init until the test body.
void setDeferContextInit(bool enabled); void setDeferContextInit(bool enabled);
......
...@@ -127,6 +127,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion, ...@@ -127,6 +127,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
mSamples(-1), mSamples(-1),
mDebugLayersEnabled(), mDebugLayersEnabled(),
mContextProgramCacheEnabled(), mContextProgramCacheEnabled(),
mContextVirtualization(),
mPlatformMethods(nullptr) mPlatformMethods(nullptr)
{ {
} }
...@@ -205,6 +206,12 @@ bool EGLWindow::initializeDisplayAndSurface(OSWindow *osWindow) ...@@ -205,6 +206,12 @@ bool EGLWindow::initializeDisplayAndSurface(OSWindow *osWindow)
displayAttributes.push_back(mDebugLayersEnabled.value() ? EGL_TRUE : EGL_FALSE); displayAttributes.push_back(mDebugLayersEnabled.value() ? EGL_TRUE : EGL_FALSE);
} }
if (mContextVirtualization.valid())
{
displayAttributes.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
displayAttributes.push_back(mContextVirtualization.value() ? EGL_TRUE : EGL_FALSE);
}
if (mPlatformMethods) if (mPlatformMethods)
{ {
static_assert(sizeof(EGLAttrib) == sizeof(mPlatformMethods), "Unexpected pointer size"); static_assert(sizeof(EGLAttrib) == sizeof(mPlatformMethods), "Unexpected pointer size");
......
...@@ -89,6 +89,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -89,6 +89,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
mPlatformMethods = platformMethods; mPlatformMethods = platformMethods;
} }
void setContextProgramCacheEnabled(bool enabled) { mContextProgramCacheEnabled = enabled; } void setContextProgramCacheEnabled(bool enabled) { mContextProgramCacheEnabled = enabled; }
void setContextVirtualization(bool enabled) { mContextVirtualization = enabled; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config); static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
...@@ -162,6 +163,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable ...@@ -162,6 +163,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
EGLint mSamples; EGLint mSamples;
Optional<bool> mDebugLayersEnabled; Optional<bool> mDebugLayersEnabled;
Optional<bool> mContextProgramCacheEnabled; Optional<bool> mContextProgramCacheEnabled;
Optional<bool> mContextVirtualization;
angle::PlatformMethods *mPlatformMethods; angle::PlatformMethods *mPlatformMethods;
}; };
......
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