Diff
Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/ChangeLog 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog 2020-10-02 07:05:42 UTC (rev 267869)
@@ -1,3 +1,60 @@
+2020-10-02 Kimmo Kinnunen <[email protected]>
+
+ [iOS WK1] Crashes when using ANGLE WebGL from another thread
+ https://bugs.webkit.org/show_bug.cgi?id=216106
+ <rdar://problem/68602452>
+
+ Reviewed by Kenneth Russell.
+
+ 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.
+
+ * extensions/EGL_ANGLE_platform_angle_device_context_volatile_cgl.txt: Added.
+ * extensions/EGL_ANGLE_platform_angle_device_context_volatile_eagl.txt: Added.
+ * include/EGL/eglext_angle.h:
+ * src/libANGLE/Caps.cpp:
+ (egl::DeviceExtensions::getStrings const):
+ (egl::ClientExtensions::getStrings const):
+ * src/libANGLE/Caps.h:
+ * src/libANGLE/Display.cpp:
+ (egl::Display::prepareForCall):
+ (egl::Display::releaseThread):
+ (egl::GenerateClientExtensions):
+ * src/libANGLE/Display.h:
+ * src/libANGLE/renderer/DisplayImpl.cpp:
+ (rx::DisplayImpl::prepareForCall):
+ (rx::DisplayImpl::releaseThread):
+ * src/libANGLE/renderer/DisplayImpl.h:
+ * src/libANGLE/renderer/gl/cgl/DisplayCGL.h:
+ * src/libANGLE/renderer/gl/cgl/DisplayCGL.mm:
+ (rx::DisplayCGL::initialize):
+ (rx::DisplayCGL::terminate):
+ (rx::DisplayCGL::prepareForCall):
+ (rx::DisplayCGL::releaseThread):
+ (rx::DisplayCGL::makeCurrent):
+ * src/libANGLE/renderer/gl/eagl/DisplayEAGL.h:
+ * src/libANGLE/renderer/gl/eagl/DisplayEAGL.mm:
+ (rx::DisplayEAGL::initialize):
+ (rx::DisplayEAGL::terminate):
+ (rx::DisplayEAGL::prepareForCall):
+ (rx::DisplayEAGL::releaseThread):
+ * src/libANGLE/validationEGL.cpp:
+ * src/libGLESv2/entry_points_egl.cpp:
+ * src/libGLESv2/entry_points_egl_ext.cpp:
+
2020-09-29 James Darpinian <[email protected]>
Fix EXT_color_buffer_half_float on iOS
Added: trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_cgl.txt (0 => 267869)
--- trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_cgl.txt (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_cgl.txt 2020-10-02 07:05:42 UTC (rev 267869)
@@ -0,0 +1,90 @@
+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
Added: trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_eagl.txt (0 => 267869)
--- trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_eagl.txt (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/extensions/EGL_ANGLE_platform_angle_device_context_volatile_eagl.txt 2020-10-02 07:05:42 UTC (rev 267869)
@@ -0,0 +1,90 @@
+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
Modified: trunk/Source/ThirdParty/ANGLE/include/EGL/eglext_angle.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/include/EGL/eglext_angle.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/include/EGL/eglext_angle.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -116,6 +116,16 @@
#define EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE 0x3481
#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
#define EGL_ANGLE_x11_visual
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -1418,6 +1418,8 @@
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_eagl", deviceEAGL, &extensionStrings);
+
// clang-format on
return extensionStrings;
@@ -1445,6 +1447,8 @@
InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_metal", platformANGLEMetal, &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_d3d11", deviceCreationD3D11, &extensionStrings);
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/Caps.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -1145,6 +1145,12 @@
// EGL_ANGLE_platform_angle_context_virtualization
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
bool deviceCreation = false;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -955,6 +955,16 @@
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
{
return mConfigSet.filter(attribs);
@@ -1544,6 +1554,14 @@
extensions.platformANGLEDeviceTypeEGLANGLE = true;
#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.debug = true;
extensions.explicitContext = true;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/Display.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -102,6 +102,13 @@
Error initialize();
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 *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -23,6 +23,16 @@
ASSERT(mState.surfaceSet.empty());
}
+egl::Error DisplayImpl::prepareForCall()
+{
+ return egl::NoError();
+}
+
+egl::Error DisplayImpl::releaseThread()
+{
+ return egl::NoError();
+}
+
const egl::DisplayExtensions &DisplayImpl::getExtensions() const
{
if (!mExtensionsInitialized)
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/DisplayImpl.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -67,11 +67,14 @@
virtual egl::Error initialize(egl::Display *display) = 0;
virtual void terminate() = 0;
+ virtual egl::Error prepareForCall();
+ virtual egl::Error releaseThread();
virtual egl::Error makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context) = 0;
+
virtual egl::ConfigSet generateConfigs() = 0;
virtual bool testDeviceLost() = 0;
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_GL_CGL_DISPLAYCGL_H_
#include <thread>
+#include <unordered_set>
#include "libANGLE/renderer/gl/DisplayGL.h"
@@ -32,6 +33,8 @@
egl::Error initialize(egl::Display *display) override;
void terminate() override;
+ egl::Error prepareForCall() override;
+ egl::Error releaseThread() override;
egl::Error makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
@@ -103,7 +106,7 @@
egl::Display *mEGLDisplay;
CGLContextObj mContext;
- std::unordered_map<std::thread::id, CGLContextObj> mCurrentContexts;
+ std::unordered_set<std::thread::id> mThreadsWithCurrentContext;
CGLPixelFormatObj mPixelFormat;
bool mSupportsGPUSwitching;
uint64_t mCurrentGPUID;
@@ -113,6 +116,7 @@
// 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.
double mLastDiscreteGPUUnrefTime;
+ bool mDeviceContextIsVolatile = false;
};
} // namespace rx
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/cgl/DisplayCGL.mm 2020-10-02 07:05:42 UTC (rev 267869)
@@ -184,10 +184,12 @@
mCurrentGPUID = angle::GetGpuIDFromDisplayID(kCGDirectMainDisplay);
}
- CGLSetCurrentContext(mContext);
+ if (CGLSetCurrentContext(mContext) != kCGLNoError)
+ {
+ return egl::EglNotInitialized() << "Could not make the CGL context current.";
+ }
+ mThreadsWithCurrentContext.insert(std::this_thread::get_id());
- mCurrentContexts[std::this_thread::get_id()] = mContext;
-
// There is no equivalent getProcAddress in CGL so we open the dylib directly
void *handle = dlopen(kDefaultOpenGLDylibName, RTLD_NOW);
if (!handle)
@@ -210,6 +212,9 @@
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);
}
@@ -223,12 +228,12 @@
CGLDestroyPixelFormat(mPixelFormat);
mPixelFormat = nullptr;
}
- mCurrentContexts.clear();
if (mContext != nullptr)
{
CGLSetCurrentContext(nullptr);
CGLDestroyContext(mContext);
mContext = nullptr;
+ mThreadsWithCurrentContext.clear();
}
if (mDiscreteGPUPixelFormat != nullptr)
{
@@ -238,23 +243,41 @@
}
}
+egl::Error DisplayCGL::prepareForCall()
+{
+ ASSERT(mContext);
+ 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::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context)
{
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(drawSurface, readSurface, context);
}
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.h (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -13,6 +13,9 @@
#if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || (defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64))
+#include <thread>
+#include <unordered_set>
+
#include "libANGLE/renderer/gl/DisplayGL.h"
#ifdef __OBJC__
@@ -35,6 +38,8 @@
egl::Error initialize(egl::Display *display) override;
void terminate() override;
+ egl::Error prepareForCall() override;
+ egl::Error releaseThread() override;
SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
@@ -93,6 +98,8 @@
egl::Display *mEGLDisplay;
EAGLContextObj mContext;
+ std::unordered_set<std::thread::id> mThreadsWithContextCurrent;
+ bool mDeviceContextIsVolatile = false;
};
} // namespace rx
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.mm (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.mm 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/renderer/gl/eagl/DisplayEAGL.mm 2020-10-02 07:05:42 UTC (rev 267869)
@@ -75,8 +75,12 @@
{
return egl::EglNotInitialized() << "Could not create the EAGL context.";
}
- [getEAGLContextClass() setCurrentContext:mContext];
+ if (![getEAGLContextClass() 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
void *handle = dlopen(kOpenGLESDylibName, RTLD_NOW);
if (!handle)
@@ -95,6 +99,9 @@
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);
}
@@ -108,9 +115,38 @@
[getEAGLContextClass() setCurrentContext:nil];
[mContext release];
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,
EGLNativeWindowType window,
const egl::AttributeMap &attribs)
Modified: trunk/Source/ThirdParty/ANGLE/src/libANGLE/validationEGL.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libANGLE/validationEGL.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libANGLE/validationEGL.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -643,6 +643,34 @@
case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
luidSpecified = true;
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:
break;
}
Modified: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -105,7 +105,8 @@
egl::Display *display = static_cast<egl::Display *>(dpy);
ANGLE_EGL_TRY_RETURN(thread, ValidateTerminate(display), "eglTerminate",
GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglTerminate",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, display->makeCurrent(thread, nullptr, nullptr, nullptr),
"eglTerminate", GetDisplayIfValid(display), EGL_FALSE);
SetContextCurrent(thread, nullptr);
@@ -127,6 +128,8 @@
{
ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglQueryString",
GetDisplayIfValid(display), nullptr);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryString",
+ GetDisplayIfValid(display), nullptr);
}
const char *result;
@@ -255,6 +258,8 @@
ANGLE_EGL_TRY_RETURN(thread,
ValidateCreateWindowSurface(display, configuration, win, attributes),
"eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
@@ -281,7 +286,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateCreatePbufferSurface(display, configuration, attributes),
"eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferSurface",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface),
"eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
@@ -310,7 +316,8 @@
ANGLE_EGL_TRY_RETURN(thread,
ValidateCreatePixmapSurface(display, configuration, pixmap, attributes),
"eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePixmapSurface",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
display->createPixmapSurface(configuration, pixmap, attributes, &surface),
@@ -332,7 +339,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySurface(display, eglSurface, surface),
"eglDestroySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySurface",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface",
GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
@@ -352,12 +360,13 @@
(uintptr_t)dpy, (uintptr_t)surface, attribute, (uintptr_t)value);
Thread *thread = egl::GetCurrentThread();
- const egl::Display *display = static_cast<const egl::Display *>(dpy);
+ egl::Display *display = static_cast<egl::Display *>(dpy);
const Surface *eglSurface = static_cast<const Surface *>(surface);
ANGLE_EGL_TRY_RETURN(thread, ValidateQuerySurface(display, eglSurface, attribute, value),
"eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, QuerySurfaceAttrib(display, eglSurface, attribute, value),
"eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
@@ -385,7 +394,8 @@
ANGLE_EGL_TRY_RETURN(thread,
ValidateCreateContext(display, configuration, sharedGLContext, attributes),
"eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateContext",
+ GetDisplayIfValid(display), EGL_NO_CONTEXT);
gl::Context *context = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
display->createContext(configuration, sharedGLContext, thread->getAPI(),
@@ -408,7 +418,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDestroyContext(display, context, ctx), "eglDestroyContext",
GetContextIfValid(display, context), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyContext",
+ GetDisplayIfValid(display), EGL_FALSE);
bool contextWasCurrent = context == thread->getContext();
ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext",
@@ -443,7 +454,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateMakeCurrent(display, drawSurface, readSurface, context),
"eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglMakeCurrent",
+ GetDisplayIfValid(display), EGL_FALSE);
Surface *previousDraw = thread->getCurrentDrawSurface();
Surface *previousRead = thread->getCurrentReadSurface();
gl::Context *previousContext = thread->getContext();
@@ -517,7 +529,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateQueryContext(display, context, attribute, value),
"eglQueryContext", GetContextIfValid(display, context), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryContext",
+ GetDisplayIfValid(display), EGL_FALSE);
QueryContextAttrib(context, attribute, value);
thread->setSuccess();
@@ -534,6 +547,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglWaitGL", GetDisplayIfValid(display),
EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitGL",
+ GetDisplayIfValid(display), EGL_FALSE);
// eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
// OpenGL ES we can do the call directly.
@@ -554,6 +569,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateWaitNative(display, engine), "eglWaitNative",
GetThreadIfValid(thread), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitNative",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative",
GetThreadIfValid(thread), EGL_FALSE);
@@ -574,6 +591,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateSwapBuffers(thread, display, eglSurface), "eglSwapBuffers",
GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffers",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers",
GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
@@ -598,7 +617,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateCopyBuffers(display, eglSurface), "eglCopyBuffers",
GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCopyBuffers",
+ GetDisplayIfValid(display), EGL_FALSE);
UNIMPLEMENTED(); // FIXME
thread->setSuccess();
@@ -622,7 +642,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateBindTexImage(display, eglSurface, surface, buffer, context, &textureObject),
"eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglBindTexImage",
+ GetDisplayIfValid(display), EGL_FALSE);
if (context)
{
ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer),
@@ -650,7 +671,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateSurfaceAttrib(display, eglSurface, attribute, value),
"eglSurfaceAttrib", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSurfaceAttrib",
+ GetDisplayIfValid(display), EGL_FALSE);
SetSurfaceAttrib(eglSurface, attribute, value);
thread->setSuccess();
@@ -671,6 +693,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateReleaseTexImage(display, eglSurface, surface, buffer),
"eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage",
+ GetDisplayIfValid(display), EGL_FALSE);
gl::Texture *texture = eglSurface->getBoundTexture();
if (texture)
@@ -697,7 +721,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateSwapInterval(display, draw_surface, context),
"eglSwapInterval", GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapInterval",
+ GetDisplayIfValid(display), EGL_FALSE);
const egl::Config *surfaceConfig = draw_surface->getConfig();
EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval),
surfaceConfig->maxSwapInterval);
@@ -759,7 +784,8 @@
thread,
ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes),
"eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferFromClientBuffer",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
display->createPbufferFromClientBuffer(configuration, buftype, buffer,
@@ -781,16 +807,19 @@
gl::Context *previousContext = thread->getContext();
egl::Display *previousDisplay = thread->getDisplay();
- // Only call makeCurrent if the context or surfaces have changed.
- if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE ||
- previousContext != EGL_NO_CONTEXT)
- {
- if (previousDisplay != EGL_NO_DISPLAY)
+ if (previousDisplay != EGL_NO_DISPLAY) {
+ ANGLE_EGL_TRY_RETURN(thread, previousDisplay->prepareForCall(), "eglReleaseThread",
+ GetDisplayIfValid(previousDisplay), EGL_FALSE);
+ // Only call makeCurrent if the context or surfaces have changed.
+ if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE ||
+ previousContext != EGL_NO_CONTEXT)
{
ANGLE_EGL_TRY_RETURN(thread,
previousDisplay->makeCurrent(thread, nullptr, nullptr, nullptr),
"eglReleaseThread", nullptr, EGL_FALSE);
}
+ ANGLE_EGL_TRY_RETURN(thread, previousDisplay->releaseThread(), "eglReleaseThread",
+ GetDisplayIfValid(previousDisplay), EGL_FALSE);
SetContextCurrent(thread, nullptr);
}
@@ -810,7 +839,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDisplay(display), "eglWaitClient",
GetContextIfValid(display, context), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitClient",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient",
GetContextIfValid(display, context), EGL_FALSE);
@@ -849,7 +879,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateCreateSync(display, type, attributes, currentDisplay, currentContext),
"eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync",
+ GetDisplayIfValid(display), EGL_FALSE);
egl::Sync *syncObject = nullptr;
ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
"eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
@@ -870,7 +901,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySync(display, syncObject), "eglDestroySync",
GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync",
+ GetDisplayIfValid(display), EGL_FALSE);
display->destroySync(syncObject);
thread->setSuccess();
@@ -891,7 +923,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateClientWaitSync(display, syncObject, flags, timeout),
"eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync",
+ GetDisplayIfValid(display), EGL_FALSE);
gl::Context *currentContext = thread->getContext();
EGLint syncStatus = EGL_FALSE;
ANGLE_EGL_TRY_RETURN(
@@ -954,6 +987,8 @@
thread->setError(error, GetDebug(), "eglCreateImage", GetDisplayIfValid(display));
return EGL_NO_IMAGE;
}
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImage",
+ GetDisplayIfValid(display), EGL_FALSE);
Image *image = nullptr;
error = display->createImage(context, target, buffer, attributes, &image);
@@ -982,7 +1017,8 @@
thread->setError(error, GetDebug(), "eglDestroyImage", GetImageIfValid(display, img));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImage",
+ GetDisplayIfValid(display), EGL_FALSE);
display->destroyImage(img);
thread->setSuccess();
@@ -1043,12 +1079,13 @@
ANGLE_EGL_TRY_RETURN(thread,
ValidateCreateWindowSurface(display, configuration, win, attributes),
- "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(thread,
display->createWindowSurface(configuration, win, attributes, &surface),
- "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
+ "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
return static_cast<EGLSurface>(surface);
}
@@ -1075,7 +1112,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateCreatePixmapSurface(display, configuration, pixmap, attributes),
"eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurface",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
egl::Surface *surface = nullptr;
ANGLE_EGL_TRY_RETURN(
thread, display->createPixmapSurface(configuration, pixmap, attributes, &surface),
@@ -1099,7 +1137,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateWaitSync(display, context, syncObject, flags),
"eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync",
+ GetDisplayIfValid(display), EGL_FALSE);
gl::Context *currentContext = thread->getContext();
ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
"eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
Modified: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl_ext.cpp (267868 => 267869)
--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl_ext.cpp 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/entry_points_egl_ext.cpp 2020-10-02 07:05:42 UTC (rev 267869)
@@ -86,7 +86,8 @@
GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurfacePointerANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
error = eglSurface->querySurfacePointerANGLE(attribute, value);
if (error.isError())
{
@@ -151,7 +152,8 @@
thread->setSuccess();
return EGL_TRUE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglPostSubBufferNV",
+ GetDisplayIfValid(display), EGL_FALSE);
// TODO(jmadill): Validate Surface is bound to the thread.
error = eglSurface->postSubBuffer(thread->getContext(), x, y, width, height);
if (error.isError())
@@ -223,7 +225,8 @@
thread,
ValidateCreatePlatformWindowSurfaceEXT(display, configuration, native_window, attributes),
"eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurfaceEXT",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
thread->setError(EglBadDisplay() << "CreatePlatformWindowSurfaceEXT unimplemented.", GetDebug(),
"eglCreatePlatformWindowSurfaceEXT", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
@@ -250,7 +253,8 @@
thread,
ValidateCreatePlatformPixmapSurfaceEXT(display, configuration, native_pixmap, attributes),
"eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display), EGL_NO_SURFACE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurfaceEXT",
+ GetDisplayIfValid(display), EGL_NO_SURFACE);
thread->setError(EglBadDisplay() << "CreatePlatformPixmapSurfaceEXT unimplemented.", GetDebug(),
"eglCreatePlatformPixmapSurfaceEXT", GetDisplayIfValid(display));
return EGL_NO_SURFACE;
@@ -275,10 +279,11 @@
thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
return EGL_FALSE;
}
-
+ egl::Display *owningDisplay = dev->getOwningDisplay();
+ ANGLE_EGL_TRY_RETURN(thread, owningDisplay->prepareForCall(), "eglQueryDeviceAttribEXT",
+ GetDisplayIfValid(owningDisplay), EGL_FALSE);
// If the device was created by (and is owned by) a display, and that display doesn't support
// device querying, then this call should fail
- egl::Display *owningDisplay = dev->getOwningDisplay();
if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
{
thread->setError(EglBadAccess() << "Device wasn't created using eglCreateDeviceANGLE, "
@@ -351,7 +356,9 @@
thread->setError(error, GetDebug(), "eglQueryDeviceStringEXT", GetDeviceIfValid(dev));
return EGL_FALSE;
}
-
+ egl::Display *owningDisplay = dev->getOwningDisplay();
+ ANGLE_EGL_TRY_RETURN(thread, owningDisplay->prepareForCall(), "eglQueryDeviceStringEXT",
+ GetDisplayIfValid(owningDisplay), EGL_FALSE);
const char *result;
switch (name)
{
@@ -381,7 +388,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateQueryDisplayAttribEXT(display, attribute),
"eglQueryDisplayAttribEXT", GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryDisplayAttribEXT",
+ GetDisplayIfValid(display), EGL_FALSE);
*value = display->queryAttrib(attribute);
thread->setSuccess();
return EGL_TRUE;
@@ -402,7 +410,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateQueryDisplayAttribANGLE(display, attribute),
"eglQueryDisplayAttribANGLE", GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryDisplayAttribANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
*value = display->queryAttrib(attribute);
thread->setSuccess();
return EGL_TRUE;
@@ -433,7 +442,8 @@
thread->setError(error, GetDebug(), "eglCreateImageKHR", GetDisplayIfValid(display));
return EGL_NO_IMAGE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImageKHR",
+ GetDisplayIfValid(display), EGL_NO_IMAGE);
Image *image = nullptr;
error = display->createImage(context, target, buffer, attributes, &image);
if (error.isError())
@@ -462,7 +472,8 @@
thread->setError(error, GetDebug(), "eglDestroyImageKHR", GetImageIfValid(display, img));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImageKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
display->destroyImage(img);
thread->setSuccess();
@@ -538,7 +549,8 @@
thread->setError(error, GetDebug(), "eglCreateStreamKHR", GetDisplayIfValid(display));
return EGL_NO_STREAM_KHR;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateStreamKHR",
+ GetDisplayIfValid(display), EGL_NO_STREAM_KHR);
Stream *stream;
error = display->createStream(attributes, &stream);
if (error.isError())
@@ -568,7 +580,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyStreamKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
display->destroyStream(streamObject);
thread->setSuccess();
@@ -597,7 +610,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamAttribKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
switch (attribute)
{
case EGL_CONSUMER_LATENCY_USEC_KHR:
@@ -636,7 +650,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStreamKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
switch (attribute)
{
case EGL_STREAM_STATE_KHR:
@@ -678,7 +693,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStreamu64KHR",
+ GetDisplayIfValid(display), EGL_FALSE);
switch (attribute)
{
case EGL_PRODUCER_FRAME_KHR:
@@ -713,7 +729,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerGLTextureExternalKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->createConsumerGLTextureExternal(AttributeMap(), context);
if (error.isError())
{
@@ -744,7 +761,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerAcquireKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->consumerAcquire(context);
if (error.isError())
{
@@ -775,7 +793,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerReleaseKHR",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->consumerRelease(context);
if (error.isError())
{
@@ -811,7 +830,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamConsumerGLTextureExternalAttribsNV",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->createConsumerGLTextureExternal(attributes, context);
if (error.isError())
{
@@ -845,7 +865,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateStreamProducerD3DTextureANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->createProducerD3D11Texture(attributes);
if (error.isError())
{
@@ -882,7 +903,8 @@
GetStreamIfValid(display, streamObject));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglStreamPostD3DTextureANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
error = streamObject->postD3D11Texture(texture, attributes);
if (error.isError())
{
@@ -915,7 +937,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateCreateSyncKHR(display, type, attributes, currentDisplay, currentContext),
"eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync",
+ GetDisplayIfValid(display), EGL_NO_SYNC);
egl::Sync *syncObject = nullptr;
ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
"eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
@@ -936,7 +959,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDestroySync(display, syncObject), "eglDestroySync",
GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync",
+ GetDisplayIfValid(display), EGL_FALSE);
display->destroySync(syncObject);
thread->setSuccess();
@@ -960,7 +984,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateClientWaitSync(display, syncObject, flags, timeout),
"eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync",
+ GetDisplayIfValid(display), EGL_FALSE);
gl::Context *currentContext = thread->getContext();
EGLint syncStatus = EGL_FALSE;
ANGLE_EGL_TRY_RETURN(
@@ -988,7 +1013,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateGetSyncAttribKHR(display, syncObject, attribute, value),
"eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetSyncAttrib",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, value),
"eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
@@ -1011,7 +1037,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateWaitSync(display, context, syncObject, flags),
"eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync",
+ GetDisplayIfValid(display), EGL_FALSE);
gl::Context *currentContext = thread->getContext();
ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
"eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
@@ -1043,7 +1070,8 @@
GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetMscRateANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
error = eglSurface->getMscRate(numerator, denominator);
if (error.isError())
{
@@ -1080,7 +1108,8 @@
GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetSyncValuesCHROMIUM",
+ GetDisplayIfValid(display), EGL_FALSE);
error = eglSurface->getSyncValues(ust, msc, sbc);
if (error.isError())
{
@@ -1116,7 +1145,8 @@
GetSurfaceIfValid(display, eglSurface));
return EGL_FALSE;
}
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffersWithDamageEXT",
+ GetDisplayIfValid(display), EGL_FALSE);
error = eglSurface->swapWithDamage(thread->getContext(), rects, n_rects);
if (error.isError())
{
@@ -1145,6 +1175,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidatePresentationTimeANDROID(display, eglSurface, time),
"eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglPresentationTimeANDROID",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, eglSurface->setPresentationTime(time),
"eglPresentationTimeANDROID", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
@@ -1166,7 +1198,8 @@
ANGLE_EGL_TRY(thread, ValidateSetBlobCacheANDROID(display, set, get),
"eglSetBlobCacheFuncsANDROID", GetDisplayIfValid(display));
-
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglSetBlobCacheFuncsANDROID",
+ GetDisplayIfValid(display));
thread->setSuccess();
display->setBlobCacheFuncs(set, get);
}
@@ -1181,7 +1214,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheGetAttribANGLE(display, attrib),
"eglProgramCacheGetAttribANGLE", GetDisplayIfValid(display), 0);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglProgramCacheGetAttribANGLE",
+ GetDisplayIfValid(display), 0);
thread->setSuccess();
return display->programCacheGetAttrib(attrib);
}
@@ -1206,7 +1240,8 @@
ANGLE_EGL_TRY(thread,
ValidateProgramCacheQueryANGLE(display, index, key, keysize, binary, binarysize),
"eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
-
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglProgramCacheQueryANGLE",
+ GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, display->programCacheQuery(index, key, keysize, binary, binarysize),
"eglProgramCacheQueryANGLE", GetDisplayIfValid(display));
@@ -1231,7 +1266,8 @@
ANGLE_EGL_TRY(thread,
ValidateProgramCachePopulateANGLE(display, key, keysize, binary, binarysize),
"eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
-
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglProgramCachePopulateANGLE",
+ GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, display->programCachePopulate(key, keysize, binary, binarysize),
"eglProgramCachePopulateANGLE", GetDisplayIfValid(display));
@@ -1249,7 +1285,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateProgramCacheResizeANGLE(display, limit, mode),
"eglProgramCacheResizeANGLE", GetDisplayIfValid(display), 0);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglProgramCacheResizeANGLE",
+ GetDisplayIfValid(display), 0);
thread->setSuccess();
return display->programCacheResize(limit, mode);
}
@@ -1340,7 +1377,13 @@
GetLabeledObjectIfValid(thread, display, objectTypePacked, object));
return error.getCode();
}
-
+ error = display->prepareForCall();
+ if (error.isError())
+ {
+ thread->setError(error, GetDebug(), "eglLabelObjectKHR",
+ GetDisplayIfValid(display));
+ return error.getCode();
+ }
LabeledObject *labeledObject =
GetLabeledObjectIfValid(thread, display, objectTypePacked, object);
ASSERT(labeledObject != nullptr);
@@ -1394,6 +1437,8 @@
thread,
ValidateGetCompositorTimingANDROID(display, eglSurface, numTimestamps, names, values),
"eglGetCompositorTimingANDROIDD", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetCompositorTimingANDROIDD",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, eglSurface->getCompositorTiming(numTimestamps, names, values),
"eglGetCompositorTimingANDROIDD", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
@@ -1418,6 +1463,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateGetNextFrameIdANDROID(display, eglSurface, frameId),
"eglGetNextFrameIdANDROID", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetNextFrameIdANDROID",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, eglSurface->getNextFrameId(frameId), "eglGetNextFrameIdANDROID",
GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
@@ -1443,7 +1490,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateGetFrameTimestampSupportedANDROID(display, eglSurface, timestampInternal),
"eglQueryTimestampSupportedANDROID", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryTimestampSupportedANDROID",
+ GetDisplayIfValid(display), EGL_FALSE);
thread->setSuccess();
return eglSurface->getSupportedTimestamps().test(timestampInternal);
}
@@ -1472,6 +1520,8 @@
numTimestamps, timestamps, values),
"eglGetFrameTimestampsANDROID", GetSurfaceIfValid(display, eglSurface),
EGL_FALSE);
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglGetFrameTimestampsANDROID",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(
thread, eglSurface->getFrameTimestamps(frameId, numTimestamps, timestamps, values),
"eglGetFrameTimestampsANDROID", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
@@ -1494,7 +1544,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateQueryStringiANGLE(display, name, index),
"eglQueryStringiANGLE", GetDisplayIfValid(display), nullptr);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryStringiANGLE",
+ GetDisplayIfValid(display), nullptr);
thread->setSuccess();
return display->queryStringi(name, index);
}
@@ -1526,7 +1577,8 @@
ANGLE_EGL_TRY_RETURN(thread, ValidateDupNativeFenceFDANDROID(display, syncObject),
"eglDupNativeFenceFDANDROID", GetSyncIfValid(display, syncObject),
EGL_NO_NATIVE_FENCE_FD_ANDROID);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDupNativeFenceFDANDROID",
+ GetDisplayIfValid(display), EGL_NO_NATIVE_FENCE_FD_ANDROID);
EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
ANGLE_EGL_TRY_RETURN(thread, syncObject->dupNativeFenceFD(display, &result),
"eglDupNativeFenceFDANDROID", GetSyncIfValid(display, syncObject),
@@ -1552,7 +1604,8 @@
ANGLE_EGL_TRY_RETURN(
thread, ValidateSwapBuffersWithFrameTokenANGLE(display, eglSurface, frametoken),
"eglSwapBuffersWithFrameTokenANGLE", GetDisplayIfValid(display), EGL_FALSE);
-
+ ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffersWithFrameTokenANGLE",
+ GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, eglSurface->swapWithFrameToken(thread->getContext(), frametoken),
"eglSwapBuffersWithFrameTokenANGLE", GetDisplayIfValid(display),
EGL_FALSE);
@@ -1573,6 +1626,8 @@
ANGLE_EGL_TRY(thread, ValidateContext(display, context), "eglReleaseHighPowerGPUANGLE",
GetDisplayIfValid(display));
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglReleaseHighPowerGPUANGLE",
+ GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, context->releaseHighPowerGPU(), "eglReleaseHighPowerGPUANGLE",
GetDisplayIfValid(display));
@@ -1591,6 +1646,8 @@
ANGLE_EGL_TRY(thread, ValidateContext(display, context), "eglReacquireHighPowerGPUANGLE",
GetDisplayIfValid(display));
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglReacquireHighPowerGPUANGLE",
+ GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, context->reacquireHighPowerGPU(), "eglReacquireHighPowerGPUANGLE",
GetDisplayIfValid(display));
@@ -1607,6 +1664,8 @@
ANGLE_EGL_TRY(thread, ValidateDisplay(display), "eglHandleGPUSwitchANGLE",
GetDisplayIfValid(display));
+ ANGLE_EGL_TRY(thread, display->prepareForCall(), "eglHandleGPUSwitchANGLE",
+ GetDisplayIfValid(display));
ANGLE_EGL_TRY(thread, display->handleGPUSwitch(), "eglHandleGPUSwitchANGLE",
GetDisplayIfValid(display));
Modified: trunk/Source/WebCore/ChangeLog (267868 => 267869)
--- trunk/Source/WebCore/ChangeLog 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/WebCore/ChangeLog 2020-10-02 07:05:42 UTC (rev 267869)
@@ -1,3 +1,75 @@
+2020-10-02 Kimmo Kinnunen <[email protected]>
+
+ [iOS WK1] Crashes when using ANGLE WebGL from another thread
+ https://bugs.webkit.org/show_bug.cgi?id=216106
+ <rdar://problem/68602452>
+
+ Reviewed by Kenneth Russell.
+
+ Source of the bug comes from following:
+ - WK1 might run WebKit code in client main thread.
+ - WK1 might run Webkit code in web thread.
+ - WebKit code might run WebGL payload, notably access
+ GraphicsContextGL classes.
+ Client is able to modify EAGL/CGL current context.
+
+ The change to ANGLE incurred two distinct behavior changes
+ compared to raw EAGL / CGL:
+ 1) Before: context was set current before any GL call
+ After: context was set current only if EGL current context
+ had been changed. (Explicit code as well as ANGLE implementation
+ optimization.)
+
+ 2) Before: context being used was able to be current in
+ multiple threads at the same time. (EAGL/CGL feature)
+ After: context cannot be current in multiple threads
+ at the same time. (EGL feature)
+
+ Change in behavior 1) caused ANGLE to sometimes use
+ the EAGL/CGL context of the client instead of
+ the real context that ANGLE created.
+ Fix this by introducing
+ EGL_ANGLE_platform_angle_device_context_volatile_eagl
+ and
+ EGL_ANGLE_platform_angle_device_context_volatile_cgl
+ which make ANGLE sync the context on each eglMakeCurrent
+ eglReleaseThread and eglTerminate.
+
+ Change in behavior 2) caused ANGLE to use uninitialized
+ context object from one thread, if the real context object
+ was current in another thread.
+ Fix this by considering "GraphicsContextGLOpenGL current context"
+ as part of "data that is owned by WebCoreThread lock".
+ The current context is set with lock held, implicitly.
+ The current context is released when lock is released.
+ When the lock is not held, GraphicsContextGLOpenGL current context
+ is nullptr.
+
+ Adds soft linking for EAGL for the purpose of testing this in
+ TestWebKitAPI. The case of Apple Silicon Mac may sometimes
+ use CGL and sometimes EAGL, and the test should test that
+ client overriding both contexts will not cause problems.
+
+ Fix ANGLE header include path:
+ - Do not include ANGLE in the path, as files are included with ANGLE/
+ - Add WK_ALTERNATE_FRAMEWORKS_DIR so that SDK_VARIANT=iosmac
+ e.g. maccatalyst builds work
+ Previously the ANGLE was not included from ThirdParty/ANGLE, rather
+ "WebKit SDK".
+
+ * Configurations/WebCore.xcconfig:
+ * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+ (WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
+ (WebCore::GraphicsContextGLOpenGL::makeContextCurrent):
+ (WebCore::GraphicsContextGLOpenGL::releaseCurrentContext):
+ (WebCore::GraphicsContextGLOpenGL::checkGPUStatus):
+ (WebCore::GraphicsContextGLOpenGL::allowOfflineRenderers const):
+ * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+ * platform/ios/wak/WebCoreThread.mm:
+ (WebThreadUnlockFromAnyThread):
+ (_WebThreadUnlock):
+
2020-10-01 Rob Buis <[email protected]>
update FormData to latest spec webidl
Modified: trunk/Source/WebCore/Configurations/WebCore.xcconfig (267868 => 267869)
--- trunk/Source/WebCore/Configurations/WebCore.xcconfig 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/WebCore/Configurations/WebCore.xcconfig 2020-10-02 07:05:42 UTC (rev 267869)
@@ -48,7 +48,7 @@
LIBRARY_SEARCH_PATHS = $(inherited) "$(WK_LIBWEBRTC_LIBRARY_DIR)";
WEBKITADDITIONS_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include/WebKitAdditions $(SDKROOT)/usr/local/include/WebKitAdditions;
-ANGLE_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include/ANGLE $(SDKROOT)/usr/local/include/ANGLE;
+ANGLE_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)$(WK_ALTERNATE_FRAMEWORKS_DIR)/usr/local/include/ $(SDKROOT)$(WK_ALTERNATE_WEBKIT_SDK_PATH)/usr/local/include/;
LIBWEBRTC_HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include/webrtc $(SDKROOT)/usr/local/include/webrtc $(BUILT_PRODUCTS_DIR)/usr/local/include/webrtc/sdk/objc/Framework/Headers $(SDKROOT)/usr/local/include/webrtc/sdk/objc/Framework/Headers;
HEADER_SEARCH_PATHS = PAL ForwardingHeaders /usr/include/libxslt /usr/include/libxml2 "$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore" "$(BUILT_PRODUCTS_DIR)/usr/local/include" $(WEBKITADDITIONS_HEADER_SEARCH_PATHS) $(ANGLE_HEADER_SEARCH_PATHS) $(LIBWEBRTC_HEADER_SEARCH_PATHS) $(HEADER_SEARCH_PATHS) $(SRCROOT);
Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm (267868 => 267869)
--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm 2020-10-02 07:05:42 UTC (rev 267869)
@@ -80,6 +80,8 @@
#import "ExtensionsGLOpenGL.h"
#elif USE(ANGLE)
#import "ExtensionsGLANGLE.h"
+#import "RuntimeApplicationChecks.h"
+#import "WebCoreThread.h"
#endif
#if PLATFORM(MAC)
@@ -91,6 +93,69 @@
namespace WebCore {
+namespace {
+
+#if USE(ANGLE)
+
+#if ASSERT_ENABLED
+// Returns true if we have volatile context extension for the particular API or
+// if the particular API is not used.
+bool checkVolatileContextSupportIfDeviceExists(EGLDisplay display, const char* deviceContextVolatileExtension,
+ const char* deviceContextExtension, EGLint deviceContextType)
+{
+ const char *clientExtensions = EGL_QueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (clientExtensions && strstr(clientExtensions, deviceContextVolatileExtension))
+ return true;
+ EGLDeviceEXT device = EGL_NO_DEVICE_EXT;
+ if (!EGL_QueryDisplayAttribEXT(display, EGL_DEVICE_EXT, reinterpret_cast<EGLAttrib*>(&device)))
+ return true;
+ if (device == EGL_NO_DEVICE_EXT)
+ return true;
+ const char* deviceExtensions = EGL_QueryDeviceStringEXT(device, EGL_EXTENSIONS);
+ if (!deviceExtensions || !strstr(deviceExtensions, deviceContextExtension))
+ return true;
+ void* deviceContext = nullptr;
+ if (!EGL_QueryDeviceAttribEXT(device, deviceContextType, reinterpret_cast<EGLAttrib*>(&deviceContext)))
+ return true;
+ return !deviceContext;
+}
+#endif
+
+EGLDisplay InitializeEGLDisplay()
+{
+ EGLint majorVersion = 0;
+ EGLint minorVersion = 0;
+ EGLDisplay display;
+ bool shouldInitializeWithVolatileContextSupport = !isInWebProcess();
+ if (shouldInitializeWithVolatileContextSupport) {
+ // For WK1 type APIs we need to set "volatile platform context" for specific
+ // APIs, since client code will be able to override the thread-global context
+ // that ANGLE expects.
+ EGLint displayAttributes[] = {
+ EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE, EGL_TRUE,
+ EGL_NONE
+ };
+ display = EGL_GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, reinterpret_cast<void *>(EGL_DEFAULT_DISPLAY), displayAttributes);
+ } else
+ display = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
+
+ if (EGL_Initialize(display, &majorVersion, &minorVersion) == EGL_FALSE) {
+ LOG(WebGL, "EGLDisplay Initialization failed.");
+ return EGL_NO_DISPLAY;
+ }
+ LOG(WebGL, "ANGLE initialised Major: %d Minor: %d", majorVersion, minorVersion);
+ if (shouldInitializeWithVolatileContextSupport) {
+ // After initialization, EGL_DEFAULT_DISPLAY will return the platform-customized display.
+ ASSERT(display == EGL_GetDisplay(EGL_DEFAULT_DISPLAY));
+ ASSERT(checkVolatileContextSupportIfDeviceExists(display, "EGL_ANGLE_platform_device_context_volatile_eagl", "EGL_ANGLE_device_eagl", EGL_EAGL_CONTEXT_ANGLE));
+ ASSERT(checkVolatileContextSupportIfDeviceExists(display, "EGL_ANGLE_platform_device_context_volatile_cgl", "EGL_ANGLE_device_cgl", EGL_CGL_CONTEXT_ANGLE));
+ }
+ return display;
+}
+#endif
+}
+
static const unsigned statusCheckThreshold = 5;
// FIXME: This class is currently empty on Mac, but will get populated as
@@ -316,16 +381,9 @@
::glEnable(GraphicsContextGL::PRIMITIVE_RESTART);
#elif USE(ANGLE)
-
- m_displayObj = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
+ m_displayObj = InitializeEGLDisplay();
if (m_displayObj == EGL_NO_DISPLAY)
return;
- EGLint majorVersion, minorVersion;
- if (EGL_Initialize(m_displayObj, &majorVersion, &minorVersion) == EGL_FALSE) {
- LOG(WebGL, "EGLDisplay Initialization failed.");
- return;
- }
- LOG(WebGL, "ANGLE initialised Major: %d Minor: %d", majorVersion, minorVersion);
const char *displayExtensions = EGL_QueryString(m_displayObj, EGL_EXTENSIONS);
LOG(WebGL, "Extensions: %s", displayExtensions);
@@ -578,17 +636,13 @@
if (m_contextObj) {
GraphicsContextGLAttributes attrs = contextAttributes();
-
+ makeContextCurrent(); // TODO: check result.
#if USE(OPENGL_ES)
- makeContextCurrent();
[static_cast<EAGLContext *>(m_contextObj) renderbufferStorage:GL_RENDERBUFFER fromDrawable:nil];
::glDeleteRenderbuffers(1, &m_texture);
#elif USE(OPENGL)
- CGLContextObj cglContext = static_cast<CGLContextObj>(m_contextObj);
- CGLSetCurrentContext(cglContext);
::glDeleteTextures(1, &m_texture);
#elif USE(ANGLE)
- EGL_MakeCurrent(m_displayObj, EGL_NO_SURFACE, EGL_NO_SURFACE, m_contextObj);
gl::DeleteTextures(1, &m_texture);
#endif
@@ -707,12 +761,50 @@
if (currentContext != m_contextObj)
return CGLSetCurrentContext(static_cast<CGLContextObj>(m_contextObj)) == kCGLNoError;
#elif USE(ANGLE)
- if (EGL_GetCurrentContext() != m_contextObj)
- return EGL_MakeCurrent(m_displayObj, EGL_NO_SURFACE, EGL_NO_SURFACE, m_contextObj);
+ // ANGLE has an early out for case where nothing changes. Calling MakeCurrent
+ // is important to set volatile platform context. See InitializeEGLDisplay().
+ if (!EGL_MakeCurrent(m_displayObj, EGL_NO_SURFACE, EGL_NO_SURFACE, m_contextObj))
+ return false;
#endif
return true;
}
+#if PLATFORM(IOS_FAMILY) && USE(ANGLE)
+bool GraphicsContextGLOpenGL::releaseCurrentContext(ReleaseBehavior releaseBehavior)
+{
+ // At the moment this function is relevant only when web thread lock owns the GraphicsContextGLOpenGL current context.
+ ASSERT(!WebCore::isInWebProcess());
+
+ if (!EGL_BindAPI(EGL_OPENGL_ES_API))
+ return false;
+ if (EGL_GetCurrentContext() == EGL_NO_CONTEXT)
+ return true;
+
+ // At the time of writing, ANGLE does not flush on MakeCurrent. Since we are
+ // potentially switching threads, we should flush.
+ // Note: Here we assume also that ANGLE has only one platform context -- otherwise
+ // we would need to flush each EGL context that has been used.
+ gl::Flush();
+
+ // Unset the EGL current context, since the next access might be from another thread, and the
+ // context cannot be current on multiple threads.
+
+ if (releaseBehavior == ReleaseBehavior::ReleaseThreadResources) {
+ // Called when we do not know if we will ever see another call from this thread again.
+ // Unset the EGL current context by releasing whole EGL thread state.
+ // Theoretically ReleaseThread can reset the bound API, so the rest of the code mentions BindAPI/QueryAPI.
+ return EGL_ReleaseThread();
+ }
+ // On WebKit owned threads, WebKit is able to choose the time for the EGL cleanup.
+ // This is why we only unset the context.
+ // Note: At the time of writing the EGL cleanup is chosen to be not done at all.
+ EGLDisplay display = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
+ if (display == EGL_NO_DISPLAY)
+ return false;
+ return EGL_MakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+}
+#endif
+
void GraphicsContextGLOpenGL::checkGPUStatus()
{
if (m_failNextStatusCheck) {
@@ -724,6 +816,7 @@
#elif USE(OPENGL_ES)
[EAGLContext setCurrentContext:0];
#elif USE(ANGLE)
+ EGL_BindAPI(EGL_OPENGL_ES_API);
EGL_MakeCurrent(m_displayObj, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
#endif
return;
Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h (267868 => 267869)
--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h 2020-10-02 07:05:42 UTC (rev 267869)
@@ -119,6 +119,13 @@
#endif
bool makeContextCurrent();
+#if PLATFORM(IOS_FAMILY) && USE(ANGLE)
+ enum class ReleaseBehavior {
+ PreserveThreadResources,
+ ReleaseThreadResources
+ };
+ static bool releaseCurrentContext(ReleaseBehavior);
+#endif
void addClient(Client& client) { m_clients.add(&client); }
void removeClient(Client& client) { m_clients.remove(&client); }
Modified: trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm (267868 => 267869)
--- trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm 2020-10-02 07:05:42 UTC (rev 267869)
@@ -30,6 +30,7 @@
#import "CommonVM.h"
#import "FloatingPointEnvironment.h"
+#import "GraphicsContextGLOpenGL.h"
#import "Logging.h"
#import "RuntimeApplicationChecks.h"
#import "ThreadGlobalData.h"
@@ -59,6 +60,26 @@
#define DistantFuture (86400.0 * 2000 * 365.2425 + 86400.0) // same as +[NSDate distantFuture]
+namespace {
+// Release global state that is accessed from both web thread as well
+// as any client thread that calls into WebKit.
+void ReleaseWebThreadGlobalState()
+{
+ // GraphicsContextGLOpenGL current context is owned by the web thread lock. Release the context
+ // before the lock is released.
+
+ // In single-threaded environments we do not need to unset the context, as there should not be access from
+ // multiple threads.
+ ASSERT(WebThreadIsEnabled());
+ using ReleaseBehavior = WebCore::GraphicsContextGLOpenGL::ReleaseBehavior;
+ // For non-web threads, we don't know if we ever see another call from the thread.
+ ReleaseBehavior releaseBehavior =
+ WebThreadIsCurrent() ? ReleaseBehavior::PreserveThreadResources : ReleaseBehavior::ReleaseThreadResources;
+ WebCore::GraphicsContextGLOpenGL::releaseCurrentContext(releaseBehavior);
+}
+
+}
+
static const constexpr Seconds DelegateWaitInterval { 10_s };
static void _WebThreadAutoLock();
@@ -778,6 +799,8 @@
if (!webThreadStarted)
return;
ASSERT(!WebThreadIsCurrent());
+ ReleaseWebThreadGlobalState();
+
// No-op except from a secondary thread.
if (pthread_main_np())
return;
@@ -799,6 +822,8 @@
void _WebThreadUnlock()
{
+ ReleaseWebThreadGlobalState();
+
#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
lockCount--;
#if LOG_WEB_LOCK
Modified: trunk/Tools/ChangeLog (267868 => 267869)
--- trunk/Tools/ChangeLog 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Tools/ChangeLog 2020-10-02 07:05:42 UTC (rev 267869)
@@ -1,3 +1,24 @@
+2020-10-02 Kimmo Kinnunen <[email protected]>
+
+ [iOS WK1] Crashes when using ANGLE WebGL from another thread
+ https://bugs.webkit.org/show_bug.cgi?id=216106
+ <rdar://problem/68602452>
+
+ Reviewed by Kenneth Russell.
+
+ Add a WK1 test which runs WebGL code both in
+ client main thread and in web thread.
+ This tests the case where ANGLE EGL context is
+ not being held current in one thread while the
+ other thread runs WebGL and thus ANGLE EGL code.
+
+ * TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLNoCrashOnOtherThreadAccess.mm: Added.
+ (-[WebGLNoCrashOnOtherThreadAccessWebViewDelegate webViewDidFinishLoad:]):
+ (-[WebGLNoCrashOnOtherThreadAccessWebViewDelegate webView:shouldStartLoadWithRequest:navigationType:]):
+ (TestWebKitAPI::TEST):
+
2020-10-01 Aakash Jain <[email protected]>
Limit number of tests to log in case of large number of API test failures
Modified: trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig (267868 => 267869)
--- trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Tools/TestWebKitAPI/Configurations/TestWebKitAPI.xcconfig 2020-10-02 07:05:42 UTC (rev 267869)
@@ -61,7 +61,17 @@
OTHER_CPLUSPLUSFLAGS = $(inherited) -isystem $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders;
-OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework _javascript_Core -framework WebKit -lWebCoreTestSupport $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_PDFKIT_LDFLAGS) $(WK_HID_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
+WK_OPENGL_LDFLAGS = $(WK_OPENGL_LDFLAGS_$(WK_PLATFORM_NAME));
+WK_OPENGL_LDFLAGS_iphoneos = -framework OpenGLES;
+WK_OPENGL_LDFLAGS_maccatalyst = -framework OpenGL;
+WK_OPENGL_LDFLAGS_iphonesimulator = -framework OpenGLES;
+WK_OPENGL_LDFLAGS_watchos = $(WK_OPENGL_LDFLAGS_iphoneos);
+WK_OPENGL_LDFLAGS_watchsimulator = $(WK_OPENGL_LDFLAGS_iphonesimulator);
+WK_OPENGL_LDFLAGS_appletvos = $(WK_OPENGL_LDFLAGS_iphoneos);
+WK_OPENGL_LDFLAGS_appletvsimulator = $(WK_OPENGL_LDFLAGS_iphonesimulator);
+WK_OPENGL_LDFLAGS_macosx = -framework OpenGL;
+
+OTHER_LDFLAGS = $(inherited) $(UNEXPORTED_SYMBOL_LDFLAGS) -lgtest -force_load $(BUILT_PRODUCTS_DIR)/libTestWebKitAPI.a -framework _javascript_Core -framework WebKit -lWebCoreTestSupport $(WK_AUTHKIT_LDFLAGS) -framework Network $(WK_PDFKIT_LDFLAGS) $(WK_HID_LDFLAGS) $(WK_OPENGL_LDFLAGS) $(OTHER_LDFLAGS_PLATFORM_$(WK_COCOA_TOUCH));
OTHER_LDFLAGS_PLATFORM_ = -framework Cocoa -framework Carbon;
// FIXME: This should not be built on iOS. Instead we should create and use a TestWebKitAPI application.
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (267868 => 267869)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-10-02 06:47:42 UTC (rev 267868)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2020-10-02 07:05:42 UTC (rev 267869)
@@ -547,6 +547,7 @@
7AE9E5091AE5AE8B00CF874B /* test.pdf in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7AE9E5081AE5AE8B00CF874B /* test.pdf */; };
7AEAD47F1E20116C00416EFE /* CrossPartitionFileSchemeAccess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7AEAD47C1E20113800416EFE /* CrossPartitionFileSchemeAccess.mm */; };
7AEAD4811E20122700416EFE /* CrossPartitionFileSchemeAccess.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7AEAD47D1E20114E00416EFE /* CrossPartitionFileSchemeAccess.html */; };
+ 7B7D096A2519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7B7D09692519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm */; };
7C1AF7951E8DCBAB002645B9 /* PrepareForMoveToWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */; };
7C3965061CDD74F90094DBB8 /* ColorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C3965051CDD74F90094DBB8 /* ColorTests.cpp */; };
7C3DB8E41D12129B00AE8CC3 /* CommandBackForward.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7C3DB8E21D12129B00AE8CC3 /* CommandBackForward.mm */; };
@@ -2309,6 +2310,7 @@
7AE9E5081AE5AE8B00CF874B /* test.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = test.pdf; sourceTree = "<group>"; };
7AEAD47C1E20113800416EFE /* CrossPartitionFileSchemeAccess.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CrossPartitionFileSchemeAccess.mm; sourceTree = "<group>"; };
7AEAD47D1E20114E00416EFE /* CrossPartitionFileSchemeAccess.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = CrossPartitionFileSchemeAccess.html; path = Tests/mac/CrossPartitionFileSchemeAccess.html; sourceTree = SOURCE_ROOT; };
+ 7B7D09692519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebGLNoCrashOnOtherThreadAccess.mm; sourceTree = "<group>"; };
7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PrepareForMoveToWindow.mm; sourceTree = "<group>"; };
7C3965051CDD74F90094DBB8 /* ColorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorTests.cpp; sourceTree = "<group>"; };
7C3DB8E21D12129B00AE8CC3 /* CommandBackForward.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CommandBackForward.mm; sourceTree = "<group>"; };
@@ -4605,6 +4607,7 @@
CDC0932A21C872C10030C4B0 /* ScrollingDoesNotPauseMedia.mm */,
F434CA1922E65BCA005DDB26 /* ScrollToRevealSelection.mm */,
0F4FFA9D1ED3AA8500F7111F /* SnapshotViaRenderInContext.mm */,
+ 7B7D09692519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm */,
31E9BDA0247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm */,
2DC9451624D8AC0200430376 /* WebThreadLock.mm */,
);
@@ -5479,6 +5482,7 @@
7C83E04C1D0A641800FEBCF3 /* WebCoreNSURLSession.mm in Sources */,
57A79857224AB34E00A7F6F1 /* WebCryptoMasterKey.mm in Sources */,
C1FF9EDB244644F000839AE4 /* WebFilter.mm in Sources */,
+ 7B7D096A2519F8F90017A078 /* WebGLNoCrashOnOtherThreadAccess.mm in Sources */,
5C973F5C1F58EF8B00359C27 /* WebGLPolicy.mm in Sources */,
31E9BDA1247F4C62002E51A2 /* WebGLPrepareDisplayOnWebThread.mm in Sources */,
7CCE7EAB1A411A2400447C4C /* WebKitAgnosticTest.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLNoCrashOnOtherThreadAccess.mm (0 => 267869)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLNoCrashOnOtherThreadAccess.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitLegacy/ios/WebGLNoCrashOnOtherThreadAccess.mm 2020-10-02 07:05:42 UTC (rev 267869)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if HAVE(UIWEBVIEW)
+
+#import "PlatformUtilities.h"
+#import <_javascript_Core/JSVirtualMachine.h>
+#import <_javascript_Core/JSVirtualMachineInternal.h>
+#import <UIKit/UIKit.h>
+#import <WebCore/WebCoreThread.h>
+#import <stdlib.h>
+#import <wtf/RetainPtr.h>
+
+#if PLATFORM(MAC) || PLATFORM(MACCATALYST)
+#import <OpenGL/OpenGL.h>
+#elif PLATFORM(IOS)
+#import <OpenGLES/EAGL.h>
+#endif
+
+namespace {
+bool didFinishLoad;
+bool didFinishTest;
+
+#if PLATFORM(MAC) || PLATFORM(MACCATALYST)
+class SetContextCGL {
+ SetContextCGL()
+ {
+ // TODO: implement properly. Skipped due to complicated instantiation.
+ // instead, just clobber the current context with nullptr.
+ CGLSetCurrentContext(nullptr);
+ }
+ ~SetContextCGL()
+ {
+ CGLSetCurrentContext(nullptr);
+ }
+};
+#else
+class SetContextCGL {
+
+};
+#endif
+
+#if PLATFORM(IOS)
+class SetContextEAGL {
+public:
+ SetContextEAGL()
+ {
+ m_eaglContext = adoptNS([[EAGLContext alloc] initWithAPI: kEAGLRenderingAPIOpenGLES3]);
+ auto r = [EAGLContext setCurrentContext: m_eaglContext.get()];
+ ASSERT(r);
+ UNUSED_VARIABLE(r);
+ }
+ ~SetContextEAGL()
+ {
+ [EAGLContext setCurrentContext: nil];
+ }
+
+private:
+ RetainPtr<EAGLContext> m_eaglContext;
+};
+#else
+class SetContextEAGL {
+
+};
+#endif
+
+}
+
+@interface WebGLNoCrashOnOtherThreadAccessWebViewDelegate : NSObject <UIWebViewDelegate>
+@end
+
+@implementation WebGLNoCrashOnOtherThreadAccessWebViewDelegate
+
+IGNORE_WARNINGS_BEGIN("deprecated-implementations")
+- (void)webViewDidFinishLoad:(UIWebView *)webView
+{
+ didFinishLoad = true;
+}
+
+- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
+{
+ if ([request.URL.scheme isEqualToString:@"callback"]) {
+ if ([request.URL.resourceSpecifier isEqualToString:@"didFinishTest"])
+ didFinishTest = true;
+ else
+ EXPECT_TRUE(false) << [request.URL.resourceSpecifier UTF8String];
+ return NO;
+ }
+
+ return YES;
+}
+IGNORE_WARNINGS_END
+
+@end
+
+namespace TestWebKitAPI {
+
+// Test that tests behavior of UIWebView API with regards to WebGL:
+// 1) WebGL can be run on web thread.
+// 2) WebGL can be run on client main thread.
+// 3) WebGL run on client thread is not affected by client changing
+// the EAGL/CGL context.
+TEST(WebKitLegacy, WebGLNoCrashOnOtherThreadAccess)
+{
+ const unsigned testIterations = 10;
+
+ RetainPtr<UIWindow> uiWindow = adoptNS([[UIWindow alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+ RetainPtr<UIWebView> uiWebView = adoptNS([[UIWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+ [uiWindow addSubview:uiWebView.get()];
+
+ ASSERT_TRUE(WebThreadIsEnabled());
+ SetContextCGL clientContextCGL1;
+ SetContextEAGL clientContextEAGL1;
+ UNUSED_VARIABLE(clientContextCGL1);
+ UNUSED_VARIABLE(clientContextEAGL1);
+
+ RetainPtr<WebGLNoCrashOnOtherThreadAccessWebViewDelegate> uiDelegate =
+ adoptNS([[WebGLNoCrashOnOtherThreadAccessWebViewDelegate alloc] init]);
+ uiWebView.get().delegate = uiDelegate.get();
+ NSString* testHtml = @R"HTML(<body>NOLINT(readability/multiline_string)
+<script>
+function runTest()
+{
+ let w = 100;
+ let h = 100;
+ let canvas = document.createElement("canvas");
+ canvas.width = w;
+ canvas.height = h;
+ let gl = canvas.getContext("webgl");
+ gl.clearColor(0, 0, 1, 1);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ let expected = 255 << 24 | 255 << 16;
+ let ps = new Uint8Array(w * h * 4);
+ gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, ps);
+ for (let i = 0; i < ps.length; i += 4) {
+ let got = ps[i] | ps[i+1] << 8 | ps[i+2] << 16 | ps[i+3] << 24;
+ if (got != expected)
+ return `${got} != ${expected}`; // NOLINT
+ }
+ return "didFinishTest";
+}
+function runTestAsync()
+{
+ setTimeout(() => { window.location = 'callback:' + runTest(); }, 10); // NOLINT
+}
+</script>)HTML"; // NOLINT(readability/multiline_string)
+ [uiWebView loadHTMLString:testHtml baseURL:nil];
+
+ Util::run(&didFinishLoad);
+
+ RetainPtr<JSContext> jsContext = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame._javascript_Context"];
+ RetainPtr<JSVirtualMachine> jsVM = [jsContext virtualMachine];
+ EXPECT_TRUE([jsVM isWebThreadAware]);
+
+ // Start to run WebGL on web thread.
+ [uiWebView stringByEvaluatingJavaScriptFromString:@"runTestAsync();"];
+ EXPECT_FALSE(didFinishTest); // The pattern runs the test on web thread.
+
+ for (unsigned i = 0; i < testIterations; i++) {
+ // Run WebGL on client main thread.
+ NSString* result = [[jsContext evaluateScript: @"runTest();"] toString];
+ EXPECT_TRUE([@"didFinishTest" isEqualToString: result]);
+
+ // Client clobbers EAGLContext between calls that run WebGL on main thread.
+ SetContextCGL clientContextCGL2;
+ SetContextEAGL clientContextEAGL2;
+ UNUSED_VARIABLE(clientContextCGL2);
+ UNUSED_VARIABLE(clientContextEAGL2);
+
+ result = [[jsContext evaluateScript: @"runTest();"] toString];
+ EXPECT_TRUE([@"didFinishTest" isEqualToString: result]);
+
+ // Wait until the previous WebGL test run has finished.
+ Util::run(&didFinishTest);
+ didFinishTest = false;
+ // Start to run WebGL on web thread.
+ [uiWebView stringByEvaluatingJavaScriptFromString:@"runTestAsync();"];
+ EXPECT_FALSE(didFinishTest);
+ }
+
+ Util::run(&didFinishTest);
+}
+
+}
+
+#endif