← All issues

WebXR Layers projection layer implementation

a965fc6

Source/WebCore/Modules/webxr/WebGLOpaqueTexture.cpp

+void WebGLOpaqueTexture::deleteObjectImpl(const AbstractLocker&, GraphicsContextGL*, PlatformGLObject)
+{
+ // Don't do anything as the context does not own the texture.
+}
+
+WebGLOpaqueTexture::~WebGLOpaqueTexture()
+{
+ if (!m_context)
+ return;
+ runDestructor();
+}

Source/WebCore/Modules/webxr/WebXRSession.cpp

-else if (session.m_activeRenderState->layers().size())
- session.m_activeRenderState->layers()[0]->startFrame(session.m_frameData);
+else if (session.m_activeRenderState->layers().size()) {
+ for (auto& layer : session.m_activeRenderState->layers())
+ layer->startFrame(session.m_frameData);
+}

WebXR Layers (XRWebGLBinding) is an extension that lets web apps render into compositor-managed textures rather than framebuffers, enabling more efficient compositing in XR headsets. This commit implements the WebXR projection layer for WPE/GTK ports, introducing a new WebGLOpaqueTexture class — a subclass of WebGLTexture whose deleteObjectImpl is deliberately a no-op because the GL texture's lifetime is owned by the swapchain, not the GL context. The architecture uses a two-tier swapchain: color textures are shared cross-process from the UIProcess XR compositor (via DMABuf/GBM on Linux), while depth/stencil textures are allocated locally as WebXRWebGLStaticImageSwapchain entries.

UIProcess (XR Compositor / OpenXR)          WebProcess
│                                              │
├─ allocates color textures (DMABuf/GBM) ─────►│ WebXRWebGLSharedImageSwapchain
│   (shared image handles via IPC)             │   └─ WebGLOpaqueTexture (no ctx teardown)
│                                              │
│                                              ├─ allocates depth locally
│                                              │   WebXRWebGLStaticImageSwapchain
│                                              │   └─ WebGLOpaqueTexture
│                                              │
│                                              ├─ XRWebGLBinding::createProjectionLayer()
│                                              │   ├─ validate formats/dimensions
│                                              │   ├─ allocateColorTextures
│                                              │   ├─ allocateDepthTextures
│                                              │   └─ return XRProjectionLayer
│                                              │
│◄── device->submitFrame(frameLayers) ─────────┤ WebXRSession::onFrame

This is a substantial new attack surface: a cross-process texture sharing pipeline between the XR compositor (UIProcess) and rendering code (WebProcess), coupled with a new WebGL object subclass that deliberately bypasses the standard GL context destruction path. The commit explicitly notes spec compliance is incomplete — multiple parameters are ignored and only stereo left-right is supported — which historically correlates with missing validation on edge-case API calls. The WebGLOpaqueTexture ownership model, where GL texture lifetime is decoupled from the GL context that uses it, creates a window for use-after-free if script retains a JS reference to a sub-image texture after the swapchain releases the backing GL object.

🔒

New cross-process texture sharing path and a WebGL object subclass with non-standard lifetime semantics — several audit directions included.

Subscribe to read more