Title: [283238] trunk
Revision
283238
Author
[email protected]
Date
2021-09-29 11:21:58 -0700 (Wed, 29 Sep 2021)

Log Message

MediaStream canvas.captureStream() fails for WebGL
https://bugs.webkit.org/show_bug.cgi?id=230613
<rdar://82307293>

Patch by Kimmo Kinnunen <[email protected]> on 2021-09-29
Reviewed by Youenn Fablet.

.:

Add a manual test to interact with media stream
captureStream() behavior until the implementation is
testable.

* ManualTests/mediastream/mediastream-canvas-to-video.html: Added.

Source/WebCore:

Remove previous incorrect behavior of turning on "preservesDrawingBuffer"
and sampling the drawing buffer. The drawing buffer is not what should
ever be touched, rather it's the display buffer that should be available.

Implement sampling of WebGL display buffer for
media stream capture. The upon sampling, obtain a shared
reference to the
display buffer, passes it to media sample consuming process and mark
the WebGL context display buffer non-eligible for recycling as
new drawing buffer.

Currently the implementation is displayed correctly for
WebGL contents that is premultiplied. Unpremultiplied
content is fixed in the associated bugs.

Note: there are bugs preventing robust use of the API,
listed in the associated bugs. As such, testing is not expanded
in this bug.

Tested by
ManualTests/mediastream/mediastream-canvas-to-video.html (added)

https://webrtc.github.io/samples/src/content/capture/canvas-video/
(Refresh the page or hide the window until MediaPlayer initialization
flakyness lets rendering happen)

The test LayoutTests/fast/mediastream/captureStream/canvas3d.html
cannot yet be used to test the implementation as the rest of the
captureStream() and playback implementation is so flaky.

* Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp:
(WebCore::CanvasCaptureMediaStreamTrack::Source::canvasChanged):
* html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::toMediaSample):
* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::paintCompositedResultsToMediaSample):
* html/canvas/WebGLRenderingContextBase.h:
(WebCore::WebGLRenderingContextBase::isPreservingDrawingBuffer const):
* platform/graphics/GraphicsContextGL.cpp:
* platform/graphics/GraphicsContextGL.h:
* platform/graphics/RemoteGraphicsContextGLProxyBase.cpp:
(WebCore::RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample):
* platform/graphics/RemoteGraphicsContextGLProxyBase.h:
* platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm:
(WebCore::MediaSampleAVFObjC::createImageSample):
* platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp:
(WebCore::GraphicsContextGLIOSurfaceSwapChain::present):
* platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h:
* platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
(WebCore::GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample):
* platform/graphics/cocoa/RemoteGraphicsContextGLProxyBaseCocoa.mm:
(WebCore::RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample):
* platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:
(WebCore::GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample):
* platform/graphics/opengl/GraphicsContextGLOpenGL.h:

LayoutTests:

Add new expectations, a warning was removed.
CONSOLE MESSAGE: Turning drawing buffer preservation for the WebGL canvas being captured

* fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events-expected.txt:
* fast/mediastream/captureStream/canvas3d-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/ChangeLog (283237 => 283238)


--- trunk/ChangeLog	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/ChangeLog	2021-09-29 18:21:58 UTC (rev 283238)
@@ -1,3 +1,17 @@
+2021-09-29  Kimmo Kinnunen  <[email protected]>
+
+        MediaStream canvas.captureStream() fails for WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=230613
+        <rdar://82307293>
+
+        Reviewed by Youenn Fablet.
+
+        Add a manual test to interact with media stream
+        captureStream() behavior until the implementation is
+        testable.
+
+        * ManualTests/mediastream/mediastream-canvas-to-video.html: Added.
+
 2021-09-28  Carlos Garcia Campos  <[email protected]>
 
         [GTK][WPE] Bump libsoup3 version to 3.0.0

Modified: trunk/LayoutTests/ChangeLog (283237 => 283238)


--- trunk/LayoutTests/ChangeLog	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/LayoutTests/ChangeLog	2021-09-29 18:21:58 UTC (rev 283238)
@@ -1,3 +1,17 @@
+2021-09-29  Kimmo Kinnunen  <[email protected]>
+
+        MediaStream canvas.captureStream() fails for WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=230613
+        <rdar://82307293>
+
+        Reviewed by Youenn Fablet.
+
+        Add new expectations, a warning was removed.
+        CONSOLE MESSAGE: Turning drawing buffer preservation for the WebGL canvas being captured
+
+        * fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events-expected.txt:
+        * fast/mediastream/captureStream/canvas3d-expected.txt:
+
 2021-09-29  Youenn Fablet  <[email protected]>
 
         [ iOS macOS wk2 ] webrtc/datachannel/mdns-ice-candidates.html is a flaky failure

Modified: trunk/LayoutTests/fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events-expected.txt (283237 => 283238)


--- trunk/LayoutTests/fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events-expected.txt	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/LayoutTests/fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events-expected.txt	2021-09-29 18:21:58 UTC (rev 283238)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Turning drawing buffer preservation for the WebGL canvas being captured
 Exercises the potential events on CanvasCaptureMediaStream.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

Modified: trunk/LayoutTests/fast/mediastream/captureStream/canvas3d-expected.txt (283237 => 283238)


--- trunk/LayoutTests/fast/mediastream/captureStream/canvas3d-expected.txt	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/LayoutTests/fast/mediastream/captureStream/canvas3d-expected.txt	2021-09-29 18:21:58 UTC (rev 283238)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Turning drawing buffer preservation for the WebGL canvas being captured
 
 
 

Added: trunk/ManualTests/mediastream/mediastream-canvas-to-video.html (0 => 283238)


--- trunk/ManualTests/mediastream/mediastream-canvas-to-video.html	                        (rev 0)
+++ trunk/ManualTests/mediastream/mediastream-canvas-to-video.html	2021-09-29 18:21:58 UTC (rev 283238)
@@ -0,0 +1,192 @@
+<html>
+<head>
+    <style type="text/css">
+    video { border: solid 1px black; }
+    canvas { padding: 1px }
+    .placeholder {
+        display: inline-block;
+        border: 1px dashed black;
+        width: 300px;
+        height: 150px;
+    }
+    </style>
+</head>
+<body>
+<p>
+<input type="button" _onclick_="drawOnce()" value="Draw once" />
+<input type="button" _onclick_="clearOnce()" value="Clear once" />
+<input type="button" _onclick_="toggleDrawing()" value="Toggle drawing"/>
+</p>
+<p>
+    <ul>
+        <li>Left: canvas</li>
+        <li>Right: video</li>
+        <li>Top rectangle small: opaque</li>
+        <li>Bottom rectangle big: 50% translucent</li>
+        <li>Background: transparent</li>
+    </ul>
+</p>
+<script>
+
+var ctx2Ds = [];
+
+var gls = [];
+
+function createTests()
+{
+    let glCases = [];
+    for (let preserveDrawingBuffer of [true, false]) {
+        for (let alpha of [true, false]) {
+            for (let premultipliedAlpha of [true, false]) {
+                glCases.push({
+                    preserveDrawingBuffer: preserveDrawingBuffer,
+                    alpha: alpha,
+                    premultipliedAlpha: premultipliedAlpha,
+                    antialias: false,
+                    inDocument: true
+                });
+            }
+        }
+    }
+    glCases.push({
+        preserveDrawingBuffer: false,
+        alpha: true,
+        premultipliedAlpha: true,
+        antialias: true,
+        inDocument: true
+    });
+    glCases.push({
+        preserveDrawingBuffer: false,
+        alpha: true,
+        premultipliedAlpha: true,
+        antialias: false,
+        inDocument: false
+    });
+
+    var ctx2DCases = [];
+    for (let inDocument of [true, false]) {
+        ctx2DCases.push({ inDocument: inDocument });
+    }
+
+    for (let c of glCases) {
+        let d = document.createElement("div");
+        document.body.appendChild(d);
+        let h = document.createElement("h3");
+        h.innerText = `WebGL case: ${JSON.stringify(c)}`;
+        d.appendChild(h);
+        let canvas = document.createElement("canvas");
+        if (c.inDocument)
+            d.appendChild(canvas);
+        else {
+            let p = document.createElement("div");
+            p.className = "placeholder";
+            d.appendChild(p);
+        }
+        let v = document.createElement("video");
+        v.controls = true;
+        v.autoplay = true;
+        d.appendChild(v);
+
+        let gl = canvas.getContext("webgl2", {
+            preserveDrawingBuffer: c.preserveDrawingBuffer,
+            alpha: c.alpha,
+            premultipliedAlpha: c.premultipliedAlpha,
+            antialias: c.antialias
+        });
+        v.srcObject = canvas.captureStream();
+        gls.push(gl);
+    }
+
+    for (let c of ctx2DCases) {
+        let d = document.createElement("div");
+        document.body.appendChild(d);
+        let h = document.createElement("h3");
+        h.innerText = `Canvas case: ${JSON.stringify(c)}`;
+        d.appendChild(h);
+        let canvas = document.createElement("canvas");
+        if (c.inDocument)
+            d.appendChild(canvas);
+        else {
+            let p = document.createElement("div");
+            p.className = "placeholder";
+            d.appendChild(p);
+        }
+        let v = document.createElement("video");
+        v.controls = true;
+        v.autoplay = true;
+        d.appendChild(v);
+        let ctx2D = canvas.getContext("2d");
+        v.srcObject = canvas.captureStream();
+        ctx2Ds.push(ctx2D);
+    }
+}
+
+function drawOnce()
+{
+    for (let c of gls) {
+        c.enable(c.SCISSOR_TEST);
+        if (c.getContextAttributes().premultipliedAlpha)
+            c.clearColor(0., 0.5, 0., 0.5);
+        else
+            c.clearColor(0., 1., 0., 0.5);
+        c.scissor(0, 0, 300, 50);
+        c.clear(c.COLOR_BUFFER_BIT);
+
+        c.scissor(125, 50, 50, 50);
+        c.clearColor(0., 1., 0., 1.);
+        c.clear(c.COLOR_BUFFER_BIT);
+        c.scissor(0, 0, 300, 50);
+        c.clear(c.COLOR_BUFFER_BIT);
+
+    }
+    for (let c of ctx2Ds) {
+        c.fillStyle = "rgba(0, 128, 0, 0.5)";
+        c.fillRect(0, 100, 300, 50);
+        c.fillStyle = "rgba(0, 255, 0, 1.)";
+        c.fillRect(125, 50, 50, 50);
+    }
+}
+
+function clearOnce()
+{
+    console.log("clear");
+    for (let c of gls) {
+        c.clearColor(0., 0., 0., 0.);
+        c.disable(c.SCISSOR_TEST);
+        c.clear(c.COLOR_BUFFER_BIT);
+    }
+    for (let c of ctx2Ds) {
+        c.clearRect(0, 0, 300, 150);
+    }
+}
+
+var isToggling = false;
+
+function toggleDrawing()
+{
+    if (isToggling) {
+        clearTimeout(isToggling);
+        isToggling = false;
+        return;
+    }
+    var hasDrawn = true;
+    function f() {
+        if (hasDrawn)
+            clearOnce();
+        else
+            drawOnce();
+        hasDrawn = !hasDrawn;
+        isToggling = setTimeout(f, 1000);
+    }
+    f();
+}
+
+createTests();
+
+if (window.testRunner) {
+    window.testRunner.waitUntilDone();
+    toggleDrawing();
+}
+</script>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (283237 => 283238)


--- trunk/Source/WebCore/ChangeLog	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/ChangeLog	2021-09-29 18:21:58 UTC (rev 283238)
@@ -1,3 +1,68 @@
+2021-09-29  Kimmo Kinnunen  <[email protected]>
+
+        MediaStream canvas.captureStream() fails for WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=230613
+        <rdar://82307293>
+
+        Reviewed by Youenn Fablet.
+
+        Remove previous incorrect behavior of turning on "preservesDrawingBuffer"
+        and sampling the drawing buffer. The drawing buffer is not what should
+        ever be touched, rather it's the display buffer that should be available.
+
+        Implement sampling of WebGL display buffer for
+        media stream capture. The upon sampling, obtain a shared
+        reference to the
+        display buffer, passes it to media sample consuming process and mark
+        the WebGL context display buffer non-eligible for recycling as
+        new drawing buffer.
+
+        Currently the implementation is displayed correctly for
+        WebGL contents that is premultiplied. Unpremultiplied
+        content is fixed in the associated bugs.
+
+        Note: there are bugs preventing robust use of the API,
+        listed in the associated bugs. As such, testing is not expanded
+        in this bug.
+
+        Tested by
+        ManualTests/mediastream/mediastream-canvas-to-video.html (added)
+
+        https://webrtc.github.io/samples/src/content/capture/canvas-video/
+        (Refresh the page or hide the window until MediaPlayer initialization
+        flakyness lets rendering happen)
+
+        The test LayoutTests/fast/mediastream/captureStream/canvas3d.html
+        cannot yet be used to test the implementation as the rest of the
+        captureStream() and playback implementation is so flaky.
+
+        * Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp:
+        (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasChanged):
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::toMediaSample):
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::paintCompositedResultsToMediaSample):
+        * html/canvas/WebGLRenderingContextBase.h:
+        (WebCore::WebGLRenderingContextBase::isPreservingDrawingBuffer const):
+        * platform/graphics/GraphicsContextGL.cpp:
+        * platform/graphics/GraphicsContextGL.h:
+        * platform/graphics/RemoteGraphicsContextGLProxyBase.cpp:
+        (WebCore::RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample):
+        * platform/graphics/RemoteGraphicsContextGLProxyBase.h:
+        * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm:
+        (WebCore::MediaSampleAVFObjC::createImageSample):
+        * platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp:
+        (WebCore::GraphicsContextGLIOSurfaceSwapChain::present):
+        * platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h:
+        * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+        (WebCore::GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample):
+        * platform/graphics/cocoa/RemoteGraphicsContextGLProxyBaseCocoa.mm:
+        (WebCore::RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample):
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.cpp:
+        (WebCore::GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample):
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+
 2021-09-29  Jer Noble  <[email protected]>
 
         Build-time optimization: forward declare more things in MediaPlayer.h and HTMLMediaElement.h

Modified: trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp (283237 => 283238)


--- trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -153,19 +153,6 @@
 {
     ASSERT_UNUSED(canvas, m_canvas == &canvas);
 
-#if ENABLE(WEBGL)
-    // FIXME: We need to preserve drawing buffer as we are currently grabbing frames asynchronously.
-    // We should instead add an anchor point for both 2d and 3d contexts where canvas will actually paint.
-    // And call canvas observers from that point.
-    if (is<WebGLRenderingContextBase>(canvas.renderingContext())) {
-        auto& context = downcast<WebGLRenderingContextBase>(*canvas.renderingContext());
-        if (!context.isPreservingDrawingBuffer()) {
-            canvas.scriptExecutionContext()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, "Turning drawing buffer preservation for the WebGL canvas being captured"_s);
-            context.enablePreserveDrawingBuffer();
-        }
-    }
-#endif
-
     // FIXME: We should try to generate the frame at the time the screen is being updated.
     if (m_captureCanvasTimer.isActive())
         return;

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (283237 => 283238)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -758,6 +758,13 @@
 RefPtr<MediaSample> HTMLCanvasElement::toMediaSample()
 {
 #if PLATFORM(COCOA) || USE(GSTREAMER)
+#if ENABLE(WEBGL)
+    if (is<WebGLRenderingContextBase>(m_context.get())) {
+        if (RuntimeEnabledFeatures::sharedFeatures().webAPIStatisticsEnabled())
+            ResourceLoadObserver::shared().logCanvasRead(document());
+        return downcast<WebGLRenderingContextBase>(*m_context).paintCompositedResultsToMediaSample();
+    }
+#endif
     auto* imageBuffer = buffer();
     if (!imageBuffer)
         return nullptr;

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (283237 => 283238)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -134,6 +134,10 @@
 #include "OffscreenCanvas.h"
 #endif
 
+#if ENABLE(MEDIA_STREAM)
+#include "MediaSample.h"
+#endif
+
 namespace WebCore {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(WebGLRenderingContextBase);
@@ -1375,6 +1379,15 @@
     return m_context->paintRenderingResultsToPixelBuffer();
 }
 
+#if ENABLE(MEDIA_STREAM)
+RefPtr<MediaSample> WebGLRenderingContextBase::paintCompositedResultsToMediaSample()
+{
+    if (isContextLostOrPending())
+        return nullptr;
+    return m_context->paintCompositedResultsToMediaSample();
+}
+#endif
+
 WebGLTexture::TextureExtensionFlag WebGLRenderingContextBase::textureExtensionFlags() const
 {
     return static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0));
