From 94e6ecd618d7388621987c7822d1a78428976b0a Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 13 Jan 2025 11:36:26 +0000 Subject: [PATCH] Bug 1935149 - Streamline IPC messaging related to font-list updates. r=layout-reviewers,emilio Differential Revision: https://phabricator.services.mozilla.com/D232151 --- dom/ipc/ContentChild.cpp | 11 +-- dom/ipc/ContentChild.h | 4 +- dom/ipc/ContentParent.cpp | 6 -- dom/ipc/ContentParent.h | 1 - dom/ipc/PContent.ipdl | 10 +-- gfx/thebes/CoreTextFontList.cpp | 4 +- gfx/thebes/gfxDWriteFonts.cpp | 2 +- gfx/thebes/gfxFcPlatformFontList.cpp | 7 +- gfx/thebes/gfxPlatform.cpp | 9 ++- gfx/thebes/gfxPlatform.h | 29 ++++++-- gfx/thebes/gfxPlatformFontList.cpp | 86 +++++++++++++++-------- gfx/thebes/gfxPlatformFontList.h | 10 ++- ipc/glue/IPCMessageUtilsSpecializations.h | 7 ++ 13 files changed, 111 insertions(+), 75 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index a61151163043..460e919e885e 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2388,16 +2388,9 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData( return IPC_OK(); } -mozilla::ipc::IPCResult ContentChild::RecvFontListChanged() { - gfxPlatformFontList::PlatformFontList()->FontListChanged(); - - return IPC_OK(); -} - mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow( - bool aNeedsReframe) { - gfxPlatform::ForceGlobalReflow(aNeedsReframe ? gfxPlatform::NeedsReframe::Yes - : gfxPlatform::NeedsReframe::No); + const gfxPlatform::GlobalReflowFlags& aFlags) { + gfxPlatform::ForceGlobalReflow(aFlags); return IPC_OK(); } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 98b99a6658bb..a960943e2793 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -312,8 +312,8 @@ class ContentChild final : public PContentChild, SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize, nsTArray&& aBlobs, nsTArray&& aChangedKeys); - mozilla::ipc::IPCResult RecvFontListChanged(); - mozilla::ipc::IPCResult RecvForceGlobalReflow(bool aNeedsReframe); + mozilla::ipc::IPCResult RecvForceGlobalReflow( + const gfxPlatform::GlobalReflowFlags& aFlags); mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 5131522ac08e..59cb5b5b51ad 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1537,12 +1537,6 @@ void ContentParent::BroadcastStringBundle( } } -void ContentParent::BroadcastFontListChanged() { - for (auto* cp : AllProcesses(eLive)) { - Unused << cp->SendFontListChanged(); - } -} - void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex) { auto* pfl = gfxPlatformFontList::PlatformFontList(); diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 4b7e18c1448c..2814fdc7d2db 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -280,7 +280,6 @@ class ContentParent final : public PContentParent, static void BroadcastStringBundle(const StringBundleDescriptor&); - static void BroadcastFontListChanged(); static void BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex); static void BroadcastThemeUpdate(widget::ThemeChangeKind); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index ef95d92367cc..c836313c0c6a 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -100,6 +100,7 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/NativeThreadId.h"; using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h"; using mozilla::gfx::IntSize from "mozilla/gfx/2D.h"; using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h"; +using gfxPlatform::GlobalReflowFlags from "gfxPlatform.h"; using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h"; using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h"; using mozilla::EventMessage from "mozilla/EventForwards.h"; @@ -697,18 +698,11 @@ child: */ [Priority=mediumhigh] async RebuildFontList(bool aFullRebuild); - /** - * The shared font list has been modified, potentially adding matches - * for src:local() names that were previously not known, so content - * may need to be reflowed. - */ - async FontListChanged(); - /** * The font list or prefs have been updated in such a way that we might need * to do a reflow and maybe reframe. */ - async ForceGlobalReflow(bool aNeedsReframe); + async ForceGlobalReflow(GlobalReflowFlags aFlags); /** * A new shmem block has been added to the font list; the child process diff --git a/gfx/thebes/CoreTextFontList.cpp b/gfx/thebes/CoreTextFontList.cpp index 251951e5968d..40e522612a26 100644 --- a/gfx/thebes/CoreTextFontList.cpp +++ b/gfx/thebes/CoreTextFontList.cpp @@ -1311,7 +1311,9 @@ void CoreTextFontList::RegisteredFontsChangedNotificationCallback( // scratch fl->UpdateFontList(); - gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes); + auto flags = gfxPlatform::GlobalReflowFlags::NeedsReframe | + gfxPlatform::GlobalReflowFlags::FontsChanged; + gfxPlatform::ForceGlobalReflow(flags); dom::ContentParent::NotifyUpdatedFonts(true); } diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index 058c887f0a14..52404197ad79 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -162,7 +162,7 @@ void gfxDWriteFont::SystemTextQualityChanged() { // flush cached stuff that depended on the old setting, and force // reflow everywhere to ensure we are using correct glyph metrics. gfxPlatform::FlushFontAndWordCaches(); - gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No); + gfxPlatform::ForceGlobalReflow(gfxPlatform::GlobalReflowFlags::None); } mozilla::Atomic gfxDWriteFont::sForceGDIClassicEnabled{true}; diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index 7a976e2e9479..6d7f3bb46cd3 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -2710,8 +2710,11 @@ void gfxFcPlatformFontList::CheckFontUpdates(nsITimer* aTimer, void* aThis) { FcConfig* current = FcConfigGetCurrent(); if (current != pfl->GetLastConfig()) { pfl->UpdateFontList(); - - gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes); + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::NeedsReframe | + gfxPlatform::GlobalReflowFlags::FontsChanged | + gfxPlatform::GlobalReflowFlags::BroadcastToChildren; + gfxPlatform::ForceGlobalReflow(flags); mozilla::dom::ContentParent::NotifyUpdatedFonts(true); } } diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 91e783e0ed8b..fa70aedcef2e 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -2244,10 +2244,9 @@ void gfxPlatform::FlushFontAndWordCaches() { } /* static */ -void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe, - BroadcastToChildren aBroadcastToChildren) { +void gfxPlatform::ForceGlobalReflow(GlobalReflowFlags aFlags) { MOZ_ASSERT(NS_IsMainThread()); - const bool reframe = aNeedsReframe == NeedsReframe::Yes; + bool reframe = !!(aFlags & GlobalReflowFlags::NeedsReframe); // Send a notification that will be observed by PresShells in this process // only. if (nsCOMPtr obs = services::GetObserverService()) { @@ -2255,11 +2254,11 @@ void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe, obs->NotifyObservers(nullptr, "font-info-updated", needsReframe); } if (XRE_IsParentProcess() && - aBroadcastToChildren == BroadcastToChildren::Yes) { + aFlags & GlobalReflowFlags::BroadcastToChildren) { // Propagate the change to child processes. for (auto* process : dom::ContentParent::AllProcesses(dom::ContentParent::eLive)) { - Unused << process->SendForceGlobalReflow(reframe); + Unused << process->SendForceGlobalReflow(aFlags); } } } diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 3d4f4ec83835..c1a15136d08e 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -599,13 +599,28 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { * an effect on layout, such as font rendering settings that influence * metrics, or installed fonts. * - * By default it also broadcast it to child processes, but some callers might - * not need it if they implement their own notification. + * Normally this is initiated in the parent process, and also broadcast to + * child processes, but some callers might not need this if they implement + * their own notification. */ - enum class NeedsReframe : bool { No, Yes }; - enum class BroadcastToChildren : bool { No, Yes }; - static void ForceGlobalReflow(NeedsReframe, - BroadcastToChildren = BroadcastToChildren::Yes); + enum class GlobalReflowFlags : uint8_t { + None = 0, + // Font data has been updated such that new fonts and/or character coverage + // may be available; existing font-lookup caches should be invalidated and + // font selection re-done. + FontsChanged = (1 << 0), + // Content should be fully reframed; this is used when font entry records + // may have been invalidated such that existing textruns in the frame tree + // are no longer safe to work with. Rather than reflow the existing frame + // tree we will discard and re-create it. + NeedsReframe = (1 << 1), + // (If this is the parent process), broadcast this reflow request to all + // child processes. + BroadcastToChildren = (1 << 2), + // For serialization. + ALL_BITS = FontsChanged | NeedsReframe | BroadcastToChildren, + }; + static void ForceGlobalReflow(GlobalReflowFlags aFlags); static void FlushFontAndWordCaches(); @@ -1007,6 +1022,8 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener { const gfxSkipChars kEmptySkipChars; }; +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatform::GlobalReflowFlags) + CMSMode GfxColorManagementMode(); #endif /* GFX_PLATFORM_H */ diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index ac06e337b81b..fa2c1a131e0d 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -204,7 +204,10 @@ gfxFontListPrefObserver::Observe(nsISupports* aSubject, const char* aTopic, FontListPrefChanged(nullptr); if (XRE_IsParentProcess()) { - gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No); + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::BroadcastToChildren | + gfxPlatform::GlobalReflowFlags::FontsChanged; + gfxPlatform::ForceGlobalReflow(flags); } return NS_OK; } @@ -584,8 +587,10 @@ bool gfxPlatformFontList::InitFontList() { // There's no need to broadcast this reflow request to child processes, as // ContentParent::NotifyUpdatedFonts deals with it by re-entering into this // function on child processes. - ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::Yes, - gfxPlatform::BroadcastToChildren::No); + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::NeedsReframe | + gfxPlatform::GlobalReflowFlags::FontsChanged; + ForceGlobalReflowLocked(flags); mAliasTable.Clear(); mLocalNameTable.Clear(); @@ -719,19 +724,6 @@ void gfxPlatformFontList::InitializeCodepointsWithNoFonts() { } } -void gfxPlatformFontList::FontListChanged() { - MOZ_ASSERT(!XRE_IsParentProcess()); - AutoLock lock(mLock); - InitializeCodepointsWithNoFonts(); - if (SharedFontList()) { - // If we're using a shared local face-name list, this may have changed - // such that existing font entries held by user font sets are no longer - // safe to use: ensure they all get flushed. - RebuildLocalFonts(/*aForgetLocalFaces*/ true); - } - ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::Yes); -} - void gfxPlatformFontList::GenerateFontListKey(const nsACString& aKeyName, nsACString& aResult) { aResult = aKeyName; @@ -1008,7 +1000,10 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) { if (mStartedLoadingCmapsFrom != 0xffffffffu) { InitializeCodepointsWithNoFonts(); mStartedLoadingCmapsFrom = 0xffffffffu; - ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::No); + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::FontsChanged | + gfxPlatform::GlobalReflowFlags::BroadcastToChildren; + ForceGlobalReflowLocked(flags); } } } @@ -2798,7 +2793,9 @@ void gfxPlatformFontList::CleanupLoader() { FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)); }); if (forceReflow) { - ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::No); + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::FontsChanged; + ForceGlobalReflowLocked(flags); } mOtherNamesMissed = nullptr; @@ -2819,20 +2816,47 @@ void gfxPlatformFontList::CleanupLoader() { gfxFontInfoLoader::CleanupLoader(); } -void gfxPlatformFontList::ForceGlobalReflowLocked( - gfxPlatform::NeedsReframe aNeedsReframe, - gfxPlatform::BroadcastToChildren aBroadcastToChildren) { +void gfxPlatformFontList::ForceGlobalReflow( + gfxPlatform::GlobalReflowFlags aFlags) { if (!NS_IsMainThread()) { NS_DispatchToMainThread(NS_NewRunnableFunction( - "gfxPlatformFontList::ForceGlobalReflowLocked", - [aNeedsReframe, aBroadcastToChildren] { - gfxPlatform::ForceGlobalReflow(aNeedsReframe, aBroadcastToChildren); - })); + "gfxPlatformFontList::ForceGlobalReflow", + [this, aFlags] { this->ForceGlobalReflow(aFlags); })); return; } + if (aFlags & gfxPlatform::GlobalReflowFlags::FontsChanged) { + AutoLock lock(mLock); + InitializeCodepointsWithNoFonts(); + if (SharedFontList()) { + // If we're using a shared local face-name list, this may have changed + // such that existing font entries held by user font sets are no longer + // safe to use: ensure they all get flushed. + RebuildLocalFonts(/*aForgetLocalFaces*/ true); + } + } + + gfxPlatform::ForceGlobalReflow(aFlags); +} + +void gfxPlatformFontList::ForceGlobalReflowLocked( + gfxPlatform::GlobalReflowFlags aFlags) { + if (!NS_IsMainThread()) { + NS_DispatchToMainThread(NS_NewRunnableFunction( + "gfxPlatformFontList::ForceGlobalReflow", + [this, aFlags] { this->ForceGlobalReflow(aFlags); })); + return; + } + + if (aFlags & gfxPlatform::GlobalReflowFlags::FontsChanged) { + InitializeCodepointsWithNoFonts(); + if (SharedFontList()) { + RebuildLocalFonts(/*aForgetLocalFaces*/ true); + } + } + AutoUnlock unlock(mLock); - gfxPlatform::ForceGlobalReflow(aNeedsReframe, aBroadcastToChildren); + gfxPlatform::ForceGlobalReflow(aFlags); } void gfxPlatformFontList::GetPrefsAndStartLoader() { @@ -3075,8 +3099,14 @@ void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() { mLocalNameTable.Clear(); forceReflow = true; } - if (forceReflow) { - dom::ContentParent::BroadcastFontListChanged(); + // If there's a LoadCmapsRunnable alive, we ignore forceReflow because the + // runnable will trigger a reflow when it completes, and we don't want to + // reflow more times than necessary. + if (forceReflow && !mLoadCmapsRunnable) { + gfxPlatform::GlobalReflowFlags flags = + gfxPlatform::GlobalReflowFlags::BroadcastToChildren | + gfxPlatform::GlobalReflowFlags::FontsChanged; + gfxPlatform::ForceGlobalReflow(flags); } } } diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 22b553b3fcde..a732707f936a 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -269,8 +269,6 @@ class gfxPlatformFontList : public gfxFontInfoLoader { // Initialize font lists; return true on success, false if something fails. bool InitFontList(); - void FontListChanged(); - /** * Gathers (from a platform's underlying font system) the information needed * to initialize a fontlist::Family with its Face members. @@ -894,10 +892,10 @@ class gfxPlatformFontList : public gfxFontInfoLoader { bool LoadFontInfo() override; void CleanupLoader() override; - void ForceGlobalReflowLocked( - gfxPlatform::NeedsReframe aNeedsReframe, - gfxPlatform::BroadcastToChildren aBroadcastToChildren = - gfxPlatform::BroadcastToChildren::Yes) MOZ_REQUIRES(mLock); + void ForceGlobalReflow(gfxPlatform::GlobalReflowFlags aFlags); + + void ForceGlobalReflowLocked(gfxPlatform::GlobalReflowFlags aFlags) + MOZ_REQUIRES(mLock); // read the loader initialization prefs, and start it void GetPrefsAndStartLoader(); diff --git a/ipc/glue/IPCMessageUtilsSpecializations.h b/ipc/glue/IPCMessageUtilsSpecializations.h index 6bf58afd292a..7873c1f62667 100644 --- a/ipc/glue/IPCMessageUtilsSpecializations.h +++ b/ipc/glue/IPCMessageUtilsSpecializations.h @@ -35,6 +35,7 @@ #include "mozilla/Vector.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/UserActivation.h" +#include "gfxPlatform.h" #include "nsCSSPropertyID.h" #include "nsDebug.h" #include "nsIContentPolicy.h" @@ -840,6 +841,12 @@ struct ParamTraits { }; }; +template <> +struct ParamTraits + : public BitFlagsEnumSerializer { +}; + } /* namespace IPC */ #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */