Title: [284989] branches/safari-612-branch/Source/WebCore

Diff

Modified: branches/safari-612-branch/Source/WebCore/ChangeLog (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/ChangeLog	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/ChangeLog	2021-10-28 17:00:26 UTC (rev 284989)
@@ -1,3 +1,90 @@
+2021-10-28  Alan Coon  <alanc...@apple.com>
+
+        Apply patch. rdar://problem/84630680
+
+    2021-10-28  Null  <n...@apple.com>
+
+            Cherry-pick r283489. rdar://problem/84630680
+
+        Regression (r283238)[ MacOS wk1 ] fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events.html is timing out
+        https://bugs.webkit.org/show_bug.cgi?id=231022
+
+        Patch by Kimmo Kinnunen <kkinnu...@apple.com> on 2021-10-04
+        Reviewed by Youenn Fablet.
+
+        Originally the implementation would always return red frame, and the test would pass.
+        r283238 changed the implementation to not return a sample if there is not a display buffer,
+        as logically such cannot be used as a sample.
+        This broke the test case since the CanvasCaptureMediaStreamTrack would try to capture
+        the canvas display buffer during next runloop iteration (0s timeout) after each modification.
+        This does not work, as the display buffer is composed during "prepare for display"
+        phase.
+
+        Add CanvasBase observers to observe that display buffer has been prepared, and capture
+        the media sample after that observer has fired.
+
+        The test would work for wk2 due to timing related differences, preparation would have
+        typically run before the canvas capture 0s timeout.
+
+        Fixes fast/mediastream/captureStream/canvas3d.html for wk1.
+
+        * Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp:
+        (WebCore::CanvasCaptureMediaStreamTrack::Source::startProducingData):
+        (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasChanged):
+        (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasDisplayBufferPrepared):
+        * Modules/mediastream/CanvasCaptureMediaStreamTrack.h:
+        * html/CanvasBase.cpp:
+        (WebCore::CanvasBase::addDisplayBufferObserver):
+        (WebCore::CanvasBase::removeDisplayBufferObserver):
+        (WebCore::CanvasBase::notifyObserversCanvasDisplayBufferPrepared):
+        * html/CanvasBase.h:
+        (WebCore::CanvasBase::hasDisplayBufferObservers const):
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::prepareForDisplay):
+        Move the "prepare only when the owner element is in the tree" logic to
+        its correct place to the caller, e.g. to the element itself.
+
+        git-svn-id: https://svn.webkit.org/repository/webkit/trunk@283489 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+        2021-10-04  Kimmo Kinnunen  <kkinnu...@apple.com>
+
+                Regression (r283238)[ MacOS wk1 ] fast/mediacapturefromelement/CanvasCaptureMediaStream-webgl-events.html is timing out
+                https://bugs.webkit.org/show_bug.cgi?id=231022
+
+                Reviewed by Youenn Fablet.
+
+                Originally the implementation would always return red frame, and the test would pass.
+                r283238 changed the implementation to not return a sample if there is not a display buffer,
+                as logically such cannot be used as a sample.
+                This broke the test case since the CanvasCaptureMediaStreamTrack would try to capture
+                the canvas display buffer during next runloop iteration (0s timeout) after each modification.
+                This does not work, as the display buffer is composed during "prepare for display"
+                phase.
+
+                Add CanvasBase observers to observe that display buffer has been prepared, and capture
+                the media sample after that observer has fired.
+
+                The test would work for wk2 due to timing related differences, preparation would have
+                typically run before the canvas capture 0s timeout.
+
+                Fixes fast/mediastream/captureStream/canvas3d.html for wk1.
+
+                * Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp:
+                (WebCore::CanvasCaptureMediaStreamTrack::Source::startProducingData):
+                (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasChanged):
+                (WebCore::CanvasCaptureMediaStreamTrack::Source::canvasDisplayBufferPrepared):
+                * Modules/mediastream/CanvasCaptureMediaStreamTrack.h:
+                * html/CanvasBase.cpp:
+                (WebCore::CanvasBase::addDisplayBufferObserver):
+                (WebCore::CanvasBase::removeDisplayBufferObserver):
+                (WebCore::CanvasBase::notifyObserversCanvasDisplayBufferPrepared):
+                * html/CanvasBase.h:
+                (WebCore::CanvasBase::hasDisplayBufferObservers const):
+                * html/canvas/WebGLRenderingContextBase.cpp:
+                (WebCore::WebGLRenderingContextBase::prepareForDisplay):
+                Move the "prepare only when the owner element is in the tree" logic to
+                its correct place to the caller, e.g. to the element itself.
+
 2021-10-26  Russell Epstein  <repst...@apple.com>
 
         Cherry-pick r284669. rdar://problem/83971417

