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
This commit is contained in:
Jamie Nicol 2021-11-29 20:52:31 +00:00
Родитель a9dd0d2943
Коммит 0155e30e96
9 изменённых файлов: 31 добавлений и 57 удалений

Просмотреть файл

@ -3242,6 +3242,10 @@ void BrowserChild::ReinitRendering() {
nsCOMPtr<Document> doc(GetTopLevelDocument());
doc->NotifyLayerManagerRecreated();
if (mRenderLayers) {
SchedulePaint();
}
}
void BrowserChild::ReinitRenderingForDeviceReset() {

Просмотреть файл

@ -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<nsWindow*>(mWidget);
window->NotifyDisablingWebRender();
}
#endif // defined(MOZ_WIDGET_ANDROID)
} // namespace layers
} // namespace mozilla

Просмотреть файл

@ -80,8 +80,6 @@ class CompositorSession {
RefPtr<UiCompositorControllerChild> GetUiCompositorControllerChild() {
return mUiCompositorControllerChild;
}
void NotifyDisablingWebRender();
#endif // defined(MOZ_WIDGET_ANDROID)
protected:
CompositorSession(nsBaseWidget* aWidget, CompositorWidgetDelegate* aDelegate,

Просмотреть файл

@ -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()) {

Просмотреть файл

@ -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:

Просмотреть файл

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

Просмотреть файл

@ -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; }

Просмотреть файл

@ -1230,9 +1230,11 @@ already_AddRefed<WebRenderLayerManager> 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

Просмотреть файл

@ -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<mozilla::CompositorVsyncDispatcher>