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();
}