Modified: branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.cpp	2021-10-28 17:00:26 UTC (rev 284989)
@@ -89,6 +89,7 @@
     if (!m_canvas)
         return;
     m_canvas->addObserver(*this);
+    m_canvas->addDisplayBufferObserver(*this);
 
     if (!m_frameRequestRate)
         return;
@@ -104,6 +105,7 @@
     if (!m_canvas)
         return;
     m_canvas->removeObserver(*this);
+    m_canvas->removeDisplayBufferObserver(*this);
 }
 
 void CanvasCaptureMediaStreamTrack::Source::requestFrameTimerFired()
@@ -152,7 +154,13 @@
 void CanvasCaptureMediaStreamTrack::Source::canvasChanged(CanvasBase& canvas, const std::optional<FloatRect>&)
 {
     ASSERT_UNUSED(canvas, m_canvas == &canvas);
+    if (m_canvas->renderingContext() && m_canvas->renderingContext()->needsPreparationForDisplay())
+        return;
+    scheduleCaptureCanvas();
+}
 
+void CanvasCaptureMediaStreamTrack::Source::scheduleCaptureCanvas()
+{
     // FIXME: We should try to generate the frame at the time the screen is being updated.
     if (m_captureCanvasTimer.isActive())
         return;
@@ -159,6 +167,15 @@
     m_captureCanvasTimer.startOneShot(0_s);
 }
 
+void CanvasCaptureMediaStreamTrack::Source::canvasDisplayBufferPrepared(CanvasBase& canvas)
+{
+    ASSERT_UNUSED(canvas, m_canvas == &canvas);
+    // FIXME: Here we should capture the image instead.
+    // However, submitting the sample to the receiver might cause layout,
+    // and currently the display preparation is done after layout.
+    scheduleCaptureCanvas();
+}
+
 void CanvasCaptureMediaStreamTrack::Source::captureCanvas()
 {
     ASSERT(m_canvas);

Modified: branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/Modules/mediastream/CanvasCaptureMediaStreamTrack.h	2021-10-28 17:00:26 UTC (rev 284989)
@@ -30,6 +30,7 @@
 #include "MediaStreamTrack.h"
 #include "Timer.h"
 #include <wtf/TypeCasts.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
@@ -50,7 +51,7 @@
 private:
     const char* activeDOMObjectName() const override;
 
-    class Source final : public RealtimeMediaSource, private CanvasObserver {
+    class Source final : public RealtimeMediaSource, private CanvasObserver, private CanvasDisplayBufferObserver {
     public:
         static Ref<Source> create(HTMLCanvasElement&, std::optional<double>&& frameRequestRate);
         
@@ -60,18 +61,21 @@
     private:
         Source(HTMLCanvasElement&, std::optional<double>&&);
 
-        // CanvasObserver API
+        // CanvasObserver overrides.
         void canvasChanged(CanvasBase&, const std::optional<FloatRect>&) final;
         void canvasResized(CanvasBase&) final;
         void canvasDestroyed(CanvasBase&) final;
 
-        // RealtimeMediaSource API
+        // CanvasDisplayBufferObserver overrides.
+        void canvasDisplayBufferPrepared(CanvasBase&) final;
+
+        // RealtimeMediaSource overrides.
         void startProducingData() final;
         void stopProducingData()  final;
         const RealtimeMediaSourceCapabilities& capabilities() final { return RealtimeMediaSourceCapabilities::emptyCapabilities(); }
         const RealtimeMediaSourceSettings& settings() final;
         void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) final;
-
+        void scheduleCaptureCanvas();
         void captureCanvas();
         void requestFrameTimerFired();
 

Modified: branches/safari-612-branch/Source/WebCore/html/CanvasBase.cpp (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/html/CanvasBase.cpp	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/html/CanvasBase.cpp	2021-10-28 17:00:26 UTC (rev 284989)
@@ -162,6 +162,22 @@
 #endif
 }
 
+void CanvasBase::addDisplayBufferObserver(CanvasDisplayBufferObserver& observer)
+{
+    m_displayBufferObservers.add(&observer);
+}
+
+void CanvasBase::removeDisplayBufferObserver(CanvasDisplayBufferObserver& observer)
+{
+    m_displayBufferObservers.remove(observer);
+}
+
+void CanvasBase::notifyObserversCanvasDisplayBufferPrepared()
+{
+    for (auto& observer : m_displayBufferObservers)
+        observer.canvasDisplayBufferPrepared(*this);
+}
+
 HashSet<Element*> CanvasBase::cssCanvasClients() const
 {
     HashSet<Element*> cssCanvasClients;

Modified: branches/safari-612-branch/Source/WebCore/html/CanvasBase.h (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/html/CanvasBase.h	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/html/CanvasBase.h	2021-10-28 17:00:26 UTC (rev 284989)
@@ -28,6 +28,7 @@
 #include "IntSize.h"
 #include <wtf/HashSet.h>
 #include <wtf/TypeCasts.h>
+#include <wtf/WeakHashSet.h>
 
 namespace WebCore {
 
@@ -54,6 +55,13 @@
     virtual void canvasDestroyed(CanvasBase&) = 0;
 };
 
+class CanvasDisplayBufferObserver : public CanMakeWeakPtr<CanvasDisplayBufferObserver> {
+public:
+    virtual ~CanvasDisplayBufferObserver() = default;
+
+    virtual void canvasDisplayBufferPrepared(CanvasBase&) = 0;
+};
+
 class CanvasBase {
 public:
     virtual ~CanvasBase();
@@ -92,6 +100,10 @@
     void notifyObserversCanvasChanged(const std::optional<FloatRect>&);
     void notifyObserversCanvasResized();
     void notifyObserversCanvasDestroyed(); // Must be called in destruction before clearing m_context.
+    void addDisplayBufferObserver(CanvasDisplayBufferObserver&);
+    void removeDisplayBufferObserver(CanvasDisplayBufferObserver&);
+    void notifyObserversCanvasDisplayBufferPrepared();
+    bool hasDisplayBufferObservers() const { return !m_displayBufferObservers.computesEmpty(); }
 
     HashSet<Element*> cssCanvasClients() const;
 
@@ -132,6 +144,7 @@
     bool m_didNotifyObserversCanvasDestroyed { false };
 #endif
     HashSet<CanvasObserver*> m_observers;
+    WeakHashSet<CanvasDisplayBufferObserver> m_displayBufferObservers;
 };
 
 } // namespace WebCore

Modified: branches/safari-612-branch/Source/WebCore/html/HTMLCanvasElement.cpp (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/html/HTMLCanvasElement.cpp	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/html/HTMLCanvasElement.cpp	2021-10-28 17:00:26 UTC (rev 284989)
@@ -1054,8 +1054,23 @@
 {
     ASSERT(needsPreparationForDisplay());
 
+    bool shouldPrepare = true;
+#if ENABLE(WEBGL)
+    // FIXME: Currently the below prepare skip logic is conservative and applies only to
+    // WebGL elements.
+    if (is<WebGLRenderingContextBase>(m_context.get())) {
+        // If the canvas is not in the document body, then it won't be
+        // composited and thus doesn't need preparation. Unfortunately
+        // it can't tell at the time it was added to the list, since it
+        // could be inserted or removed from the document body afterwards.
+        shouldPrepare = isInTreeScope() || hasDisplayBufferObservers();
+    }
+#endif
+    if (!shouldPrepare)
+        return;
     if (m_context)
         m_context->prepareForDisplay();
+    notifyObserversCanvasDisplayBufferPrepared();
 }
 
 bool HTMLCanvasElement::isControlledByOffscreen() const

Modified: branches/safari-612-branch/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (284988 => 284989)


--- branches/safari-612-branch/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2021-10-28 16:38:53 UTC (rev 284988)
+++ branches/safari-612-branch/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2021-10-28 17:00:26 UTC (rev 284989)
@@ -8020,14 +8020,6 @@
     if (!m_context)
         return;
 
-    // If the canvas is not in the document body, then it won't be
-    // composited and thus doesn't need preparation. Unfortunately
-    // it can't tell at the time it was added to the list, since it
-    // could be inserted or removed from the document body afterwards.
-    auto canvas = htmlCanvas();
-    if (!canvas || !canvas->isInTreeScope())
-        return;
-
     m_context->prepareForDisplay();
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to