From 01b7e43b006b965c30ce401b12de07862b2e66ac Mon Sep 17 00:00:00 2001 From: Jamie Nicol Date: Mon, 29 Nov 2021 20:52:31 +0000 Subject: [PATCH] Bug 1741156 - Reinitialize compositor and request repaint after GPU process restart. r=aosmond,geckoview-reviewers,agi This patch ensures that, following a GPU process crash, we re-initialize the compositor and resume painting on Android. nsWindow::GetWindowRenderer() is made to always reinitialize the window renderer if there is none, like on other platforms. We therefore no longer need to track whether webrender is being disabled, as this is no longer a special case. Previously we started the compositor as initially paused in nsBaseWidget::CreateCompositorSession only if the widget did not yet have a surface. Now we must unconditionally (re)start it as initially paused, as even though the widget in the parent process may have a surface, we will not have been able to send it to the GPU process yet. We will send the surface to the compositor once control flow returns to nsWindow::CreateLayerManager, where we will also now resume the compositor if required. Finally, we must ensure that we manually trigger a paint, both in the parent and content processes. On other platforms this occurs automatically following a GPU process loss through various refresh driver events. On Android, however, nothing causes the refresh driver to paint by itself, and we cannot receive input without first initializing our APZ controllers, which does not happen until the compositor receives a display list. We therefore must manually schedule a paint. We do so from nsWindow::NotifyCompositorSessionLost for the parent process, and BrowserChild::ReinitRendering for content processes. Differential Revision: https://phabricator.services.mozilla.com/D131232 --- dom/ipc/BrowserChild.cpp | 4 ++++ gfx/ipc/CompositorSession.cpp | 14 -------------- gfx/ipc/CompositorSession.h | 2 -- gfx/ipc/GPUProcessManager.cpp | 21 --------------------- gfx/ipc/GPUProcessManager.h | 2 -- widget/android/nsWindow.cpp | 29 ++++++++++++++++++----------- widget/android/nsWindow.h | 6 +++--- widget/nsBaseWidget.cpp | 8 +++++--- widget/nsBaseWidget.h | 2 +- 9 files changed, 31 insertions(+), 57 deletions(-) diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index db204bac70be..b6ccbf0c9f44 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -3242,6 +3242,10 @@ void BrowserChild::ReinitRendering() { nsCOMPtr doc(GetTopLevelDocument()); doc->NotifyLayerManagerRecreated(); + + if (mRenderLayers) { + SchedulePaint(); + } } void BrowserChild::ReinitRenderingForDeviceReset() { diff --git a/gfx/ipc/CompositorSession.cpp b/gfx/ipc/CompositorSession.cpp index 41c495545268..ffeec65589f8 100644 --- a/gfx/ipc/CompositorSession.cpp +++ b/gfx/ipc/CompositorSession.cpp @@ -11,10 +11,6 @@ #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/CompositorBridgeParent.h" -#if defined(MOZ_WIDGET_ANDROID) -# include "mozilla/widget/nsWindow.h" -#endif // defined(MOZ_WIDGET_ANDROID) - namespace mozilla { namespace layers { @@ -36,15 +32,5 @@ CompositorBridgeChild* CompositorSession::GetCompositorBridgeChild() { return mCompositorBridgeChild; } -#if defined(MOZ_WIDGET_ANDROID) -void CompositorSession::NotifyDisablingWebRender() { - if (!mWidget) { - return; - } - nsWindow* window = static_cast(mWidget); - window->NotifyDisablingWebRender(); -} -#endif // defined(MOZ_WIDGET_ANDROID) - } // namespace layers } // namespace mozilla diff --git a/gfx/ipc/CompositorSession.h b/gfx/ipc/CompositorSession.h index d0b7f9131ece..88b223154665 100644 --- a/gfx/ipc/CompositorSession.h +++ b/gfx/ipc/CompositorSession.h @@ -80,8 +80,6 @@ class CompositorSession { RefPtr GetUiCompositorControllerChild() { return mUiCompositorControllerChild; } - - void NotifyDisablingWebRender(); #endif // defined(MOZ_WIDGET_ANDROID) protected: CompositorSession(nsBaseWidget* aWidget, CompositorWidgetDelegate* aDelegate, diff --git a/gfx/ipc/GPUProcessManager.cpp b/gfx/ipc/GPUProcessManager.cpp index 2ff523dc32b3..2d1e47e48cf8 100644 --- a/gfx/ipc/GPUProcessManager.cpp +++ b/gfx/ipc/GPUProcessManager.cpp @@ -537,15 +537,6 @@ bool GPUProcessManager::DisableWebRenderConfig(wr::WebRenderError aError, mUnstableProcessAttempts = 1; } -#if defined(MOZ_WIDGET_ANDROID) - // If aError is not wr::WebRenderError::INITIALIZE, nsWindow does not - // re-create LayerManager. Needs to trigger re-creating LayerManager on - // android - if (aError != wr::WebRenderError::INITIALIZE) { - NotifyDisablingWebRender(); - } -#endif - return true; } @@ -787,18 +778,6 @@ void GPUProcessManager::RebuildInProcessSessions() { } } -void GPUProcessManager::NotifyDisablingWebRender() { -#if defined(MOZ_WIDGET_ANDROID) - for (const auto& session : mRemoteSessions) { - session->NotifyDisablingWebRender(); - } - - for (const auto& session : mInProcessSessions) { - session->NotifyDisablingWebRender(); - } -#endif -} - void GPUProcessManager::NotifyRemoteActorDestroyed( const uint64_t& aProcessToken) { if (!NS_IsMainThread()) { diff --git a/gfx/ipc/GPUProcessManager.h b/gfx/ipc/GPUProcessManager.h index 1ae49cccde6d..36d50b6806ea 100644 --- a/gfx/ipc/GPUProcessManager.h +++ b/gfx/ipc/GPUProcessManager.h @@ -230,8 +230,6 @@ class GPUProcessManager final : public GPUProcessHost::Listener { // Returns true if WebRender was enabled and is now disabled. bool DisableWebRenderConfig(wr::WebRenderError aError, const nsCString& aMsg); - void NotifyDisablingWebRender(); - void FallbackToSoftware(const char* aMessage); private: diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index f987046a25e3..e811212f2d1a 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1710,7 +1710,6 @@ nsWindow::nsWindow() mParent(nullptr), mDynamicToolbarMaxHeight(0), mIsFullScreen(false), - mIsDisablingWebRender(false), mCompositorWidgetDelegate(nullptr) {} nsWindow::~nsWindow() { @@ -2167,17 +2166,11 @@ nsresult nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) { } mozilla::WindowRenderer* nsWindow::GetWindowRenderer() { - if (mWindowRenderer) { - return mWindowRenderer; - } - - if (mIsDisablingWebRender) { + if (!mWindowRenderer) { CreateLayerManager(); - mIsDisablingWebRender = false; - return mWindowRenderer; } - return nullptr; + return mWindowRenderer; } void nsWindow::CreateLayerManager() { @@ -2198,6 +2191,19 @@ void nsWindow::CreateLayerManager() { LayoutDeviceIntRect rect = GetBounds(); CreateCompositor(rect.Width(), rect.Height()); if (mWindowRenderer) { + auto lvs(mLayerViewSupport.Access()); + if (lvs) { + GetUiCompositorControllerChild()->OnCompositorSurfaceChanged( + mWidgetId, lvs->GetSurface()); + + if (!lvs->CompositorPaused()) { + CompositorBridgeChild* remoteRenderer = GetRemoteRenderer(); + if (remoteRenderer) { + remoteRenderer->SendResumeAsync(); + } + } + } + return; } @@ -2211,8 +2217,9 @@ void nsWindow::CreateLayerManager() { } } -void nsWindow::NotifyDisablingWebRender() { - mIsDisablingWebRender = true; +void nsWindow::NotifyCompositorSessionLost( + mozilla::layers::CompositorSession* aSession) { + nsBaseWidget::NotifyCompositorSessionLost(aSession); RedrawAll(); } diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 73fca0e8adba..7ca99d2f315b 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -127,8 +127,6 @@ class nsWindow final : public nsBaseWidget { void PassExternalResponse(mozilla::java::WebResponse::Param aResponse); - void NotifyDisablingWebRender(); - void ShowDynamicToolbar(); void DetachNatives(); @@ -184,6 +182,9 @@ class nsWindow final : public nsBaseWidget { WindowRenderer* GetWindowRenderer() override; + void NotifyCompositorSessionLost( + mozilla::layers::CompositorSession* aSession) override; + virtual bool NeedsPaint() override; virtual bool WidgetPaintsBackground() override; @@ -261,7 +262,6 @@ class nsWindow final : public nsBaseWidget { mozilla::ScreenIntMargin mSafeAreaInsets; bool mIsFullScreen; - bool mIsDisablingWebRender; bool UseExternalCompositingSurface() const override { return true; } diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index d8dff0657851..539ba8e7fdbb 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1230,9 +1230,11 @@ already_AddRefed nsBaseWidget::CreateCompositorSession( options.SetUseWebGPU(StaticPrefs::dom_webgpu_enabled()); #ifdef MOZ_WIDGET_ANDROID - if (!GetNativeData(NS_JAVA_SURFACE)) { - options.SetInitiallyPaused(true); - } + // Unconditionally set the compositor as initially paused, as we have not + // yet had a chance to send the compositor surface to the GPU process. We + // will do so shortly once we have returned to nsWindow::CreateLayerManager, + // where we will also resume the compositor if required. + options.SetInitiallyPaused(true); #else options.SetInitiallyPaused(CompositorInitiallyPaused()); #endif diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index a4afec0e68c1..5df0c4dccf79 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -219,7 +219,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { // // A reference to the session object is held until this function has // returned. - void NotifyCompositorSessionLost( + virtual void NotifyCompositorSessionLost( mozilla::layers::CompositorSession* aSession); already_AddRefed