gecko-dev/widget/android/InProcessAndroidCompositorWidget.h
Jamie Nicol 0691a2b63f Bug 1766127 - Allow AndroidCompositorWidget::mClientSize to be updated from main thread. r=agi,gfx-reviewers,lsalzman
On Android we have long since calculated the compositor widget size
from the Surface rather than using the main thread widget size. This
is to avoid a trip via the main thread in response to a
ResumeAndResize event on the UI thread.
AndroidCompositorWidget::mClientSize therefore gets calculated when
the compositor is resumed.

However, it is possible in some circumstances for the compositor to
receive a display list prior to it being resumed. In this bug's case,
SyncResumeAndResize is getting called before the UI thread has been
notified that the compositor has been initialized. It therefore cannot
resume the compositor, and we instead resume the compositor on the
subsequent NotifyCompositorCreated call. This starts a race between
the main thread paint and NotifyCompositorCreated being scheduled on
the UI thread then resuming the compositor via
PUiCompositorController. If we receive
WebRenderBridgeParent::RecvSetDisplayList prior to
UiCompositorControllerParent::RecvResumeAndResize, then
AndroidCompositorWidget::mClientSize will be zero. This results in us
setting zero-sized webrender scene rect, leading to webrender exiting
early during rendering, resulting in a black screen.

To fix this, allow the main thread to set the AndroidCompositorWidget
size, in addition to the UI thread being able to set it. We do so by
adding a NotifyClientSizeChanged method to
PlatformCompositorWidgetDelegate, called from
nsWindow::OnSizeChanged. The cross-process implementation of this uses
an IPDL call on PCompositorWidget, which shares a top-level protocol
with PWebRenderBridge, meaning calls are guaranteed to occur in
order. This means a resize event on the main thread is guaranteed to
set the CompositorWidget size before the display list from the
subsequent paint is received.

Differential Revision: https://phabricator.services.mozilla.com/D144594
2022-04-25 18:20:55 +00:00

46 lines
1.4 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef widget_android_InProcessAndroidCompositorWidget_h
#define widget_android_InProcessAndroidCompositorWidget_h
#include "AndroidCompositorWidget.h"
#include "CompositorWidget.h"
class nsWindow;
namespace mozilla {
namespace widget {
class InProcessAndroidCompositorWidget final
: public AndroidCompositorWidget,
public PlatformCompositorWidgetDelegate {
public:
InProcessAndroidCompositorWidget(
const AndroidCompositorWidgetInitData& aInitData,
const layers::CompositorOptions& aOptions, nsWindow* aWidget);
// CompositorWidget overrides
void ObserveVsync(VsyncObserver* aObserver) override;
nsIWidget* RealWidget() override;
CompositorWidgetDelegate* AsDelegate() override { return this; }
// PlatformCompositorWidgetDelegate overrides
void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize) override;
private:
// AndroidCompositorWidget overrides
void OnCompositorSurfaceChanged() override;
nsWindow* mWindow;
};
} // namespace widget
} // namespace mozilla
#endif // widget_android_InProcessAndroidCompositorWidget_h