Commit 27af0b2d by James Darpinian Committed by Commit Bot

Reland "ANGLE_platform_angle_device_context_volatile_* extensions"

This is a reland of e70f6aa6 Original change's description: > ANGLE_platform_angle_device_context_volatile_* extensions > > Change from Kimmo Kinnunen downstream: > https://bugs.webkit.org/show_bug.cgi?id=216106 > > Add two extensions for EAGL and CGL backends to declare the > underlying platform context being "volatile". It means that > the thread-global current context is being modified behind > ANGLE. If ANGLE context is marked volatile for a particular > API, it will sync the underlying context for every EGL > function that needs the context. Most intuitive use is > for the client to call eglMakeCurrent before calling any > gl function if the client knowns the platform state might > be dirty. > > Implement eglReleaseThread for EAGL and CGL backends. > Releasing thread will unset the platform current context. > > Fix a bug of omitting EGL_ANGLE_device_eagl from being > advertised. > > Bug: angleproject:5104 > Change-Id: I1ec98ad35bc0caada23556ae8697fdef20f65b1a > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2486548 > Commit-Queue: James Darpinian <jdarpinian@chromium.org> > Reviewed-by: Kenneth Russell <kbr@chromium.org> > Reviewed-by: Geoff Lang <geofflang@chromium.org> Bug: angleproject:5104 Change-Id: I88265625a4bb4c1412532768d17d7b4356c7be41 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2508842Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: James Darpinian <jdarpinian@chromium.org>
parent fa616931
Name
ANGLE_platform_angle_device_context_volatile_cgl
Name Strings
EGL_ANGLE_platform_angle_device_context_volatile_cgl
Contributors
Kimmo Kinnunen, Apple
Kenneth Russell, Google
Contacts
Kimmo Kinnunen, Apple (kkinnunen 'at' apple 'dot' org)
Kenneth Russell, Google (kbr 'at' chromium 'dot' org)
Status
Draft
Version
Version 1, 2020-09-30
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
is able to function even if client changes current CGL context of the
thread. Requesting a volatile device context contexts may impact performance.
The extension is useful for using EGL in a library that cannot guarantee
which platform APIs its clients will use.
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_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE 0x34A3
Additions to the EGL Specification
None.
New Behavior
To request a display that internally supports the feature,
use the attribute EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE.
EGL_TRUE enables volatile CGL device context and EGL_FALSE disables it.
Any value other than these will result in an error.
The default value for EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE
is EGL_FALSE.
When the device context of the display is set as volatile CGL, then
each EGL function will change the current CGL context state accordingly
to use the internal device context, if needed. If the internal device context
is not using CGL, the property has no effect.
Calls to OpenGL or OpenGL ES functions will not ensure the underlying device
context is correct. If the state of the current CGL context is unknown,
clients should call MakeCurrent to ensure that the internal device
context is made current.
Issues
None
Revision History
Version 1, 2020-09-30 (Kimmo Kinnunen)
- Initial draft
Name
ANGLE_platform_angle_device_context_volatile_eagl
Name Strings
EGL_ANGLE_platform_angle_device_context_volatile_eagl
Contributors
Kimmo Kinnunen, Apple
Kenneth Russell, Google
Contacts
Kimmo Kinnunen, Apple (kkinnunen 'at' apple 'dot' org)
Kenneth Russell, Google (kbr 'at' chromium 'dot' org)
Status
Draft
Version
Version 1, 2020-09-30
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
is able to function even if client changes current EAGL context of the
thread. Requesting a volatile device context contexts may impact performance.
The extension is useful for using EGL in a library that cannot guarantee
which platform APIs its clients will use.
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_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE 0x34A2
Additions to the EGL Specification
None.
New Behavior
To request a display that internally supports the feature,
use the attribute EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE.
EGL_TRUE enables volatile EAGL device context and EGL_FALSE disables it.
Any value other than these will result in an error.
The default value for EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE
is EGL_FALSE.
When the device context of the display is set as volatile EAGL, then
each EGL function will change the current EAGL context state accordingly
to use the internal device context, if needed. If the internal device context
is not using EAGL, the property has no effect.
Calls to OpenGL or OpenGL ES functions will not ensure the underlying device
context is correct. If the state of the current EAGL context is unknown,
clients should call MakeCurrent to ensure that the internal device
context is made current.
Issues
None
Revision History
Version 1, 2020-09-30 (Kimmo Kinnunen)
- Initial draft
...@@ -118,6 +118,16 @@ ...@@ -118,6 +118,16 @@
#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481 #define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
#endif /* EGL_ANGLE_platform_angle_context_virtualization */ #endif /* EGL_ANGLE_platform_angle_context_virtualization */
#ifndef EGL_ANGLE_platform_angle_device_context_volatile_eagl
#define EGL_ANGLE_platform_angle_device_context_volatile_eagl 1
#define EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE 0x34A2
#endif /* EGL_ANGLE_platform_angle_device_context_volatile_eagl */
#ifndef EGL_ANGLE_platform_angle_device_context_volatile_cgl
#define EGL_ANGLE_platform_angle_device_context_volatile_cgl 1
#define EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE 0x34A3
#endif /* EGL_ANGLE_platform_angle_device_context_volatile_cgl */
#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
......
...@@ -1440,6 +1440,8 @@ std::vector<std::string> DeviceExtensions::getStrings() const ...@@ -1440,6 +1440,8 @@ std::vector<std::string> DeviceExtensions::getStrings() const
// | Extension name | Supported flag | Output vector | // | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_eagl", deviceEAGL, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
...@@ -1467,6 +1469,8 @@ std::vector<std::string> ClientExtensions::getStrings() const ...@@ -1467,6 +1469,8 @@ std::vector<std::string> ClientExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_metal", platformANGLEMetal, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_metal", platformANGLEMetal, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings); InsertExtensionString("EGL_ANGLE_platform_angle_context_virtualization", platformANGLEContextVirtualization, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_eagl", platformANGLEDeviceContextVolatileEagl, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_cgl", platformANGLEDeviceContextVolatileCgl, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings); InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings); InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
......
...@@ -1205,6 +1205,12 @@ struct ClientExtensions ...@@ -1205,6 +1205,12 @@ struct ClientExtensions
// EGL_ANGLE_platform_angle_context_virtualization // EGL_ANGLE_platform_angle_context_virtualization
bool platformANGLEContextVirtualization = false; bool platformANGLEContextVirtualization = false;
// EGL_ANGLE_platform_angle_device_context_volatile_eagl
bool platformANGLEDeviceContextVolatileEagl = false;
// EGL_ANGLE_platform_angle_device_context_volatile_cgl
bool platformANGLEDeviceContextVolatileCgl = false;
// EGL_ANGLE_device_creation // EGL_ANGLE_device_creation
bool deviceCreation = false; bool deviceCreation = false;
......
...@@ -962,6 +962,16 @@ Error Display::terminate(const Thread *thread) ...@@ -962,6 +962,16 @@ Error Display::terminate(const Thread *thread)
return NoError(); return NoError();
} }
Error Display::prepareForCall()
{
return mImplementation->prepareForCall();
}
Error Display::releaseThread()
{
return mImplementation->releaseThread();
}
std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
{ {
return mConfigSet.filter(attribs); return mConfigSet.filter(attribs);
...@@ -1643,6 +1653,15 @@ static ClientExtensions GenerateClientExtensions() ...@@ -1643,6 +1653,15 @@ static ClientExtensions GenerateClientExtensions()
extensions.platformANGLEDeviceTypeEGLANGLE = true; extensions.platformANGLEDeviceTypeEGLANGLE = true;
#endif #endif
#if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || \
(defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64))
extensions.platformANGLEDeviceContextVolatileEagl = true;
#endif
#if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
extensions.platformANGLEDeviceContextVolatileCgl = true;
#endif
extensions.clientGetAllProcAddresses = true; extensions.clientGetAllProcAddresses = true;
extensions.debug = true; extensions.debug = true;
extensions.explicitContext = true; extensions.explicitContext = true;
......
...@@ -116,6 +116,13 @@ class Display final : public LabeledObject, ...@@ -116,6 +116,13 @@ class Display final : public LabeledObject,
Error initialize(); Error initialize();
Error terminate(const Thread *thread); Error terminate(const Thread *thread);
// Called before all display state dependent EGL functions. Backends can set up, for example,
// thread-specific backend state through this function. Not called for functions that do not
// need the state.
Error prepareForCall();
// Called on eglReleaseThread. Backends can tear down thread-specific backend state through
// this function.
Error releaseThread();
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap); static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay, static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
......
...@@ -23,6 +23,16 @@ DisplayImpl::~DisplayImpl() ...@@ -23,6 +23,16 @@ DisplayImpl::~DisplayImpl()
ASSERT(mState.surfaceSet.empty()); ASSERT(mState.surfaceSet.empty());
} }
egl::Error DisplayImpl::prepareForCall()
{
return egl::NoError();
}
egl::Error DisplayImpl::releaseThread()
{
return egl::NoError();
}
const egl::DisplayExtensions &DisplayImpl::getExtensions() const const egl::DisplayExtensions &DisplayImpl::getExtensions() const
{ {
if (!mExtensionsInitialized) if (!mExtensionsInitialized)
......
...@@ -68,6 +68,8 @@ class DisplayImpl : public EGLImplFactory, public angle::Subject ...@@ -68,6 +68,8 @@ class DisplayImpl : public EGLImplFactory, public angle::Subject
virtual egl::Error initialize(egl::Display *display) = 0; virtual egl::Error initialize(egl::Display *display) = 0;
virtual void terminate() = 0; virtual void terminate() = 0;
virtual egl::Error prepareForCall();
virtual egl::Error releaseThread();
virtual egl::Error makeCurrent(egl::Display *display, virtual egl::Error makeCurrent(egl::Display *display,
egl::Surface *drawSurface, egl::Surface *drawSurface,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_ #define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
#include <thread> #include <thread>
#include <unordered_set>
#include "libANGLE/renderer/gl/DisplayGL.h" #include "libANGLE/renderer/gl/DisplayGL.h"
...@@ -43,6 +44,8 @@ class DisplayCGL : public DisplayGL ...@@ -43,6 +44,8 @@ class DisplayCGL : public DisplayGL
egl::Error initialize(egl::Display *display) override; egl::Error initialize(egl::Display *display) override;
void terminate() override; void terminate() override;
egl::Error prepareForCall() override;
egl::Error releaseThread() override;
egl::Error makeCurrent(egl::Display *display, egl::Error makeCurrent(egl::Display *display,
egl::Surface *drawSurface, egl::Surface *drawSurface,
...@@ -115,7 +118,7 @@ class DisplayCGL : public DisplayGL ...@@ -115,7 +118,7 @@ class DisplayCGL : public DisplayGL
egl::Display *mEGLDisplay; egl::Display *mEGLDisplay;
CGLContextObj mContext; CGLContextObj mContext;
std::unordered_map<std::thread::id, CGLContextObj> mCurrentContexts; std::unordered_set<std::thread::id> mThreadsWithCurrentContext;
CGLPixelFormatObj mPixelFormat; CGLPixelFormatObj mPixelFormat;
bool mSupportsGPUSwitching; bool mSupportsGPUSwitching;
uint64_t mCurrentGPUID; uint64_t mCurrentGPUID;
...@@ -125,6 +128,7 @@ class DisplayCGL : public DisplayGL ...@@ -125,6 +128,7 @@ class DisplayCGL : public DisplayGL
// is unref'd for the last time, this is set to the time of that last unref. If it isn't // is unref'd for the last time, this is set to the time of that last unref. If it isn't
// activated again in 10 seconds, the discrete GPU pixel format is deleted. // activated again in 10 seconds, the discrete GPU pixel format is deleted.
double mLastDiscreteGPUUnrefTime; double mLastDiscreteGPUUnrefTime;
bool mDeviceContextIsVolatile = false;
}; };
} // namespace rx } // namespace rx
......
...@@ -198,9 +198,11 @@ egl::Error DisplayCGL::initialize(egl::Display *display) ...@@ -198,9 +198,11 @@ egl::Error DisplayCGL::initialize(egl::Display *display)
mCurrentGPUID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay); mCurrentGPUID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay);
} }
CGLSetCurrentContext(mContext); if (CGLSetCurrentContext(mContext) != kCGLNoError)
{
mCurrentContexts[std::this_thread::get_id()] = mContext; return egl::EglNotInitialized() << "Could not make the CGL context current.";
}
mThreadsWithCurrentContext.insert(std::this_thread::get_id());
// There is no equivalent getProcAddress in CGL so we open the dylib directly // There is no equivalent getProcAddress in CGL so we open the dylib directly
void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW); void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW);
...@@ -224,6 +226,10 @@ egl::Error DisplayCGL::initialize(egl::Display *display) ...@@ -224,6 +226,10 @@ egl::Error DisplayCGL::initialize(egl::Display *display)
return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable."; return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
} }
auto &attributes = display->getAttributeMap();
mDeviceContextIsVolatile =
attributes.get(EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE, GL_FALSE);
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -237,12 +243,12 @@ void DisplayCGL::terminate() ...@@ -237,12 +243,12 @@ void DisplayCGL::terminate()
CGLDestroyPixelFormat(mPixelFormat); CGLDestroyPixelFormat(mPixelFormat);
mPixelFormat = nullptr; mPixelFormat = nullptr;
} }
mCurrentContexts.clear();
if (mContext != nullptr) if (mContext != nullptr)
{ {
CGLSetCurrentContext(nullptr); CGLSetCurrentContext(nullptr);
CGLDestroyContext(mContext); CGLDestroyContext(mContext);
mContext = nullptr; mContext = nullptr;
mThreadsWithCurrentContext.clear();
} }
if (mDiscreteGPUPixelFormat != nullptr) if (mDiscreteGPUPixelFormat != nullptr)
{ {
...@@ -252,24 +258,46 @@ void DisplayCGL::terminate() ...@@ -252,24 +258,46 @@ void DisplayCGL::terminate()
} }
} }
egl::Error DisplayCGL::prepareForCall()
{
if (!mContext)
{
return egl::EglNotInitialized() << "Context not allocated.";
}
auto threadId = std::this_thread::get_id();
if (mDeviceContextIsVolatile ||
mThreadsWithCurrentContext.find(threadId) == mThreadsWithCurrentContext.end())
{
if (CGLSetCurrentContext(mContext) != kCGLNoError)
{
return egl::EglBadAlloc() << "Could not make device CGL context current.";
}
mThreadsWithCurrentContext.insert(threadId);
}
return egl::NoError();
}
egl::Error DisplayCGL::releaseThread()
{
ASSERT(mContext);
auto threadId = std::this_thread::get_id();
if (mThreadsWithCurrentContext.find(threadId) != mThreadsWithCurrentContext.end())
{
if (CGLSetCurrentContext(nullptr) != kCGLNoError)
{
return egl::EglBadAlloc() << "Could not release device CGL context.";
}
mThreadsWithCurrentContext.erase(threadId);
}
return egl::NoError();
}
egl::Error DisplayCGL::makeCurrent(egl::Display *display, egl::Error DisplayCGL::makeCurrent(egl::Display *display,
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface, egl::Surface *readSurface,
gl::Context *context) gl::Context *context)
{ {
checkDiscreteGPUStatus(); checkDiscreteGPUStatus();
// If the thread that's calling makeCurrent does not have the correct
// context current (either mContext or 0), we need to set it current.
CGLContextObj newContext = 0;
if (context)
{
newContext = mContext;
}
if (newContext != mCurrentContexts[std::this_thread::get_id()])
{
CGLSetCurrentContext(newContext);
mCurrentContexts[std::this_thread::get_id()] = newContext;
}
return DisplayGL::makeCurrent(display, drawSurface, readSurface, context); return DisplayGL::makeCurrent(display, drawSurface, readSurface, context);
} }
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#ifndef LIBANGLE_RENDERER_GL_EAGL_DISPLAYEAGL_H_ #ifndef LIBANGLE_RENDERER_GL_EAGL_DISPLAYEAGL_H_
#define LIBANGLE_RENDERER_GL_EAGL_DISPLAYEAGL_H_ #define LIBANGLE_RENDERER_GL_EAGL_DISPLAYEAGL_H_
#include <thread>
#include <unordered_set>
#import "common/platform.h" #import "common/platform.h"
#if defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST) #if defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)
...@@ -35,6 +38,8 @@ class DisplayEAGL : public DisplayGL ...@@ -35,6 +38,8 @@ class DisplayEAGL : public DisplayGL
egl::Error initialize(egl::Display *display) override; egl::Error initialize(egl::Display *display) override;
void terminate() override; void terminate() override;
egl::Error prepareForCall() override;
egl::Error releaseThread() override;
SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window, EGLNativeWindowType window,
...@@ -93,6 +98,8 @@ class DisplayEAGL : public DisplayGL ...@@ -93,6 +98,8 @@ class DisplayEAGL : public DisplayGL
egl::Display *mEGLDisplay; egl::Display *mEGLDisplay;
EAGLContextObj mContext; EAGLContextObj mContext;
std::unordered_set<std::thread::id> mThreadsWithContextCurrent;
bool mDeviceContextIsVolatile = false;
}; };
} // namespace rx } // namespace rx
......
...@@ -75,7 +75,12 @@ egl::Error DisplayEAGL::initialize(egl::Display *display) ...@@ -75,7 +75,12 @@ egl::Error DisplayEAGL::initialize(egl::Display *display)
{ {
return egl::EglNotInitialized() << "Could not create the EAGL context."; return egl::EglNotInitialized() << "Could not create the EAGL context.";
} }
[EAGLContext setCurrentContext:mContext];
if (![EAGLContext setCurrentContext:mContext])
{
return egl::EglNotInitialized() << "Could set the EAGL context current.";
}
mThreadsWithContextCurrent.insert(std::this_thread::get_id());
// There is no equivalent getProcAddress in EAGL so we open the dylib directly // There is no equivalent getProcAddress in EAGL so we open the dylib directly
void *handle = dlopen(kOpenGLESDylibName, RTLD_NOW); void *handle = dlopen(kOpenGLESDylibName, RTLD_NOW);
...@@ -95,6 +100,10 @@ egl::Error DisplayEAGL::initialize(egl::Display *display) ...@@ -95,6 +100,10 @@ egl::Error DisplayEAGL::initialize(egl::Display *display)
return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable."; return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
} }
auto &attributes = display->getAttributeMap();
mDeviceContextIsVolatile =
attributes.get(EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE, GL_FALSE);
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -107,7 +116,37 @@ void DisplayEAGL::terminate() ...@@ -107,7 +116,37 @@ void DisplayEAGL::terminate()
{ {
[EAGLContext setCurrentContext:nil]; [EAGLContext setCurrentContext:nil];
mContext = nullptr; mContext = nullptr;
mThreadsWithContextCurrent.clear();
}
}
egl::Error DisplayEAGL::prepareForCall()
{
auto threadId = std::this_thread::get_id();
if (mDeviceContextIsVolatile ||
mThreadsWithContextCurrent.find(threadId) == mThreadsWithContextCurrent.end())
{
if (![getEAGLContextClass() setCurrentContext:mContext])
{
return egl::EglBadAlloc() << "Could not make device EAGL context current.";
}
mThreadsWithContextCurrent.insert(threadId);
}
return egl::NoError();
}
egl::Error DisplayEAGL::releaseThread()
{
auto threadId = std::this_thread::get_id();
if (mThreadsWithContextCurrent.find(threadId) != mThreadsWithContextCurrent.end())
{
if (![getEAGLContextClass() setCurrentContext:nil])
{
return egl::EglBadAlloc() << "Could not release device EAGL context.";
}
mThreadsWithContextCurrent.erase(threadId);
} }
return egl::NoError();
} }
SurfaceImpl *DisplayEAGL::createWindowSurface(const egl::SurfaceState &state, SurfaceImpl *DisplayEAGL::createWindowSurface(const egl::SurfaceState &state,
......
...@@ -643,6 +643,36 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform, ...@@ -643,6 +643,36 @@ Error ValidateGetPlatformDisplayCommon(EGLenum platform,
case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE: case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
luidSpecified = true; luidSpecified = true;
break; break;
case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE:
// The property does not have an effect if it's not active, so do not check
// for non-support.
switch (value)
{
case EGL_FALSE:
case EGL_TRUE:
break;
default:
return EglBadAttribute()
<< "Invalid value for "
"EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
"EAGL_ANGLE attrib";
}
break;
case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE:
// The property does not have an effect if it's not active, so do not check
// for non-support.
switch (value)
{
case EGL_FALSE:
case EGL_TRUE:
break;
default:
return EglBadAttribute()
<< "Invalid value for "
"EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
"CGL_ANGLE attrib";
}
break;
default: default:
break; break;
} }
......
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