browser(firefox): screencast for headless mac (#2956)

This commit is contained in:
Yury Semikhatsky 2020-07-15 09:37:08 -07:00 committed by GitHub
parent 4a00e5c4ea
commit 0aff9bef11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 41 deletions

View file

@ -1,2 +1,2 @@
1127 1128
Changed: yurys@chromium.org Tue Jul 14 12:47:49 PDT 2020 Changed: yurys@chromium.org Wed Jul 15 09:22:48 PDT 2020

View file

@ -132,7 +132,6 @@ nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
nsIWidget* widget = view->GetWidget(); nsIWidget* widget = view->GetWidget();
#ifdef MOZ_WIDGET_GTK
*sessionId = ++mLastSessionId; *sessionId = ++mLastSessionId;
rtc::scoped_refptr<webrtc::VideoCaptureModule> capturer = CreateWindowCapturer(widget, *sessionId); rtc::scoped_refptr<webrtc::VideoCaptureModule> capturer = CreateWindowCapturer(widget, *sessionId);
if (!capturer) if (!capturer)
@ -154,10 +153,6 @@ nsresult nsScreencastService::StartVideoRecording(nsIDocShell* aDocShell, const
mIdToSession.emplace(*sessionId, std::move(session)); mIdToSession.emplace(*sessionId, std::move(session));
return NS_OK; return NS_OK;
#else
// TODO: support Windows and Mac.
return NS_ERROR_NOT_IMPLEMENTED;
#endif
} }
nsresult nsScreencastService::StopVideoRecording(int32_t sessionId) { nsresult nsScreencastService::StopVideoRecording(int32_t sessionId) {

View file

@ -1810,8 +1810,34 @@ index ea8b9b08f3e6f6e99b8a4fa3fa427beb8c5f5945..a7ec2bd3afe53d500f0cd8f800223ee2
}; };
/** /**
diff --git a/widget/InProcessCompositorWidget.cpp b/widget/InProcessCompositorWidget.cpp
index 7d7ef5a5f9e6c092e643eb5c3feef239e90c0bb2..7c975244f26b3c2ec20d8174e5d84fc9938860a9 100644
--- a/widget/InProcessCompositorWidget.cpp
+++ b/widget/InProcessCompositorWidget.cpp
@@ -4,6 +4,8 @@
#include "InProcessCompositorWidget.h"
+#include "HeadlessCompositorWidget.h"
+#include "HeadlessWidget.h"
#include "mozilla/VsyncDispatcher.h"
#include "nsBaseWidget.h"
@@ -22,6 +24,12 @@ RefPtr<CompositorWidget> CompositorWidget::CreateLocal(
const CompositorWidgetInitData& aInitData,
const layers::CompositorOptions& aOptions, nsIWidget* aWidget) {
MOZ_ASSERT(aWidget);
+ if (aInitData.type() ==
+ CompositorWidgetInitData::THeadlessCompositorWidgetInitData) {
+ return new HeadlessCompositorWidget(
+ aInitData.get_HeadlessCompositorWidgetInitData(), aOptions,
+ static_cast<HeadlessWidget*>(aWidget));
+ }
# ifdef MOZ_WIDGET_ANDROID
return new AndroidCompositorWidget(aOptions,
static_cast<nsBaseWidget*>(aWidget));
diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp diff --git a/widget/headless/HeadlessCompositorWidget.cpp b/widget/headless/HeadlessCompositorWidget.cpp
index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..41f483959bd80aa9cc6ad9eac068503639b33887 100644 index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..5f4080dacc1376cda7ec75ed0ed2823cd01d6001 100644
--- a/widget/headless/HeadlessCompositorWidget.cpp --- a/widget/headless/HeadlessCompositorWidget.cpp
+++ b/widget/headless/HeadlessCompositorWidget.cpp +++ b/widget/headless/HeadlessCompositorWidget.cpp
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
@ -1822,7 +1848,7 @@ index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..41f483959bd80aa9cc6ad9eac0685036
#include "mozilla/widget/PlatformWidgetTypes.h" #include "mozilla/widget/PlatformWidgetTypes.h"
#include "HeadlessCompositorWidget.h" #include "HeadlessCompositorWidget.h"
#include "VsyncDispatcher.h" #include "VsyncDispatcher.h"
@@ -17,6 +18,54 @@ HeadlessCompositorWidget::HeadlessCompositorWidget( @@ -17,6 +18,32 @@ HeadlessCompositorWidget::HeadlessCompositorWidget(
mClientSize = aInitData.InitialClientSize(); mClientSize = aInitData.InitialClientSize();
} }
@ -1839,6 +1865,7 @@ index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..41f483959bd80aa9cc6ad9eac0685036
+ MOZ_ASSERT(NS_IsInCompositorThread()); + MOZ_ASSERT(NS_IsInCompositorThread());
+ mSnapshotListener = std::move(listener); + mSnapshotListener = std::move(listener);
+ UpdateDrawTarget(); + UpdateDrawTarget();
+ PeriodicSnapshot();
+} +}
+ +
+already_AddRefed<gfx::DrawTarget> HeadlessCompositorWidget::StartRemoteDrawingInRegion( +already_AddRefed<gfx::DrawTarget> HeadlessCompositorWidget::StartRemoteDrawingInRegion(
@ -1850,34 +1877,11 @@ index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..41f483959bd80aa9cc6ad9eac0685036
+ RefPtr<gfx::DrawTarget> result = mDrawTarget; + RefPtr<gfx::DrawTarget> result = mDrawTarget;
+ return result.forget(); + return result.forget();
+} +}
+
+void HeadlessCompositorWidget::EndRemoteDrawingInRegion(
+ gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) {
+ if (!mDrawTarget)
+ return;
+
+ if (!mSnapshotListener)
+ return;
+
+ RefPtr<gfx::SourceSurface> snapshot = mDrawTarget->Snapshot();
+ if (!snapshot) {
+ fprintf(stderr, "Failed to get snapshot of draw target\n");
+ return;
+ }
+
+ RefPtr<gfx::DataSourceSurface> dataSurface = snapshot->GetDataSurface();
+ if (!dataSurface) {
+ fprintf(stderr, "Failed to get data surface from snapshot\n");
+ return;
+ }
+
+ mSnapshotListener(std::move(dataSurface));
+}
+ +
void HeadlessCompositorWidget::ObserveVsync(VsyncObserver* aObserver) { void HeadlessCompositorWidget::ObserveVsync(VsyncObserver* aObserver) {
if (RefPtr<CompositorVsyncDispatcher> cvd = if (RefPtr<CompositorVsyncDispatcher> cvd =
mWidget->GetCompositorVsyncDispatcher()) { mWidget->GetCompositorVsyncDispatcher()) {
@@ -29,6 +78,25 @@ nsIWidget* HeadlessCompositorWidget::RealWidget() { return mWidget; } @@ -29,6 +56,51 @@ nsIWidget* HeadlessCompositorWidget::RealWidget() { return mWidget; }
void HeadlessCompositorWidget::NotifyClientSizeChanged( void HeadlessCompositorWidget::NotifyClientSizeChanged(
const LayoutDeviceIntSize& aClientSize) { const LayoutDeviceIntSize& aClientSize) {
mClientSize = aClientSize; mClientSize = aClientSize;
@ -1900,14 +1904,40 @@ index b31a969b7ab3d0fc80912b110d91dfdf3e5991f4..41f483959bd80aa9cc6ad9eac0685036
+ // TODO: this is called on Main thread, while Start/End drawing are on Compositor thread. + // TODO: this is called on Main thread, while Start/End drawing are on Compositor thread.
+ mDrawTarget = mozilla::gfx::Factory::CreateDrawTarget( + mDrawTarget = mozilla::gfx::Factory::CreateDrawTarget(
+ mozilla::gfx::BackendType::SKIA, size, format); + mozilla::gfx::BackendType::SKIA, size, format);
+}
+
+void HeadlessCompositorWidget::PeriodicSnapshot() {
+ if (!mDrawTarget)
+ return;
+
+ if (!mSnapshotListener)
+ return;
+
+ RefPtr<gfx::SourceSurface> snapshot = mDrawTarget->Snapshot();
+ if (!snapshot) {
+ fprintf(stderr, "Failed to get snapshot of draw target\n");
+ return;
+ }
+
+ RefPtr<gfx::DataSourceSurface> dataSurface = snapshot->GetDataSurface();
+ if (!dataSurface) {
+ fprintf(stderr, "Failed to get data surface from snapshot\n");
+ return;
+ }
+
+ mSnapshotListener(std::move(dataSurface));
+
+ NS_DelayedDispatchToCurrentThread(NewRunnableMethod(
+ "HeadlessCompositorWidget::PeriodicSnapshot", this,
+ &HeadlessCompositorWidget::PeriodicSnapshot), 40);
} }
LayoutDeviceIntSize HeadlessCompositorWidget::GetClientSize() { LayoutDeviceIntSize HeadlessCompositorWidget::GetClientSize() {
diff --git a/widget/headless/HeadlessCompositorWidget.h b/widget/headless/HeadlessCompositorWidget.h diff --git a/widget/headless/HeadlessCompositorWidget.h b/widget/headless/HeadlessCompositorWidget.h
index 7f91de9e67d7ffa02de3eef1d760e5cfd05e7ad6..849cd6f98982fbabc8e483c8bb8f7935225869fc 100644 index 7f91de9e67d7ffa02de3eef1d760e5cfd05e7ad6..e6d542ac3945a1845d604e1c24bf7505fcc40e13 100644
--- a/widget/headless/HeadlessCompositorWidget.h --- a/widget/headless/HeadlessCompositorWidget.h
+++ b/widget/headless/HeadlessCompositorWidget.h +++ b/widget/headless/HeadlessCompositorWidget.h
@@ -23,9 +23,16 @@ class HeadlessCompositorWidget final : public CompositorWidget, @@ -23,9 +23,13 @@ class HeadlessCompositorWidget final : public CompositorWidget,
HeadlessWidget* aWindow); HeadlessWidget* aWindow);
void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize); void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize);
@ -1917,19 +1947,17 @@ index 7f91de9e67d7ffa02de3eef1d760e5cfd05e7ad6..849cd6f98982fbabc8e483c8bb8f7935
+ already_AddRefed<gfx::DrawTarget> StartRemoteDrawingInRegion( + already_AddRefed<gfx::DrawTarget> StartRemoteDrawingInRegion(
+ LayoutDeviceIntRegion& aInvalidRegion, layers::BufferMode* aBufferMode) override; + LayoutDeviceIntRegion& aInvalidRegion, layers::BufferMode* aBufferMode) override;
+ void EndRemoteDrawingInRegion(
+ gfx::DrawTarget* aDrawTarget,
+ const LayoutDeviceIntRegion& aInvalidRegion) override;
+ +
uintptr_t GetWidgetKey() override; uintptr_t GetWidgetKey() override;
LayoutDeviceIntSize GetClientSize() override; LayoutDeviceIntSize GetClientSize() override;
@@ -42,9 +49,15 @@ class HeadlessCompositorWidget final : public CompositorWidget, @@ -42,9 +46,16 @@ class HeadlessCompositorWidget final : public CompositorWidget,
} }
private: private:
+ void SetSnapshotListenerOnCompositorThread(HeadlessWidget::SnapshotListener&& listener); + void SetSnapshotListenerOnCompositorThread(HeadlessWidget::SnapshotListener&& listener);
+ void UpdateDrawTarget(); + void UpdateDrawTarget();
+ void PeriodicSnapshot();
+ +
HeadlessWidget* mWidget; HeadlessWidget* mWidget;
@ -1941,10 +1969,19 @@ index 7f91de9e67d7ffa02de3eef1d760e5cfd05e7ad6..849cd6f98982fbabc8e483c8bb8f7935
} // namespace widget } // namespace widget
diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp
index 7589d8a1a886dab5431e423d20f7d0aa19c2af75..19dd67a330848b6b39bfc578a6940385329fff8e 100644 index 7589d8a1a886dab5431e423d20f7d0aa19c2af75..b14925a7b6972c120a59f70fbbe70a1145a5cb4e 100644
--- a/widget/headless/HeadlessWidget.cpp --- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp +++ b/widget/headless/HeadlessWidget.cpp
@@ -499,5 +499,13 @@ nsresult HeadlessWidget::SynthesizeNativeTouchPoint( @@ -104,6 +104,8 @@ void HeadlessWidget::Destroy() {
}
}
+ SetSnapshotListener(nullptr);
+
nsBaseWidget::OnDestroy();
nsBaseWidget::Destroy();
@@ -499,5 +501,13 @@ nsresult HeadlessWidget::SynthesizeNativeTouchPoint(
return NS_OK; return NS_OK;
} }