@@ -3950,14 +3963,6 @@
     return false;
 }
 
-void WebGLRenderingContextBase::enablePreserveDrawingBuffer()
-{
-    ASSERT(!m_attributes.preserveDrawingBuffer);
-    m_attributes.preserveDrawingBuffer = true;
-    // Must send this notification down to the GraphicsContextGL as well.
-    m_context->enablePreserveDrawingBuffer();
-}
-
 void WebGLRenderingContextBase::hint(GCGLenum target, GCGLenum mode)
 {
     if (isContextLostOrPending())

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h (283237 => 283238)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -128,6 +128,10 @@
 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>>;
 #endif
 
+#if ENABLE(MEDIA_STREAM)
+class MediaSample;
+#endif
+
 class WebGLRenderingContextBase : public GraphicsContextGL::Client, public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
     WTF_MAKE_ISO_ALLOCATED(WebGLRenderingContextBase);
 public:
@@ -233,10 +237,6 @@
     bool extensionIsEnabled(const String&);
 
     bool isPreservingDrawingBuffer() const { return m_attributes.preserveDrawingBuffer; }
-    // Concession to canvas capture API, which must dynamically enable
-    // preserveDrawingBuffer. This can only be called once, when
-    // isPreservingDrawingBuffer() returns false.
-    void enablePreserveDrawingBuffer();
 
     bool preventBufferClearForInspector() const { return m_preventBufferClearForInspector; }
     void setPreventBufferClearForInspector(bool value) { m_preventBufferClearForInspector = value; }
@@ -392,6 +392,9 @@
     void prepareForDisplayWithPaint() final;
     void paintRenderingResultsToCanvas() final;
     std::optional<PixelBuffer> paintRenderingResultsToPixelBuffer();
+#if ENABLE(MEDIA_STREAM)
+    RefPtr<MediaSample> paintCompositedResultsToMediaSample();
+#endif
 
     void removeSharedObject(WebGLSharedObject&);
     void removeContextObject(WebGLContextObject&);

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContextGL.cpp (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/GraphicsContextGL.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContextGL.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -362,12 +362,6 @@
 {
 }
 
-void GraphicsContextGL::enablePreserveDrawingBuffer()
-{
-    // Canvas capture should not call this unless necessary.
-    ASSERT(!m_attrs.preserveDrawingBuffer);
-    m_attrs.preserveDrawingBuffer = true;
-}
 
 bool GraphicsContextGL::computeFormatAndTypeParameters(GCGLenum format, GCGLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent)
 {

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContextGL.h (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/GraphicsContextGL.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContextGL.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -59,8 +59,10 @@
 #if ENABLE(VIDEO) && USE(AVFOUNDATION)
 class GraphicsContextGLCV;
 #endif
+#if ENABLE(MEDIA_STREAM)
+class MediaSample;
+#endif
 
-
 // Base class for graphics context for implementing WebGL rendering model.
 class GraphicsContextGL : public RefCounted<GraphicsContextGL> {
 public:
@@ -1244,13 +1246,6 @@
     GraphicsContextGLAttributes contextAttributes() const { return m_attrs; }
     void setContextAttributes(const GraphicsContextGLAttributes& attrs) { m_attrs = attrs; }
 
-    // FIXME: The calling site should be fixed, this breaks the WebGL spec
-    // wrt preserveDrawingBuffer == false behavior.
-    // Concession to Canvas captureStream, which needs to dynamically set
-    // preserveDrawingBuffer to true in order to avoid implicit clears.
-    // Implementations generally do not support toggling this bit arbitrarily.
-    virtual void enablePreserveDrawingBuffer();
-
     // Support for extensions. Returns a non-null object, though not
     // all methods it contains may necessarily be supported on the
     // current hardware. Must call ExtensionsGL::supports() to
@@ -1294,6 +1289,9 @@
     virtual void paintRenderingResultsToCanvas(ImageBuffer&) = 0;
     virtual std::optional<PixelBuffer> paintRenderingResultsToPixelBuffer() = 0;
     virtual void paintCompositedResultsToCanvas(ImageBuffer&) = 0;
+#if ENABLE(MEDIA_STREAM)
+    virtual RefPtr<MediaSample> paintCompositedResultsToMediaSample() = 0;
+#endif
 
     // FIXME: this should be removed. The layer should be marked composited by
     // preparing for display, so that canvas image buffer and the layer agree

Modified: trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -97,13 +97,6 @@
     return m_buffersToAutoClear;
 }
 
-void RemoteGraphicsContextGLProxyBase::enablePreserveDrawingBuffer()
-{
-    // Redeclared for export reasons.
-    // FIXME: The whole function should be removed.
-    GraphicsContextGL::enablePreserveDrawingBuffer();
-}
-
 bool RemoteGraphicsContextGLProxyBase::supports(const String& name)
 {
     waitUntilInitialized();
@@ -156,5 +149,12 @@
 {
 }
 #endif
+
+#if ENABLE(MEDIA_STREAM) && !PLATFORM(COCOA)
+RefPtr<MediaSample> RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample()
+{
+    return nullptr;
 }
 #endif
+}
+#endif

Modified: trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/RemoteGraphicsContextGLProxyBase.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -67,7 +67,6 @@
     void setBuffersToAutoClear(GCGLbitfield) final;
     GCGLbitfield getBuffersToAutoClear() const final;
     void markLayerComposited() final;
-    void enablePreserveDrawingBuffer() final;
 
 #if ENABLE(VIDEO) && USE(AVFOUNDATION)
     GraphicsContextGLCV* asCV() final;
@@ -83,6 +82,9 @@
     void getnUniformfvEXT(GCGLuint, GCGLint, GCGLsizei, GCGLfloat*) final;
     void getnUniformivEXT(GCGLuint, GCGLint, GCGLsizei, GCGLint*) final;
 #endif
+#if ENABLE(MEDIA_STREAM)
+    RefPtr<MediaSample> paintCompositedResultsToMediaSample() final;
+#endif
 
 protected:
     void initialize(const String& availableExtensions, const String& requestableExtensions);

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -30,6 +30,8 @@
 #include <pal/avfoundation/MediaTimeAVFoundation.h>
 #include <wtf/Forward.h>
 
+using CVPixelBufferRef = struct __CVBuffer*;
+
 namespace WebCore {
 
 class PixelBuffer;
@@ -40,6 +42,7 @@
     static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, AtomString trackID) { return adoptRef(*new MediaSampleAVFObjC(sample, trackID)); }
     static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, VideoRotation rotation = VideoRotation::None, bool mirrored = false) { return adoptRef(*new MediaSampleAVFObjC(sample, rotation, mirrored)); }
     static RefPtr<MediaSampleAVFObjC> createImageSample(PixelBuffer&&);
+    static RefPtr<MediaSampleAVFObjC> createImageSample(RetainPtr<CVPixelBufferRef>&&, VideoRotation, bool mirrored);
 
     WEBCORE_EXPORT static void setAsDisplayImmediately(MediaSample&);
     static RetainPtr<CMSampleBufferRef> cloneSampleBufferAndSetAsDisplayImmediately(CMSampleBufferRef);

Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm	2021-09-29 18:21:58 UTC (rev 283238)
@@ -95,24 +95,33 @@
         return nullptr;
     }
     ASSERT_UNUSED(status, !status);
+    return createImageSample(WTFMove(cvPixelBuffer), VideoRotation::None, false);
+}
 
+RefPtr<MediaSampleAVFObjC> MediaSampleAVFObjC::createImageSample(RetainPtr<CVPixelBufferRef>&& pixelBuffer, VideoRotation rotation, bool mirrored)
+{
     CMVideoFormatDescriptionRef formatDescriptionRaw = nullptr;
-    status = PAL::CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, cvPixelBuffer.get(), &formatDescriptionRaw);
-    ASSERT(!status);
+    auto status = PAL::CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer.get(), &formatDescriptionRaw);
+    if (status || !formatDescriptionRaw) {
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
     auto formatDescription = adoptCF(formatDescriptionRaw);
 
     CMSampleTimingInfo sampleTimingInformation = { PAL::kCMTimeInvalid, PAL::kCMTimeInvalid, PAL::kCMTimeInvalid };
     CMSampleBufferRef sampleBufferRaw = nullptr;
-    status = PAL::CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, cvPixelBuffer.get(), formatDescription.get(), &sampleTimingInformation, &sampleBufferRaw);
-    ASSERT(!status);
+    status = PAL::CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, pixelBuffer.get(), formatDescription.get(), &sampleTimingInformation, &sampleBufferRaw);
+    if (status || !sampleBufferRaw) {
+        ASSERT_NOT_REACHED();
+        return nullptr;
+    }
     auto sampleBuffer = adoptCF(sampleBufferRaw);
-
     CFArrayRef attachmentsArray = PAL::CMSampleBufferGetSampleAttachmentsArray(sampleBuffer.get(), true);
     for (CFIndex i = 0, count = CFArrayGetCount(attachmentsArray); i < count; ++i) {
         CFMutableDictionaryRef attachments = checked_cf_cast<CFMutableDictionaryRef>(CFArrayGetValueAtIndex(attachmentsArray, i));
         CFDictionarySetValue(attachments, PAL::kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
     }
-    return create(sampleBuffer.get());
+    return create(sampleBuffer.get(), rotation, mirrored);
 }
 
 MediaTime MediaSampleAVFObjC::presentationTime() const

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -37,6 +37,11 @@
     return m_displayBuffer;
 }
 
+void GraphicsContextGLIOSurfaceSwapChain::markDisplayBufferInUse()
+{
+    m_displayBufferInUse = true;
+}
+
 GraphicsContextGLIOSurfaceSwapChain::Buffer GraphicsContextGLIOSurfaceSwapChain::recycleBuffer()
 {
     if (m_spareBuffer.surface) {
@@ -56,6 +61,10 @@
 void GraphicsContextGLIOSurfaceSwapChain::present(Buffer&& buffer)
 {
     m_spareBuffer = std::exchange(m_displayBuffer, WTFMove(buffer));
+    if (m_displayBufferInUse) {
+        m_displayBufferInUse = false;
+        m_spareBuffer.surface.reset();
+    }
 }
 
 }

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLIOSurfaceSwapChain.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -67,6 +67,9 @@
     // next present, recycleBuffer or detachClient call.
     virtual const Buffer& displayBuffer() const;
 
+    // Marks the current display buffer to be in use and not eligble to recycling.
+    void markDisplayBufferInUse();
+
     // Detaches the client and returns the current contents buffer metadata handle.
     // The if multiple buffers have been submitted, recycleBuffer must have been called before calling
     // this.
@@ -75,6 +78,7 @@
 protected:
     Buffer m_displayBuffer;
     Buffer m_spareBuffer;
+    bool m_displayBufferInUse = false;
 };
 
 }

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


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2021-09-29 18:21:58 UTC (rev 283238)
@@ -28,6 +28,7 @@
 #if ENABLE(WEBGL)
 #import "GraphicsContextGLOpenGL.h"
 
+#import "CVUtilities.h"
 #import "ExtensionsGLANGLE.h"
 #import "GraphicsContextGLANGLEUtilities.h"
 #import "GraphicsContextGLIOSurfaceSwapChain.h"
@@ -50,6 +51,10 @@
 #include "GraphicsContextGLCV.h"
 #endif
 
+#if ENABLE(MEDIA_STREAM)
+#include "MediaSampleAVFObjC.h"
+#endif
+
 WTF_WEAK_LINK_FORCE_IMPORT(EGL_Initialize);
 
 namespace WebCore {
@@ -878,6 +883,21 @@
     ScopedEGLDefaultDisplay::releaseAllResourcesIfUnused();
 }
 
+#if ENABLE(MEDIA_STREAM)
+RefPtr<MediaSample> GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample()
+{
+    auto &displayBuffer = m_swapChain->displayBuffer();
+    if (!displayBuffer.surface || !displayBuffer.handle)
+        return nullptr;
+    if (displayBuffer.surface->size() != getInternalFramebufferSize())
+        return nullptr;
+    m_swapChain->markDisplayBufferInUse();
+    auto pixelBuffer = createCVPixelBuffer(displayBuffer.surface->surface());
+    if (!pixelBuffer)
+        return nullptr;
+    return MediaSampleAVFObjC::createImageSample(WTFMove(*pixelBuffer), MediaSampleAVFObjC::VideoRotation::UpsideDown, true);
 }
+#endif
+}
 
 #endif // ENABLE(WEBGL)

