зеркало из https://github.com/AvaloniaUI/angle.git
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: Yuly Novikov <ynovikov@chromium.org>
This commit is contained in:
Родитель
5bdf8bd1cf
Коммит
24ddc7a894
|
@ -0,0 +1,80 @@
|
|||
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 @@
|
|||
#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
|
||||
#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
|
||||
#define EGL_ANGLE_x11_visual
|
||||
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
|
||||
|
|
|
@ -1389,13 +1389,14 @@ ClientExtensions::ClientExtensions()
|
|||
platformANGLED3D(false),
|
||||
platformANGLEOpenGL(false),
|
||||
platformANGLEVulkan(false),
|
||||
platformANGLEContextVirtualization(false),
|
||||
deviceCreation(false),
|
||||
deviceCreationD3D11(false),
|
||||
x11Visual(false),
|
||||
experimentalPresentPath(false),
|
||||
clientGetAllProcAddresses(false),
|
||||
explicitContext(false),
|
||||
debug(false)
|
||||
debug(false),
|
||||
explicitContext(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1406,22 +1407,23 @@ std::vector<std::string> ClientExtensions::getStrings() const
|
|||
std::vector<std::string> extensionStrings;
|
||||
|
||||
// clang-format off
|
||||
// | Extension name | Supported flag | Output vector |
|
||||
InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
|
||||
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
|
||||
InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
|
||||
// | Extension name | Supported flag | Output vector |
|
||||
InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
|
||||
InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
|
||||
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
|
||||
InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_explicit_context", explicitContext, &extensionStrings);
|
||||
// clang-format on
|
||||
|
||||
return extensionStrings;
|
||||
|
|
|
@ -813,6 +813,9 @@ struct ClientExtensions
|
|||
// EGL_ANGLE_platform_angle_vulkan
|
||||
bool platformANGLEVulkan;
|
||||
|
||||
// EGL_ANGLE_platform_angle_context_virtualization
|
||||
bool platformANGLEContextVirtualization;
|
||||
|
||||
// EGL_ANGLE_device_creation
|
||||
bool deviceCreation;
|
||||
|
||||
|
@ -828,11 +831,11 @@ struct ClientExtensions
|
|||
// EGL_KHR_client_get_all_proc_addresses
|
||||
bool clientGetAllProcAddresses;
|
||||
|
||||
// EGL_ANGLE_explicit_context
|
||||
bool explicitContext;
|
||||
|
||||
// EGL_KHR_debug
|
||||
bool debug;
|
||||
|
||||
// EGL_ANGLE_explicit_context
|
||||
bool explicitContext;
|
||||
};
|
||||
|
||||
} // namespace egl
|
||||
|
|
|
@ -1027,6 +1027,9 @@ static ClientExtensions GenerateClientExtensions()
|
|||
|
||||
#if defined(ANGLE_ENABLE_OPENGL)
|
||||
extensions.platformANGLEOpenGL = true;
|
||||
|
||||
// Selecting context virtualization is currently only supported in the OpenGL backend.
|
||||
extensions.platformANGLEContextVirtualization = true;
|
||||
#endif
|
||||
|
||||
#if defined(ANGLE_ENABLE_NULL)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libANGLE/renderer/gl/wgl/RendererWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
|
||||
#include "libANGLE/renderer/renderer_utils.h"
|
||||
|
||||
#include "platform/Platform.h"
|
||||
|
||||
|
@ -34,6 +35,9 @@
|
|||
namespace rx
|
||||
{
|
||||
|
||||
// Use context virtualization by default because Chrome uses it.
|
||||
static constexpr bool kDefaultWGLVirtualizedContexts = true;
|
||||
|
||||
class FunctionsGLWindows : public FunctionsGL
|
||||
{
|
||||
public:
|
||||
|
@ -65,6 +69,7 @@ class FunctionsGLWindows : public FunctionsGL
|
|||
DisplayWGL::DisplayWGL(const egl::DisplayState &state)
|
||||
: DisplayGL(state),
|
||||
mRenderer(nullptr),
|
||||
mVirtualizedContexts(kDefaultWGLVirtualizedContexts),
|
||||
mCurrentData(),
|
||||
mOpenGLModule(nullptr),
|
||||
mFunctionsWGL(nullptr),
|
||||
|
@ -103,6 +108,9 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display)
|
|||
{
|
||||
mDisplayAttributes = display->getAttributeMap();
|
||||
|
||||
mVirtualizedContexts =
|
||||
ShouldUseVirtualizedContexts(mDisplayAttributes, kDefaultWGLVirtualizedContexts);
|
||||
|
||||
mOpenGLModule = LoadLibraryA("opengl32.dll");
|
||||
if (!mOpenGLModule)
|
||||
{
|
||||
|
@ -250,7 +258,7 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display)
|
|||
<< "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();
|
||||
|
||||
mHasRobustness = functionsGL->getGraphicsResetStatus != nullptr;
|
||||
|
@ -439,7 +447,23 @@ SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &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()
|
||||
|
@ -527,8 +551,11 @@ egl::ConfigSet DisplayWGL::generateConfigs()
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -665,20 +692,45 @@ egl::Error DisplayWGL::makeCurrent(egl::Surface *drawSurface,
|
|||
{
|
||||
CurrentNativeContext ¤tContext = mCurrentData[std::this_thread::get_id()];
|
||||
|
||||
HDC newDC = currentContext.dc;
|
||||
HDC newDC = nullptr;
|
||||
if (drawSurface)
|
||||
{
|
||||
SurfaceWGL *drawSurfaceWGL = GetImplAs<SurfaceWGL>(drawSurface);
|
||||
newDC = drawSurfaceWGL->getDC();
|
||||
}
|
||||
|
||||
HGLRC newContext = currentContext.glrc;
|
||||
HGLRC newContext = nullptr;
|
||||
if (context)
|
||||
{
|
||||
ContextWGL *contextWGL = GetImplAs<ContextWGL>(context);
|
||||
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 (!mFunctionsWGL->makeCurrent(newDC, newContext))
|
||||
|
@ -749,9 +801,19 @@ gl::Version DisplayWGL::getMaxSupportedESVersion() const
|
|||
void DisplayWGL::destroyNativeContext(HGLRC 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 ¤tContext = 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>(
|
||||
eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
|
||||
|
@ -770,7 +832,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
|
|||
{
|
||||
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
|
||||
|
@ -787,7 +849,7 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
|
|||
profileFlag |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
|
||||
}
|
||||
|
||||
HGLRC context = createContextAttribs(info.version, profileFlag);
|
||||
HGLRC context = createContextAttribs(shareContext, info.version, profileFlag);
|
||||
if (context != nullptr)
|
||||
{
|
||||
return context;
|
||||
|
@ -797,7 +859,9 @@ HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttribute
|
|||
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;
|
||||
|
||||
|
@ -824,15 +888,17 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMa
|
|||
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;
|
||||
if (mFunctionsWGL->createContextAttribsARB)
|
||||
{
|
||||
context = initializeContextAttribs(mDisplayAttributes);
|
||||
context = initializeContextAttribs(shareContext, mDisplayAttributes);
|
||||
}
|
||||
|
||||
// If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
|
||||
|
@ -840,6 +906,14 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
|
|||
{
|
||||
// Don't have control over GL versions
|
||||
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)
|
||||
|
@ -852,9 +926,6 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
|
|||
{
|
||||
return egl::EglNotInitialized() << "Failed to make the intermediate WGL context current.";
|
||||
}
|
||||
CurrentNativeContext ¤tContext = mCurrentData[std::this_thread::get_id()];
|
||||
currentContext.dc = mDeviceContext;
|
||||
currentContext.glrc = context;
|
||||
|
||||
std::unique_ptr<FunctionsGL> functionsGL(
|
||||
new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress));
|
||||
|
@ -862,6 +933,21 @@ egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
|
|||
|
||||
outRenderer->reset(new RendererWGL(std::move(functionsGL), mDisplayAttributes, this, context));
|
||||
|
||||
CurrentNativeContext ¤tContext = 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,12 +87,18 @@ class DisplayWGL : public DisplayGL
|
|||
|
||||
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
|
||||
|
||||
HGLRC initializeContextAttribs(const egl::AttributeMap &eglAttributes) const;
|
||||
HGLRC createContextAttribs(const gl::Version &version, int profileMask) const;
|
||||
HGLRC initializeContextAttribs(HGLRC shareContext,
|
||||
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;
|
||||
bool mVirtualizedContexts;
|
||||
|
||||
struct CurrentNativeContext
|
||||
{
|
||||
|
|
|
@ -442,6 +442,20 @@ bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
|
|||
#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,
|
||||
size_t sourceRowPitch,
|
||||
size_t sourcePixelBytes,
|
||||
|
|
|
@ -209,6 +209,7 @@ struct LoadImageFunctionInfo
|
|||
using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
|
||||
|
||||
bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
|
||||
bool ShouldUseVirtualizedContexts(const egl::AttributeMap &attribs, bool defaultValue);
|
||||
|
||||
void CopyImageCHROMIUM(const uint8_t *sourceData,
|
||||
size_t sourceRowPitch,
|
||||
|
|
|
@ -409,6 +409,27 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform,
|
|||
}
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -26,9 +26,10 @@ class MultithreadingTest : public ANGLETest
|
|||
setConfigGreenBits(8);
|
||||
setConfigBlueBits(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
|
||||
|
@ -92,7 +93,7 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext)
|
|||
std::array<std::thread, kThreadCount> threads;
|
||||
for (size_t thread = 0; thread < kThreadCount; thread++)
|
||||
{
|
||||
threads[thread] = std::thread([&]() {
|
||||
threads[thread] = std::thread([&, thread]() {
|
||||
EGLSurface pbuffer= EGL_NO_SURFACE;
|
||||
EGLConfig ctx= EGL_NO_CONTEXT;
|
||||
|
||||
|
@ -102,7 +103,6 @@ TEST_P(MultithreadingTest, MakeCurrentMultiContext)
|
|||
// Initialize the pbuffer and context
|
||||
EGLint pbufferAttributes[] = {
|
||||
EGL_WIDTH, kPBufferSize, EGL_HEIGHT, kPBufferSize,
|
||||
EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
|
||||
EGL_NONE, EGL_NONE,
|
||||
};
|
||||
pbuffer = eglCreatePbufferSurface(dpy, config, pbufferAttributes);
|
||||
|
|
|
@ -897,6 +897,11 @@ void ANGLETestBase::setContextProgramCacheEnabled(bool enabled)
|
|||
mEGLWindow->setContextProgramCacheEnabled(enabled);
|
||||
}
|
||||
|
||||
void ANGLETestBase::setContextVirtualization(bool enabled)
|
||||
{
|
||||
mEGLWindow->setContextVirtualization(enabled);
|
||||
}
|
||||
|
||||
void ANGLETestBase::setDeferContextInit(bool enabled)
|
||||
{
|
||||
mDeferContextInit = enabled;
|
||||
|
|
|
@ -341,6 +341,7 @@ class ANGLETestBase
|
|||
void setClientArraysEnabled(bool enabled);
|
||||
void setRobustResourceInit(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.
|
||||
void setDeferContextInit(bool enabled);
|
||||
|
|
|
@ -127,6 +127,7 @@ EGLWindow::EGLWindow(EGLint glesMajorVersion,
|
|||
mSamples(-1),
|
||||
mDebugLayersEnabled(),
|
||||
mContextProgramCacheEnabled(),
|
||||
mContextVirtualization(),
|
||||
mPlatformMethods(nullptr)
|
||||
{
|
||||
}
|
||||
|
@ -205,6 +206,12 @@ bool EGLWindow::initializeDisplayAndSurface(OSWindow *osWindow)
|
|||
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)
|
||||
{
|
||||
static_assert(sizeof(EGLAttrib) == sizeof(mPlatformMethods), "Unexpected pointer size");
|
||||
|
|
|
@ -89,6 +89,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
|
|||
mPlatformMethods = platformMethods;
|
||||
}
|
||||
void setContextProgramCacheEnabled(bool enabled) { mContextProgramCacheEnabled = enabled; }
|
||||
void setContextVirtualization(bool enabled) { mContextVirtualization = enabled; }
|
||||
|
||||
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
|
||||
|
||||
|
@ -162,6 +163,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
|
|||
EGLint mSamples;
|
||||
Optional<bool> mDebugLayersEnabled;
|
||||
Optional<bool> mContextProgramCacheEnabled;
|
||||
Optional<bool> mContextVirtualization;
|
||||
angle::PlatformMethods *mPlatformMethods;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче