Title: [279298] trunk/Source/WebCore
Revision
279298
Author
[email protected]
Date
2021-06-25 15:06:49 -0700 (Fri, 25 Jun 2021)

Log Message

Add support for MTLSharedTextures in WebXR
https://bugs.webkit.org/show_bug.cgi?id=227245
<rdar://problem/79591620>

Reviewed by Tim Horton.

Source/WebCore:

Sometimes, the IOSurface passed to WebXR come from a shared MTLTexture. In
this case we can't treat the IOSurface data as a regular single-plane
image. Instead we should use it to recreate the MTLTexture and then
bind that to WebGL's framebuffer.

* Modules/webxr/WebXROpaqueFramebuffer.cpp: Use some new binding methods on GraphicsContextGLOpenGL
if given a shared texture.
(WebCore::WebXROpaqueFramebuffer::startFrame):
(WebCore::WebXROpaqueFramebuffer::endFrame):
* Modules/webxr/WebXROpaqueFramebuffer.h:
* platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm: New methods to link an
IOSurface to a GL texture, going through a MTLSharedTexture.
(WebCore::GraphicsContextGLOpenGL::attachIOSurfaceToSharedTexture):
(WebCore::GraphicsContextGLOpenGL::detachIOSurfaceFromSharedTexture):
* platform/graphics/opengl/GraphicsContextGLOpenGL.h:
* platform/xr/PlatformXR.h: Add a new "isShared" member to LayerData
to differentiate between normal IOSurfaces and those that came
from a shared texture.
(PlatformXR::Device::FrameData::LayerData::encode const):
(PlatformXR::Device::FrameData::LayerData::decode):

Source/WebCore/PAL:

Define MTLSharedTextureHandle's initWithIOSurface.

* pal/spi/cocoa/MetalSPI.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (279297 => 279298)


--- trunk/Source/WebCore/ChangeLog	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/ChangeLog	2021-06-25 22:06:49 UTC (rev 279298)
@@ -1,3 +1,32 @@
+2021-06-22  Dean Jackson  <[email protected]>
+
+        Add support for MTLSharedTextures in WebXR
+        https://bugs.webkit.org/show_bug.cgi?id=227245
+        <rdar://problem/79591620>
+
+        Reviewed by Tim Horton.
+
+        Sometimes, the IOSurface passed to WebXR come from a shared MTLTexture. In
+        this case we can't treat the IOSurface data as a regular single-plane
+        image. Instead we should use it to recreate the MTLTexture and then
+        bind that to WebGL's framebuffer.
+
+        * Modules/webxr/WebXROpaqueFramebuffer.cpp: Use some new binding methods on GraphicsContextGLOpenGL
+        if given a shared texture.
+        (WebCore::WebXROpaqueFramebuffer::startFrame):
+        (WebCore::WebXROpaqueFramebuffer::endFrame):
+        * Modules/webxr/WebXROpaqueFramebuffer.h:
+        * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm: New methods to link an
+        IOSurface to a GL texture, going through a MTLSharedTexture.
+        (WebCore::GraphicsContextGLOpenGL::attachIOSurfaceToSharedTexture):
+        (WebCore::GraphicsContextGLOpenGL::detachIOSurfaceFromSharedTexture):
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+        * platform/xr/PlatformXR.h: Add a new "isShared" member to LayerData
+        to differentiate between normal IOSurfaces and those that came
+        from a shared texture.
+        (PlatformXR::Device::FrameData::LayerData::encode const):
+        (PlatformXR::Device::FrameData::LayerData::decode):
+
 2021-06-25  Alex Christensen  <[email protected]>
 
         Fix null crash in AudioMediaStreamTrackRendererCocoa::start

Modified: trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.cpp (279297 => 279298)


--- trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.cpp	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.cpp	2021-06-25 22:06:49 UTC (rev 279298)
@@ -125,9 +125,6 @@
     auto gCGL = static_cast<GraphicsContextGLOpenGL*>(m_context.graphicsContextGL());
     GCGLenum textureTarget = GraphicsContextGLOpenGL::drawingBufferTextureTarget();
 
-    auto size = data.surface->size();
-    if (!size.width() || !size.height())
-        return;
 
     if (!m_opaqueTexture)
         m_opaqueTexture = gCGL->createTexture();
@@ -139,18 +136,29 @@
     gCGL->texParameteri(textureTarget, GL::TEXTURE_WRAP_T, GL::CLAMP_TO_EDGE);
 
     // Tell the GraphicsContextGL to use the IOSurface as the backing store for m_opaqueTexture.
-    m_ioSurfaceTextureHandle = gCGL->createPbufferAndAttachIOSurface(textureTarget, GraphicsContextGLOpenGL::PbufferAttachmentUsage::Write, GL::BGRA, size.width(), size.height(), GL::UNSIGNED_BYTE, data.surface->surface(), 0);
-    if (!m_ioSurfaceTextureHandle && m_opaqueTexture) {
+    if (data.isShared) {
+        m_ioSurfaceTextureHandle = gCGL->attachIOSurfaceToSharedTexture(textureTarget, data.surface.get());
+        m_ioSurfaceTextureHandleIsShared = true;
+    } else {
+        auto size = data.surface->size();
+        if (!size.width() || !size.height())
+            return;
+        m_ioSurfaceTextureHandle = gCGL->createPbufferAndAttachIOSurface(textureTarget, GraphicsContextGLOpenGL::PbufferAttachmentUsage::Write, GL::BGRA, size.width(), size.height(), GL::UNSIGNED_BYTE, data.surface->surface(), 0);
+        m_ioSurfaceTextureHandleIsShared = false;
+    }
+
+    if (!m_ioSurfaceTextureHandle) {
         gCGL->deleteTexture(m_opaqueTexture);
+        m_opaqueTexture = 0;
         return;
     }
 
-    // FIXME: This is assuming multisampling is turned off and we're rendering directly into the framebuffer.
-
     // Now set up the framebuffer to use the texture that points to the IOSurface. The depth and
     // stencil buffers were attached by startFrame.
     gl.framebufferTexture2D(GL::FRAMEBUFFER, GL::COLOR_ATTACHMENT0, GL::TEXTURE_2D, m_opaqueTexture, 0);
 
+    // FIXME: This is assuming multisampling is turned off and we're rendering directly into the framebuffer.
+
     // At this point the framebuffer should be "complete".
     ASSERT(gl.checkFramebufferStatus(GL::FRAMEBUFFER) == GL::FRAMEBUFFER_COMPLETE);
 #else
@@ -187,7 +195,12 @@
 
     if (m_ioSurfaceTextureHandle) {
         auto gCGL = static_cast<GraphicsContextGLOpenGL*>(&gl);
-        gCGL->destroyPbufferAndDetachIOSurface(m_ioSurfaceTextureHandle);
+        if (m_ioSurfaceTextureHandleIsShared)
+            gCGL->detachIOSurfaceFromSharedTexture(m_ioSurfaceTextureHandle);
+        else
+            gCGL->destroyPbufferAndDetachIOSurface(m_ioSurfaceTextureHandle);
+        m_ioSurfaceTextureHandle = nullptr;
+        m_ioSurfaceTextureHandleIsShared = false;
     }
 #else
 

Modified: trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.h (279297 => 279298)


--- trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.h	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/Modules/webxr/WebXROpaqueFramebuffer.h	2021-06-25 22:06:49 UTC (rev 279298)
@@ -79,6 +79,7 @@
     PlatformGLObject m_opaqueTexture { 0 };
 #if USE(IOSURFACE_FOR_XR_LAYER_DATA)
     void* m_ioSurfaceTextureHandle { nullptr };
+    bool m_ioSurfaceTextureHandleIsShared { false };
 #endif
 };
 

Modified: trunk/Source/WebCore/PAL/ChangeLog (279297 => 279298)


--- trunk/Source/WebCore/PAL/ChangeLog	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/PAL/ChangeLog	2021-06-25 22:06:49 UTC (rev 279298)
@@ -1,3 +1,15 @@
+2021-06-22  Dean Jackson  <[email protected]>
+
+        Add support for MTLSharedTextures in WebXR
+        https://bugs.webkit.org/show_bug.cgi?id=227245
+        <rdar://problem/79591620>
+
+        Reviewed by Tim Horton.
+
+        Define MTLSharedTextureHandle's initWithIOSurface.
+
+        * pal/spi/cocoa/MetalSPI.h:
+
 2021-06-25  Wenson Hsieh  <[email protected]>
 
         Unreviewed, fix the macOS Monterey build

Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/MetalSPI.h (279297 => 279298)


--- trunk/Source/WebCore/PAL/pal/spi/cocoa/MetalSPI.h	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/MetalSPI.h	2021-06-25 22:06:49 UTC (rev 279298)
@@ -25,6 +25,7 @@
 
 #if USE(APPLE_INTERNAL_SDK)
 
+#import <Metal/MTLTexture_Private.h>
 #import <Metal/MetalPrivate.h>
 
 #else
@@ -31,6 +32,8 @@
 
 #import <Foundation/NSObject.h>
 
+typedef struct __IOSurface *IOSurfaceRef;
+
 @protocol MTLDeviceSPI <MTLDevice>
 - (NSString*)vendorName;
 - (NSString*)familyName;
@@ -41,4 +44,8 @@
 - (void)_purgeDevice;
 @end
 
+@interface MTLSharedTextureHandle(Private)
+- (instancetype)initWithIOSurface:(IOSurfaceRef)ioSurface label:(NSString*)label;
+@end
+
 #endif

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm (279297 => 279298)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2021-06-25 22:06:49 UTC (rev 279298)
@@ -37,6 +37,7 @@
 #import "WebGLLayer.h"
 #import <CoreGraphics/CGBitmapContext.h>
 #import <Metal/Metal.h>
+#import <pal/spi/cocoa/MetalSPI.h>
 #import <wtf/BlockObjCExceptions.h>
 #import <wtf/darwin/WeakLinking.h>
 #import <wtf/text/CString.h>
@@ -684,7 +685,52 @@
     EGL_DestroySurface(display, handle);
 }
 
+void* GraphicsContextGLOpenGL::attachIOSurfaceToSharedTexture(GCGLenum target, IOSurface* surface)
+{
+    constexpr EGLint emptyAttributes[] = { EGL_NONE };
 
+    // Create a MTLTexture out of the IOSurface.
+    // FIXME: We need to use the same device that ANGLE is using, which might not be the default.
+
+    RetainPtr<MTLSharedTextureHandle> handle = adoptNS([[MTLSharedTextureHandle alloc] initWithIOSurface:surface->surface() label:@"WebXR"]);
+    if (!handle) {
+        LOG(WebGL, "Unable to create a MTLSharedTextureHandle from the IOSurface in attachIOSurfaceToTexture.");
+        return nullptr;
+    }
+
+    if (!handle.get().device) {
+        LOG(WebGL, "MTLSharedTextureHandle does not have a Metal device in attachIOSurfaceToTexture.");
+        return nullptr;
+    }
+
+    auto texture = adoptNS([handle.get().device newSharedTextureWithHandle:handle.get()]);
+    if (!texture) {
+        LOG(WebGL, "Unable to create a MTLSharedTexture from the texture handle in attachIOSurfaceToTexture.");
+        return nullptr;
+    }
+
+    // FIXME: Does the texture have the correct usage mode?
+
+    // Create an EGLImage out of the MTLTexture
+    auto display = platformDisplay();
+    auto eglImage = EGL_CreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, reinterpret_cast<EGLClientBuffer>(texture.get()), emptyAttributes);
+    if (!eglImage) {
+        LOG(WebGL, "Unable to create an EGLImage from the Metal handle in attachIOSurfaceToTexture.");
+        return nullptr;
+    }
+
+    // Tell the currently bound texture to use the EGLImage.
+    gl::EGLImageTargetTexture2DOES(target, eglImage);
+
+    return eglImage;
+}
+
+void GraphicsContextGLOpenGL::detachIOSurfaceFromSharedTexture(void* handle)
+{
+    auto display = platformDisplay();
+    EGL_DestroyImageKHR(display, handle);
+}
+
 bool GraphicsContextGLOpenGL::isGLES2Compliant() const
 {
     return m_isForWebGL2;

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h (279297 => 279298)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2021-06-25 22:06:49 UTC (rev 279298)
@@ -536,6 +536,8 @@
     // detach call below.
     void* createPbufferAndAttachIOSurface(GCGLenum target, PbufferAttachmentUsage, GCGLenum internalFormat, GCGLsizei width, GCGLsizei height, GCGLenum type, IOSurfaceRef, GCGLuint plane);
     void destroyPbufferAndDetachIOSurface(void* handle);
+    void* attachIOSurfaceToSharedTexture(GCGLenum target, IOSurface*);
+    void detachIOSurfaceFromSharedTexture(void* handle);
 #endif
 
 private:

Modified: trunk/Source/WebCore/platform/xr/PlatformXR.h (279297 => 279298)


--- trunk/Source/WebCore/platform/xr/PlatformXR.h	2021-06-25 20:50:25 UTC (rev 279297)
+++ trunk/Source/WebCore/platform/xr/PlatformXR.h	2021-06-25 22:06:49 UTC (rev 279298)
@@ -173,6 +173,7 @@
         struct LayerData {
 #if USE(IOSURFACE_FOR_XR_LAYER_DATA)
             std::unique_ptr<WebCore::IOSurface> surface;
+            bool isShared { false };
 #else
             PlatformGLObject opaqueTexture { 0 };
 #endif
@@ -442,6 +443,7 @@
 #if USE(IOSURFACE_FOR_XR_LAYER_DATA)
     WTF::MachSendRight surfaceSendRight = surface ? surface->createSendRight() : WTF::MachSendRight();
     encoder << surfaceSendRight;
+    encoder << isShared;
 #else
     encoder << opaqueTexture;
 #endif
@@ -456,6 +458,8 @@
     if (!decoder.decode(surfaceSendRight))
         return std::nullopt;
     layerData.surface = WebCore::IOSurface::createFromSendRight(WTFMove(surfaceSendRight), WebCore::DestinationColorSpace::SRGB());
+    if (!decoder.decode(layerData.isShared))
+        return std::nullopt;
 #else
     if (!decoder.decode(layerData.opaqueTexture))
         return std::nullopt;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to