Modified: trunk/Source/WebCore/platform/graphics/cocoa/RemoteGraphicsContextGLProxyBaseCocoa.mm (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/cocoa/RemoteGraphicsContextGLProxyBaseCocoa.mm	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/cocoa/RemoteGraphicsContextGLProxyBaseCocoa.mm	2021-09-29 18:21:58 UTC (rev 283238)
@@ -32,6 +32,11 @@
 #import "WebGLLayer.h"
 #import <wtf/BlockObjCExceptions.h>
 
+#if ENABLE(MEDIA_STREAM)
+#import "CVUtilities.h"
+#import "MediaSampleAVFObjC.h"
+#endif
+
 namespace WebCore {
 
 void RemoteGraphicsContextGLProxyBase::platformInitialize()
@@ -63,5 +68,20 @@
     return [m_webGLLayer swapChain];
 }
 
+#if ENABLE(MEDIA_STREAM)
+RefPtr<MediaSample> RemoteGraphicsContextGLProxyBase::paintCompositedResultsToMediaSample()
+{
+    auto& sc = platformSwapChain();
+    auto& displayBuffer = sc.displayBuffer();
+    if (!displayBuffer.surface)
+        return nullptr;
+    sc.markDisplayBufferInUse();
+    auto pixelBuffer = createCVPixelBuffer(displayBuffer.surface->surface());
+    if (!pixelBuffer)
+        return nullptr;
+    return MediaSampleAVFObjC::createImageSample(WTFMove(*pixelBuffer), MediaSampleAVFObjC::VideoRotation::UpsideDown, true);
 }
 #endif
+
+}
+#endif

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp (283237 => 283238)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.cpp	2021-09-29 18:21:58 UTC (rev 283238)
@@ -34,6 +34,7 @@
 #include "ImageBuffer.h"
 #include "MediaPlayerPrivate.h"
 #include "PixelBuffer.h"
+#include <memory>
 #include <wtf/UniqueArray.h>
 
 #if USE(AVFOUNDATION)
@@ -40,7 +41,9 @@
 #include "GraphicsContextGLCV.h"
 #endif
 
-#include <memory>
+#if !PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+#include "MediaSample.h"
+#endif
 
 namespace WebCore {
 
@@ -72,14 +75,6 @@
     return m_buffersToAutoClear;
 }
 
-void GraphicsContextGLOpenGL::enablePreserveDrawingBuffer()
-{
-    GraphicsContextGL::enablePreserveDrawingBuffer();
-    // After dynamically transitioning to preserveDrawingBuffer:true
-    // for canvas capture, clear out any buffer auto-clearing state.
-    m_buffersToAutoClear = 0;
-}
-
 #if !USE(ANGLE)
 bool GraphicsContextGLOpenGL::texImage2DResourceSafe(GCGLenum target, GCGLint level, GCGLenum internalformat, GCGLsizei width, GCGLsizei height, GCGLint border, GCGLenum format, GCGLenum type, GCGLint unpackAlignment)
 {
@@ -170,6 +165,13 @@
     return results;
 }
 
+#if !PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+RefPtr<MediaSample> GraphicsContextGLOpenGL::paintCompositedResultsToMediaSample()
+{
+    return nullptr;
+}
+#endif
+
 std::optional<PixelBuffer> GraphicsContextGLOpenGL::readRenderingResultsForPainting()
 {
     if (!makeContextCurrent())

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


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2021-09-29 18:19:46 UTC (rev 283237)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2021-09-29 18:21:58 UTC (rev 283238)
@@ -460,7 +460,6 @@
     void resetBuffersToAutoClear();
     void setBuffersToAutoClear(GCGLbitfield) final;
     GCGLbitfield getBuffersToAutoClear() const final;
-    void enablePreserveDrawingBuffer() final;
 
     void dispatchContextChangedNotification();
 
@@ -467,6 +466,9 @@
     void paintRenderingResultsToCanvas(ImageBuffer&) final;
     std::optional<PixelBuffer> paintRenderingResultsToPixelBuffer() final;
     void paintCompositedResultsToCanvas(ImageBuffer&) final;
+#if ENABLE(MEDIA_STREAM)
+    RefPtr<MediaSample> paintCompositedResultsToMediaSample() final;
+#endif
 
     std::optional<PixelBuffer> readRenderingResultsForPainting();
     std::optional<PixelBuffer> readCompositedResultsForPainting();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to