зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1722450 [Wayland] Pause compositor when screen scale changes and content is not updated yet, r=sotaro
We need to track window compositor state in various cases, when compositor is paused after window creation, when compositor is paused for hidden window (EGLSurface is missing) and paused compositor when layout is not updated yet and drawing will lead to incorrect / obsoleted window content. In this patch we track compositor state by WindowCompositorState atomic enum (because it can be accessed from Compositor thread) and two private methods (PauseCompositorHiddenWindow and ResumeCompositorHiddenWindow) and two public ones (PauseCompositor() and ResumeCompositor). Private interface is used by nsWindow when EGLSurface is missing so we can't render to window - it's initial compositor pause and pause when window is hidden. Public interface is used by nsWindow and WebRender compositor to disable/enable rendering when window content is updated. When compositor is disabled by public interface it will be enabled automatically after a timeout (1s) or when content layout is updated. Changes in the patch: - Implement GtkCompositorWidget::RemoteLayoutSizeUpdated() to notify GtkCompositorWidget widget about layout size update in content process. - Track nsWindow compositor state by WindowCompositorState - Implement nsWindow::PauseCompositorHiddenWindow() and ResumeCompositorHiddenWindow() to handle internal nsWindow states. - Implement nsWindow::PauseCompositor() and nsWindow::ResumeCompositor() to allow compositor pause/resume during content layout updates. - Use timeout to resume compositor paused by public interface as a fallback when content is not updated or it takes too long. Differential Revision: https://phabricator.services.mozilla.com/D121650
This commit is contained in:
Родитель
39d89466c3
Коммит
e9207013f4
|
@ -50,6 +50,9 @@
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
# include "mozilla/widget/WinCompositorWidget.h"
|
# include "mozilla/widget/WinCompositorWidget.h"
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MOZ_WIDGET_GTK)
|
||||||
|
# include "mozilla/widget/GtkCompositorWidget.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool is_in_main_thread() { return NS_IsMainThread(); }
|
bool is_in_main_thread() { return NS_IsMainThread(); }
|
||||||
|
|
||||||
|
@ -1113,6 +1116,11 @@ bool WebRenderBridgeParent::SetDisplayList(
|
||||||
wr::Vec<uint8_t> dlCache(std::move(aDLCache));
|
wr::Vec<uint8_t> dlCache(std::move(aDLCache));
|
||||||
|
|
||||||
if (IsRootWebRenderBridgeParent()) {
|
if (IsRootWebRenderBridgeParent()) {
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (mWidget->AsGTK()) {
|
||||||
|
mWidget->AsGTK()->RemoteLayoutSizeUpdated(aRect);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
LayoutDeviceIntSize widgetSize = mWidget->GetClientSize();
|
LayoutDeviceIntSize widgetSize = mWidget->GetClientSize();
|
||||||
LayoutDeviceIntRect rect =
|
LayoutDeviceIntRect rect =
|
||||||
LayoutDeviceIntRect(LayoutDeviceIntPoint(), widgetSize);
|
LayoutDeviceIntRect(LayoutDeviceIntPoint(), widgetSize);
|
||||||
|
|
|
@ -88,6 +88,22 @@ LayoutDeviceIntSize GtkCompositorWidget::GetClientSize() {
|
||||||
return *size;
|
return *size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GtkCompositorWidget::RemoteLayoutSizeUpdated(
|
||||||
|
const LayoutDeviceRect& aSize) {
|
||||||
|
if (!mWidget || !mWidget->IsWaitingForCompositorResume()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're waiting for layout to match widget size.
|
||||||
|
auto clientSize = mClientSize.Lock();
|
||||||
|
if (clientSize->width != (int)aSize.width ||
|
||||||
|
clientSize->height != (int)aSize.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWidget->ResumeCompositorFromCompositorThread();
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t GtkCompositorWidget::GetWidgetKey() {
|
uintptr_t GtkCompositorWidget::GetWidgetKey() {
|
||||||
return reinterpret_cast<uintptr_t>(mWidget);
|
return reinterpret_cast<uintptr_t>(mWidget);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ class GtkCompositorWidget : public CompositorWidget,
|
||||||
uintptr_t GetWidgetKey() override;
|
uintptr_t GetWidgetKey() override;
|
||||||
|
|
||||||
LayoutDeviceIntSize GetClientSize() override;
|
LayoutDeviceIntSize GetClientSize() override;
|
||||||
|
void RemoteLayoutSizeUpdated(const LayoutDeviceRect& aSize);
|
||||||
|
|
||||||
nsIWidget* RealWidget() override;
|
nsIWidget* RealWidget() override;
|
||||||
GtkCompositorWidget* AsGTK() override { return this; }
|
GtkCompositorWidget* AsGTK() override { return this; }
|
||||||
|
|
|
@ -437,8 +437,8 @@ nsWindow::nsWindow()
|
||||||
mGdkWindow(nullptr),
|
mGdkWindow(nullptr),
|
||||||
mWindowShouldStartDragging(false),
|
mWindowShouldStartDragging(false),
|
||||||
mCompositorWidgetDelegate(nullptr),
|
mCompositorWidgetDelegate(nullptr),
|
||||||
mNeedsCompositorResume(false),
|
mCompositorState(COMPOSITOR_ENABLED),
|
||||||
mCompositorInitiallyPaused(false),
|
mCompositorPauseTimeoutID(0),
|
||||||
mHasMappedToplevel(false),
|
mHasMappedToplevel(false),
|
||||||
mRetryPointerGrab(false),
|
mRetryPointerGrab(false),
|
||||||
mSizeState(nsSizeMode_Normal),
|
mSizeState(nsSizeMode_Normal),
|
||||||
|
@ -717,6 +717,11 @@ void nsWindow::Destroy() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (mCompositorPauseTimeoutID) {
|
||||||
|
g_source_remove(mCompositorPauseTimeoutID);
|
||||||
|
mCompositorPauseTimeoutID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// It is safe to call DestroyeCompositor several times (here and
|
// It is safe to call DestroyeCompositor several times (here and
|
||||||
// in the parent class) since it will take effect only once.
|
// in the parent class) since it will take effect only once.
|
||||||
// The reason we call it here is because on gtk platforms we need
|
// The reason we call it here is because on gtk platforms we need
|
||||||
|
@ -1314,7 +1319,7 @@ void nsWindow::RemovePopupFromHierarchyList() {
|
||||||
|
|
||||||
void nsWindow::HideWaylandWindow() {
|
void nsWindow::HideWaylandWindow() {
|
||||||
LOG(("nsWindow::HideWaylandWindow: [%p]\n", this));
|
LOG(("nsWindow::HideWaylandWindow: [%p]\n", this));
|
||||||
PauseCompositor();
|
PauseCompositorHiddenWindow();
|
||||||
gtk_widget_hide(mShell);
|
gtk_widget_hide(mShell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4722,6 +4727,12 @@ void nsWindow::OnScaleChanged() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We pause compositor to avoid rendering of obsoleted remote content which
|
||||||
|
// produces flickering.
|
||||||
|
// Re-enable compositor again when remote content is updated or
|
||||||
|
// timeout happens.
|
||||||
|
PauseCompositor();
|
||||||
|
|
||||||
// Force scale factor recalculation
|
// Force scale factor recalculation
|
||||||
mWindowScaleFactorChanged = true;
|
mWindowScaleFactorChanged = true;
|
||||||
|
|
||||||
|
@ -5380,12 +5391,16 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||||
mContainer = MOZ_CONTAINER(container);
|
mContainer = MOZ_CONTAINER(container);
|
||||||
#ifdef MOZ_WAYLAND
|
#ifdef MOZ_WAYLAND
|
||||||
if (GdkIsWaylandDisplay() && mIsAccelerated) {
|
if (GdkIsWaylandDisplay() && mIsAccelerated) {
|
||||||
mCompositorInitiallyPaused = true;
|
mCompositorState = COMPOSITOR_PAUSED_INITIALLY;
|
||||||
RefPtr<nsWindow> self(this);
|
RefPtr<nsWindow> self(this);
|
||||||
moz_container_wayland_add_initial_draw_callback(
|
moz_container_wayland_add_initial_draw_callback(
|
||||||
mContainer, [self]() -> void {
|
mContainer, [self]() -> void {
|
||||||
self->mNeedsCompositorResume = true;
|
MOZ_LOG(self->IsPopup() ? gWidgetPopupLog : gWidgetLog,
|
||||||
self->MaybeResumeCompositor();
|
mozilla::LogLevel::Debug,
|
||||||
|
("moz_container_wayland initial create "
|
||||||
|
"ResumeCompositorHiddenWindow()"));
|
||||||
|
self->mCompositorState = COMPOSITOR_PAUSED_MISSING_EGL_WINDOW;
|
||||||
|
self->ResumeCompositorHiddenWindow();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -5448,9 +5463,8 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||||
mGdkWindow = gtk_widget_get_window(eventWidget);
|
mGdkWindow = gtk_widget_get_window(eventWidget);
|
||||||
|
|
||||||
if (GdkIsX11Display() && gfx::gfxVars::UseEGL() && mIsAccelerated) {
|
if (GdkIsX11Display() && gfx::gfxVars::UseEGL() && mIsAccelerated) {
|
||||||
mCompositorInitiallyPaused = true;
|
mCompositorState = COMPOSITOR_PAUSED_MISSING_EGL_WINDOW;
|
||||||
mNeedsCompositorResume = true;
|
ResumeCompositorHiddenWindow();
|
||||||
MaybeResumeCompositor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsWaylandPanelWindow) {
|
if (mIsWaylandPanelWindow) {
|
||||||
|
@ -5645,12 +5659,11 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("nsWindow [%p] %s %s\n", (void*)this,
|
LOG(("nsWindow [%p] type %d %s\n", (void*)this, mWindowType,
|
||||||
mWindowType == eWindowType_toplevel ? "Toplevel" : "Popup",
|
|
||||||
mIsPIPWindow ? "PIP window" : ""));
|
mIsPIPWindow ? "PIP window" : ""));
|
||||||
if (mShell) {
|
if (mShell) {
|
||||||
LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n", mShell, mContainer,
|
LOG(("\tmShell %p mContainer %p mGdkWindow %p XID 0x%lx\n", mShell,
|
||||||
mGdkWindow,
|
mContainer, mGdkWindow,
|
||||||
GdkIsX11Display() ? gdk_x11_window_get_xid(mGdkWindow) : 0));
|
GdkIsX11Display() ? gdk_x11_window_get_xid(mGdkWindow) : 0));
|
||||||
} else if (mContainer) {
|
} else if (mContainer) {
|
||||||
LOG(("\tmContainer %p mGdkWindow %p\n", mContainer, mGdkWindow));
|
LOG(("\tmContainer %p mGdkWindow %p\n", mContainer, mGdkWindow));
|
||||||
|
@ -5884,46 +5897,50 @@ void nsWindow::NativeMoveResize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsWindow::MaybeResumeCompositor() {
|
void nsWindow::ResumeCompositorHiddenWindow() {
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (mIsDestroyed || !mNeedsCompositorResume) {
|
if (mIsDestroyed || mCompositorState == COMPOSITOR_ENABLED ||
|
||||||
|
mCompositorState == COMPOSITOR_PAUSED_INITIALLY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
|
if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
|
||||||
|
LOG(("nsWindow::ResumeCompositorHiddenWindow [%p]\n", (void*)this));
|
||||||
MOZ_ASSERT(mCompositorWidgetDelegate);
|
MOZ_ASSERT(mCompositorWidgetDelegate);
|
||||||
if (mCompositorWidgetDelegate) {
|
if (mCompositorWidgetDelegate) {
|
||||||
mCompositorInitiallyPaused = false;
|
mCompositorState = COMPOSITOR_ENABLED;
|
||||||
mNeedsCompositorResume = false;
|
|
||||||
remoteRenderer->SendResumeAsync();
|
remoteRenderer->SendResumeAsync();
|
||||||
}
|
}
|
||||||
remoteRenderer->SendForcePresent();
|
remoteRenderer->SendForcePresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsWindow::PauseCompositor() {
|
|
||||||
// Because wl_egl_window is destroyed on moz_container_unmap(),
|
// Because wl_egl_window is destroyed on moz_container_unmap(),
|
||||||
// the current compositor cannot use it anymore. To avoid crash,
|
// the current compositor cannot use it anymore. To avoid crash,
|
||||||
// pause the compositor and destroy EGLSurface & resume the compositor
|
// pause the compositor and destroy EGLSurface & resume the compositor
|
||||||
// and re-create EGLSurface on next expose event.
|
// and re-create EGLSurface on next expose event.
|
||||||
|
void nsWindow::PauseCompositorHiddenWindow() {
|
||||||
// moz_container_wayland_has_egl_window() could not be used here, since
|
if (!mIsAccelerated || mIsDestroyed ||
|
||||||
// there is a case that resume compositor is not completed yet.
|
mCompositorState == COMPOSITOR_PAUSED_INITIALLY) {
|
||||||
|
|
||||||
// TODO: The compositor backend currently relies on the pause event to work
|
|
||||||
// around a Gnome specific bug. Remove again once the fix is widely available.
|
|
||||||
// See bug 1721298
|
|
||||||
if ((!mIsAccelerated && !gfx::gfxVars::UseWebRenderCompositor()) ||
|
|
||||||
mIsDestroyed) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(("nsWindow::PauseCompositorHiddenWindow [%p]\n", (void*)this));
|
||||||
|
|
||||||
|
mCompositorState = COMPOSITOR_PAUSED_MISSING_EGL_WINDOW;
|
||||||
|
|
||||||
|
// Without remote widget / renderer we can't pause compositor.
|
||||||
|
// So delete LayerManager to avoid EGLSurface access.
|
||||||
CompositorBridgeChild* remoteRenderer = GetRemoteRenderer();
|
CompositorBridgeChild* remoteRenderer = GetRemoteRenderer();
|
||||||
bool needsCompositorPause =
|
if (!remoteRenderer || !mCompositorWidgetDelegate) {
|
||||||
!mNeedsCompositorResume && !!remoteRenderer && mCompositorWidgetDelegate;
|
LOG((" deleted layer manager"));
|
||||||
if (needsCompositorPause) {
|
DestroyLayerManager();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// XXX slow sync IPC
|
// XXX slow sync IPC
|
||||||
|
LOG((" paused compositor"));
|
||||||
remoteRenderer->SendPause();
|
remoteRenderer->SendPause();
|
||||||
#ifdef MOZ_WAYLAND
|
#ifdef MOZ_WAYLAND
|
||||||
if (GdkIsWaylandDisplay()) {
|
if (GdkIsWaylandDisplay()) {
|
||||||
|
@ -5931,14 +5948,91 @@ void nsWindow::PauseCompositor() {
|
||||||
RefPtr<nsWindow> self(this);
|
RefPtr<nsWindow> self(this);
|
||||||
moz_container_wayland_add_initial_draw_callback(
|
moz_container_wayland_add_initial_draw_callback(
|
||||||
mContainer, [self]() -> void {
|
mContainer, [self]() -> void {
|
||||||
self->mNeedsCompositorResume = true;
|
MOZ_LOG(self->IsPopup() ? gWidgetPopupLog : gWidgetLog,
|
||||||
self->MaybeResumeCompositor();
|
mozilla::LogLevel::Debug,
|
||||||
|
("moz_container_wayland resume callback "
|
||||||
|
"ResumeCompositorHiddenWindow()"));
|
||||||
|
self->ResumeCompositorHiddenWindow();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
|
||||||
DestroyLayerManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int WindowResumeCompositor(void* data) {
|
||||||
|
nsWindow* window = static_cast<nsWindow*>(data);
|
||||||
|
window->ResumeCompositor();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We pause compositor to avoid rendering of obsoleted remote content which
|
||||||
|
// produces flickering.
|
||||||
|
// Re-enable compositor again when remote content is updated or
|
||||||
|
// timeout happens.
|
||||||
|
|
||||||
|
// Define maximal compositor pause when it's paused to avoid flickering,
|
||||||
|
// in milliseconds.
|
||||||
|
#define COMPOSITOR_PAUSE_TIMEOUT (1000)
|
||||||
|
|
||||||
|
void nsWindow::PauseCompositor() {
|
||||||
|
bool pauseCompositor = (mWindowType == eWindowType_toplevel) &&
|
||||||
|
mCompositorState == COMPOSITOR_ENABLED &&
|
||||||
|
mIsAccelerated && mCompositorWidgetDelegate &&
|
||||||
|
!mIsDestroyed;
|
||||||
|
if (!pauseCompositor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("nsWindow::PauseCompositor() [%p]\n", (void*)this));
|
||||||
|
|
||||||
|
if (mCompositorPauseTimeoutID) {
|
||||||
|
g_source_remove(mCompositorPauseTimeoutID);
|
||||||
|
mCompositorPauseTimeoutID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositorBridgeChild* remoteRenderer = GetRemoteRenderer();
|
||||||
|
if (remoteRenderer) {
|
||||||
|
remoteRenderer->SendPause();
|
||||||
|
mCompositorState = COMPOSITOR_PAUSED_FLICKERING;
|
||||||
|
mCompositorPauseTimeoutID = (int)g_timeout_add(
|
||||||
|
COMPOSITOR_PAUSE_TIMEOUT, &WindowResumeCompositor, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nsWindow::IsWaitingForCompositorResume() {
|
||||||
|
return !mIsDestroyed && mCompositorState == COMPOSITOR_PAUSED_FLICKERING;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsWindow::ResumeCompositor() {
|
||||||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!IsWaitingForCompositorResume()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("nsWindow::ResumeCompositor() [%p]\n", (void*)this));
|
||||||
|
|
||||||
|
if (mCompositorPauseTimeoutID) {
|
||||||
|
g_source_remove(mCompositorPauseTimeoutID);
|
||||||
|
mCompositorPauseTimeoutID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're expected to have mCompositorWidgetDelegate present
|
||||||
|
// as we don't delete LayerManager (in PauseCompositor())
|
||||||
|
// to avoid flickering.
|
||||||
|
MOZ_RELEASE_ASSERT(mCompositorWidgetDelegate);
|
||||||
|
|
||||||
|
CompositorBridgeChild* remoteRenderer = GetRemoteRenderer();
|
||||||
|
if (remoteRenderer) {
|
||||||
|
mCompositorState = COMPOSITOR_ENABLED;
|
||||||
|
remoteRenderer->SendResumeAsync();
|
||||||
|
remoteRenderer->SendForcePresent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nsWindow::ResumeCompositorFromCompositorThread() {
|
||||||
|
nsCOMPtr<nsIRunnable> event = NewRunnableMethod(
|
||||||
|
"nsWindow::ResumeCompositor", this, &nsWindow::ResumeCompositor);
|
||||||
|
NS_DispatchToMainThread(event.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsWindow::WaylandStartVsync() {
|
void nsWindow::WaylandStartVsync() {
|
||||||
|
@ -8295,13 +8389,16 @@ nsIWidget::WindowRenderer* nsWindow::GetWindowRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsWindow::SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) {
|
void nsWindow::SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) {
|
||||||
|
LOG(("nsWindow::SetCompositorWidgetDelegate [%p] %p\n", (void*)this,
|
||||||
|
delegate));
|
||||||
|
|
||||||
if (delegate) {
|
if (delegate) {
|
||||||
mCompositorWidgetDelegate = delegate->AsPlatformSpecificDelegate();
|
mCompositorWidgetDelegate = delegate->AsPlatformSpecificDelegate();
|
||||||
MOZ_ASSERT(mCompositorWidgetDelegate,
|
MOZ_ASSERT(mCompositorWidgetDelegate,
|
||||||
"nsWindow::SetCompositorWidgetDelegate called with a "
|
"nsWindow::SetCompositorWidgetDelegate called with a "
|
||||||
"non-PlatformCompositorWidgetDelegate");
|
"non-PlatformCompositorWidgetDelegate");
|
||||||
|
ResumeCompositorHiddenWindow();
|
||||||
WaylandStartVsync();
|
WaylandStartVsync();
|
||||||
MaybeResumeCompositor();
|
|
||||||
} else {
|
} else {
|
||||||
WaylandStopVsync();
|
WaylandStopVsync();
|
||||||
mCompositorWidgetDelegate = nullptr;
|
mCompositorWidgetDelegate = nullptr;
|
||||||
|
|
|
@ -407,6 +407,25 @@ class nsWindow final : public nsBaseWidget {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
// WebRender compositor is enabled
|
||||||
|
COMPOSITOR_ENABLED,
|
||||||
|
// WebRender compositor is paused after window creation.
|
||||||
|
COMPOSITOR_PAUSED_INITIALLY,
|
||||||
|
// WebRender compositor is paused because GtkWindow is hidden,
|
||||||
|
// we can't draw into EGLSurface.
|
||||||
|
COMPOSITOR_PAUSED_MISSING_EGL_WINDOW,
|
||||||
|
// WebRender compositor is paused as we're repainting whole window and
|
||||||
|
// we're waiting for content process to update page content.
|
||||||
|
COMPOSITOR_PAUSED_FLICKERING
|
||||||
|
} WindowCompositorState;
|
||||||
|
|
||||||
|
// Pause compositor to avoid rendering artifacts from content process.
|
||||||
|
void ResumeCompositor();
|
||||||
|
void ResumeCompositorFromCompositorThread();
|
||||||
|
void PauseCompositor();
|
||||||
|
bool IsWaitingForCompositorResume();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~nsWindow();
|
virtual ~nsWindow();
|
||||||
|
|
||||||
|
@ -418,7 +437,7 @@ class nsWindow final : public nsBaseWidget {
|
||||||
virtual void RegisterTouchWindow() override;
|
virtual void RegisterTouchWindow() override;
|
||||||
virtual bool CompositorInitiallyPaused() override {
|
virtual bool CompositorInitiallyPaused() override {
|
||||||
#ifdef MOZ_WAYLAND
|
#ifdef MOZ_WAYLAND
|
||||||
return mCompositorInitiallyPaused;
|
return mCompositorState == COMPOSITOR_PAUSED_INITIALLY;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
@ -471,9 +490,8 @@ class nsWindow final : public nsBaseWidget {
|
||||||
|
|
||||||
void DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
|
void DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
|
||||||
GdkEventButton* aEvent);
|
GdkEventButton* aEvent);
|
||||||
|
void ResumeCompositorHiddenWindow();
|
||||||
void MaybeResumeCompositor();
|
void PauseCompositorHiddenWindow();
|
||||||
void PauseCompositor();
|
|
||||||
|
|
||||||
void WaylandStartVsync();
|
void WaylandStartVsync();
|
||||||
void WaylandStopVsync();
|
void WaylandStopVsync();
|
||||||
|
@ -518,9 +536,10 @@ class nsWindow final : public nsBaseWidget {
|
||||||
GdkWindow* mGdkWindow;
|
GdkWindow* mGdkWindow;
|
||||||
bool mWindowShouldStartDragging;
|
bool mWindowShouldStartDragging;
|
||||||
PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
|
PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
|
||||||
|
WindowCompositorState mCompositorState;
|
||||||
bool mNeedsCompositorResume;
|
// This is used in COMPOSITOR_PAUSED_FLICKERING mode only to resume compositor
|
||||||
bool mCompositorInitiallyPaused;
|
// in some reasonable time when page content is not updated.
|
||||||
|
int mCompositorPauseTimeoutID;
|
||||||
|
|
||||||
uint32_t mHasMappedToplevel : 1, mRetryPointerGrab : 1;
|
uint32_t mHasMappedToplevel : 1, mRetryPointerGrab : 1;
|
||||||
nsSizeMode mSizeState;
|
nsSizeMode mSizeState;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче