Bug 1765399 - Don't create a new SoftwareVsyncSource instance when layout.frame_rate is changed to a different value. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D144378
This commit is contained in:
Markus Stange 2022-05-04 16:13:40 +00:00
Родитель c6833dc477
Коммит 5d919a3c2e
6 изменённых файлов: 78 добавлений и 64 удалений

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

@ -368,5 +368,5 @@ gfxAndroidPlatform::CreateGlobalHardwareVsyncSource() {
}
NS_WARNING("Vsync not supported. Falling back to software vsync");
return CreateSoftwareVsyncSource();
return GetSoftwareVsyncSource();
}

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

@ -167,8 +167,6 @@ using namespace mozilla::gfx;
gfxPlatform* gPlatform = nullptr;
static bool gEverInitialized = false;
static int32_t gLastUsedFrameRate = -1;
const ContentDeviceData* gContentDeviceInitData = nullptr;
Atomic<bool, MemoryOrdering::ReleaseAcquire> gfxPlatform::gCMSInitialized;
@ -781,16 +779,6 @@ WebRenderMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
#undef REPORT_INTERNER
#undef REPORT_DATA_STORE
static void FrameRatePrefChanged(const char* aPref, void*) {
int32_t newRate = gfxPlatform::ForceSoftwareVsync()
? gfxPlatform::GetSoftwareVsyncRate()
: -1;
if (newRate != gLastUsedFrameRate) {
gLastUsedFrameRate = newRate;
gfxPlatform::ReInitFrameRate();
}
}
void gfxPlatform::Init() {
MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
MOZ_RELEASE_ASSERT(!XRE_IsRDDProcess(), "GFX: Not allowed in RDD process.");
@ -940,14 +928,19 @@ void gfxPlatform::Init() {
nsAutoCString allowlist;
Preferences::GetCString("gfx.offscreencanvas.domain-allowlist", allowlist);
gfxVars::SetOffscreenCanvasDomainAllowlist(allowlist);
}
gLastUsedFrameRate = ForceSoftwareVsync() ? GetSoftwareVsyncRate() : -1;
Preferences::RegisterCallback(
FrameRatePrefChanged,
nsDependentCString(StaticPrefs::GetPrefName_layout_frame_rate()));
// Set up the vsync source for the parent process.
ReInitFrameRate();
// Create the global vsync source and dispatcher.
RefPtr<VsyncSource> vsyncSource =
gfxPlatform::ForceSoftwareVsync()
? gPlatform->GetSoftwareVsyncSource()
: gPlatform->GetGlobalHardwareVsyncSource();
gPlatform->mVsyncDispatcher = new VsyncDispatcher(vsyncSource);
// Listen for layout.frame_rate pref changes.
Preferences::RegisterCallback(
gfxPlatform::ReInitFrameRate,
nsDependentCString(StaticPrefs::GetPrefName_layout_frame_rate()));
}
// Create the sRGB to output display profile transforms. They can be accessed
// off the main thread so we want to avoid a race condition.
@ -1239,10 +1232,18 @@ void gfxPlatform::Shutdown() {
}
if (XRE_IsParentProcess()) {
gPlatform->mVsyncSource->Shutdown();
if (gPlatform->mGlobalHardwareVsyncSource) {
gPlatform->mGlobalHardwareVsyncSource->Shutdown();
}
if (gPlatform->mSoftwareVsyncSource &&
gPlatform->mSoftwareVsyncSource !=
gPlatform->mGlobalHardwareVsyncSource) {
gPlatform->mSoftwareVsyncSource->Shutdown();
}
}
gPlatform->mVsyncSource = nullptr;
gPlatform->mGlobalHardwareVsyncSource = nullptr;
gPlatform->mSoftwareVsyncSource = nullptr;
gPlatform->mVsyncDispatcher = nullptr;
// Shut down the default GL context provider.
@ -2988,6 +2989,14 @@ RefPtr<mozilla::VsyncDispatcher> gfxPlatform::GetGlobalVsyncDispatcher() {
return mVsyncDispatcher;
}
already_AddRefed<mozilla::gfx::VsyncSource>
gfxPlatform::GetGlobalHardwareVsyncSource() {
if (!mGlobalHardwareVsyncSource) {
mGlobalHardwareVsyncSource = CreateGlobalHardwareVsyncSource();
}
return do_AddRef(mGlobalHardwareVsyncSource);
}
/***
* The preference "layout.frame_rate" has 3 meanings depending on the value:
*
@ -2997,12 +3006,13 @@ RefPtr<mozilla::VsyncDispatcher> gfxPlatform::GetGlobalVsyncDispatcher() {
* X = Software vsync at a rate of X times per second.
*/
already_AddRefed<mozilla::gfx::VsyncSource>
gfxPlatform::CreateSoftwareVsyncSource() {
double rateInMS = 1000.0 / (double)gfxPlatform::GetSoftwareVsyncRate();
RefPtr<mozilla::gfx::VsyncSource> softwareVsync =
new mozilla::gfx::SoftwareVsyncSource(
TimeDuration::FromMilliseconds(rateInMS));
return softwareVsync.forget();
gfxPlatform::GetSoftwareVsyncSource() {
if (!mSoftwareVsyncSource) {
double rateInMS = 1000.0 / (double)gfxPlatform::GetSoftwareVsyncRate();
mSoftwareVsyncSource = new mozilla::gfx::SoftwareVsyncSource(
TimeDuration::FromMilliseconds(rateInMS));
}
return do_AddRef(mSoftwareVsyncSource);
}
/* static */
@ -3033,31 +3043,23 @@ int gfxPlatform::GetSoftwareVsyncRate() {
int gfxPlatform::GetDefaultFrameRate() { return 60; }
/* static */
void gfxPlatform::ReInitFrameRate() {
if (XRE_IsParentProcess()) {
RefPtr<VsyncSource> oldSource = gPlatform->mVsyncSource;
void gfxPlatform::ReInitFrameRate(const char* aPrefIgnored,
void* aDataIgnored) {
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
// Start a new one:
if (gfxPlatform::ForceSoftwareVsync()) {
gPlatform->mVsyncSource = gPlatform->CreateSoftwareVsyncSource();
} else {
gPlatform->mVsyncSource = gPlatform->CreateGlobalHardwareVsyncSource();
}
if (gPlatform->mVsyncDispatcher) {
// Swap out the dispatcher's underlying source.
gPlatform->mVsyncDispatcher->SetVsyncSource(gPlatform->mVsyncSource);
} else {
// Initial assignment of the vsync dispatcher.
gPlatform->mVsyncDispatcher =
new VsyncDispatcher(gPlatform->mVsyncSource);
}
// Shut down the old vsync source.
if (oldSource) {
oldSource->Shutdown();
}
if (gPlatform->mSoftwareVsyncSource) {
// Update the rate of the existing software vsync source.
double rateInMS = 1000.0 / (double)gfxPlatform::GetSoftwareVsyncRate();
gPlatform->mSoftwareVsyncSource->SetVsyncRate(
TimeDuration::FromMilliseconds(rateInMS));
}
// Swap out the dispatcher's underlying source.
RefPtr<VsyncSource> vsyncSource =
gfxPlatform::ForceSoftwareVsync()
? gPlatform->GetSoftwareVsyncSource()
: gPlatform->GetGlobalHardwareVsyncSource();
gPlatform->mVsyncDispatcher->SetVsyncSource(vsyncSource);
}
const char* gfxPlatform::GetAzureCanvasBackend() const {

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

@ -55,6 +55,7 @@ class SourceSurface;
class DataSourceSurface;
class ScaledFont;
class VsyncSource;
class SoftwareVsyncSource;
class ContentDeviceData;
class GPUDeviceData;
class FeatureState;
@ -685,7 +686,7 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
/**
* Update the frame rate (called e.g. after pref changes).
*/
static void ReInitFrameRate();
static void ReInitFrameRate(const char* aPrefIgnored, void* aDataIgnored);
/**
* Update force subpixel AA quality setting (called after pref
@ -819,13 +820,16 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
*/
virtual void WillShutdown();
// Create a software vsync source (which uses a timer internally).
// Return a hardware vsync source for this platform.
already_AddRefed<mozilla::gfx::VsyncSource> GetGlobalHardwareVsyncSource();
// Return a software vsync source (which uses a timer internally).
// Can be used as a fallback for platforms without hardware vsync,
// and when the layout.frame_rate pref is set to a non-negative value.
already_AddRefed<mozilla::gfx::VsyncSource> CreateSoftwareVsyncSource();
already_AddRefed<mozilla::gfx::VsyncSource> GetSoftwareVsyncSource();
// Create the platform-specific global vsync source. Can fall back to
// CreateSoftwareVsyncSource().
// GetSoftwareVsyncSource().
virtual already_AddRefed<mozilla::gfx::VsyncSource>
CreateGlobalHardwareVsyncSource() = 0;
@ -928,13 +932,21 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
// max number of entries in word cache
int32_t mWordCacheMaxEntries;
// Hardware vsync source. Only valid on parent process
RefPtr<mozilla::gfx::VsyncSource> mVsyncSource;
// The vsync dispatcher for the hardware vsync source. Only non-null in the
// parent process.
// The global vsync dispatcher. Only non-null in the parent process.
// Its underlying VsyncSource is either mGlobalHardwareVsyncSource
// or mSoftwareVsyncSource.
RefPtr<mozilla::VsyncDispatcher> mVsyncDispatcher;
// Cached software vsync source. Only non-null in the parent process,
// and only after the first time GetHardwareVsyncSource has been called.
RefPtr<mozilla::gfx::VsyncSource> mGlobalHardwareVsyncSource;
// Cached software vsync source. Only non-null in the parent process,
// and only after the first time GetSoftwareVsyncSource has been called.
// Used as a fallback source if hardware vsync is not available,
// or when the layout.frame_rate pref is set.
RefPtr<mozilla::gfx::SoftwareVsyncSource> mSoftwareVsyncSource;
RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
private:

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

@ -958,7 +958,7 @@ gfxPlatformGtk::CreateGlobalHardwareVsyncSource() {
if (IsHeadless() || IsWaylandDisplay()) {
// On Wayland we can not create a global hardware based vsync source, thus
// use a software based one here. We create window specific ones later.
return CreateSoftwareVsyncSource();
return GetSoftwareVsyncSource();
}
nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
@ -983,7 +983,7 @@ gfxPlatformGtk::CreateGlobalHardwareVsyncSource() {
RefPtr<GtkVsyncSource> vsyncSource = new GtkVsyncSource();
if (!vsyncSource->Setup()) {
NS_WARNING("Failed to setup GLContext, falling back to software vsync.");
return CreateSoftwareVsyncSource();
return GetSoftwareVsyncSource();
}
return vsyncSource.forget();
}

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

@ -1079,7 +1079,7 @@ gfxPlatformMac::CreateGlobalHardwareVsyncSource() {
if (!osxVsyncSource->IsVsyncEnabled()) {
NS_WARNING(
"OS X Vsync source not enabled. Falling back to software vsync.");
return CreateSoftwareVsyncSource();
return GetSoftwareVsyncSource();
}
osxVsyncSource->DisableVsync();

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

@ -1794,7 +1794,7 @@ gfxWindowsPlatform::CreateGlobalHardwareVsyncSource() {
if (!DwmCompositionEnabled()) {
NS_WARNING("DWM not enabled, falling back to software vsync");
return CreateSoftwareVsyncSource();
return GetSoftwareVsyncSource();
}
RefPtr<VsyncSource> d3dVsyncSource = new D3DVsyncSource();