зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1580117 - Pause composition for occluded windows on macOS. r=mstange
This pauses composition when a window becomes fully occluded. This is particularly important for platforms like macOS, where minimized / hidden windows historically would remain compositing, potentially on every vsync if the hidden window contained animations. This should lead to a nice power savings by skipping this unnecessary work. This change affects both the WebRender and legacy compositor paths. As bug 1580117 is believed to be a macOS specific issue, this is currently implemented for macOS only, but could in the future be generalized to other platforms as well (likely using size mode changes since other platforms do not notify on occlusion change). Differential Revision: https://phabricator.services.mozilla.com/D85954
This commit is contained in:
Родитель
6db78719c3
Коммит
643a99c8fa
|
@ -340,6 +340,9 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
|
|||
|
||||
bool InFullScreenMode() const { return mInFullScreenMode; }
|
||||
|
||||
void PauseCompositor();
|
||||
void ResumeCompositor();
|
||||
|
||||
protected:
|
||||
virtual ~nsCocoaWindow();
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "nsIScreenManager.h"
|
||||
#include "nsIWidgetListener.h"
|
||||
#include "VibrancyManager.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsDocShell.h"
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
#include "qcms.h"
|
||||
|
@ -44,6 +46,7 @@
|
|||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
#include "mozilla/StaticPrefs_widget.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -2090,6 +2093,12 @@ void nsCocoaWindow::DispatchOcclusionEvent() {
|
|||
if (mWidgetListener) {
|
||||
mWidgetListener->OcclusionStateChanged(mIsFullyOccluded);
|
||||
}
|
||||
|
||||
if (mIsFullyOccluded) {
|
||||
PauseCompositor();
|
||||
} else {
|
||||
ResumeCompositor();
|
||||
}
|
||||
}
|
||||
|
||||
void nsCocoaWindow::ReportSizeEvent() {
|
||||
|
@ -2105,6 +2114,72 @@ void nsCocoaWindow::ReportSizeEvent() {
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
void nsCocoaWindow::PauseCompositor() {
|
||||
nsIWidget* mainChildView = static_cast<nsIWidget*>([[mWindow mainChildView] widget]);
|
||||
if (!mainChildView) {
|
||||
return;
|
||||
}
|
||||
CompositorBridgeChild* remoteRenderer = mainChildView->GetRemoteRenderer();
|
||||
if (!remoteRenderer) {
|
||||
return;
|
||||
}
|
||||
remoteRenderer->SendPause();
|
||||
|
||||
// Now that the compositor has paused, we also try to mark the browser window
|
||||
// docshell inactive to stop any animations. This does not affect docshells
|
||||
// for browsers in other processes, but browser UI code should be managing
|
||||
// their active state appropriately.
|
||||
if (!mWidgetListener) {
|
||||
return;
|
||||
}
|
||||
PresShell* presShell = mWidgetListener->GetPresShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (!presContext) {
|
||||
return;
|
||||
}
|
||||
nsDocShell* docShell = presContext->GetDocShell();
|
||||
if (!docShell) {
|
||||
return;
|
||||
}
|
||||
docShell->SetIsActive(false);
|
||||
}
|
||||
|
||||
void nsCocoaWindow::ResumeCompositor() {
|
||||
nsIWidget* mainChildView = static_cast<nsIWidget*>([[mWindow mainChildView] widget]);
|
||||
if (!mainChildView) {
|
||||
return;
|
||||
}
|
||||
CompositorBridgeChild* remoteRenderer = mainChildView->GetRemoteRenderer();
|
||||
if (!remoteRenderer) {
|
||||
return;
|
||||
}
|
||||
remoteRenderer->SendResume();
|
||||
|
||||
// Now that the compositor has resumed, we also try to mark the browser window
|
||||
// docshell active to restart any animations. This does not affect docshells
|
||||
// for browsers in other processes, but browser UI code should be managing
|
||||
// their active state appropriately.
|
||||
if (!mWidgetListener) {
|
||||
return;
|
||||
}
|
||||
PresShell* presShell = mWidgetListener->GetPresShell();
|
||||
if (!presShell) {
|
||||
return;
|
||||
}
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (!presContext) {
|
||||
return;
|
||||
}
|
||||
nsDocShell* docShell = presContext->GetDocShell();
|
||||
if (!docShell) {
|
||||
return;
|
||||
}
|
||||
docShell->SetIsActive(true);
|
||||
}
|
||||
|
||||
void nsCocoaWindow::SetMenuBar(nsMenuBarX* aMenuBar) {
|
||||
if (mMenuBar) mMenuBar->SetParent(nullptr);
|
||||
if (!mWindow) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче