Bug 1935149 - Streamline IPC messaging related to font-list updates. r=layout-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D232151
This commit is contained in:
Jonathan Kew
2025-01-13 11:36:26 +00:00
parent 3f76ec7cf1
commit 94e6ecd618
13 changed files with 111 additions and 75 deletions

View File

@@ -2388,16 +2388,9 @@ mozilla::ipc::IPCResult ContentChild::RecvUpdateSharedData(
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult ContentChild::RecvFontListChanged() {
gfxPlatformFontList::PlatformFontList()->FontListChanged();
return IPC_OK();
}
mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow( mozilla::ipc::IPCResult ContentChild::RecvForceGlobalReflow(
bool aNeedsReframe) { const gfxPlatform::GlobalReflowFlags& aFlags) {
gfxPlatform::ForceGlobalReflow(aNeedsReframe ? gfxPlatform::NeedsReframe::Yes gfxPlatform::ForceGlobalReflow(aFlags);
: gfxPlatform::NeedsReframe::No);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -312,8 +312,8 @@ class ContentChild final : public PContentChild,
SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize, SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys); nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
mozilla::ipc::IPCResult RecvFontListChanged(); mozilla::ipc::IPCResult RecvForceGlobalReflow(
mozilla::ipc::IPCResult RecvForceGlobalReflow(bool aNeedsReframe); const gfxPlatform::GlobalReflowFlags& aFlags);
mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition); mozilla::ipc::IPCResult RecvGeolocationUpdate(nsIDOMGeoPosition* aPosition);

View File

@@ -1537,12 +1537,6 @@ void ContentParent::BroadcastStringBundle(
} }
} }
void ContentParent::BroadcastFontListChanged() {
for (auto* cp : AllProcesses(eLive)) {
Unused << cp->SendFontListChanged();
}
}
void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration, void ContentParent::BroadcastShmBlockAdded(uint32_t aGeneration,
uint32_t aIndex) { uint32_t aIndex) {
auto* pfl = gfxPlatformFontList::PlatformFontList(); auto* pfl = gfxPlatformFontList::PlatformFontList();

View File

@@ -280,7 +280,6 @@ class ContentParent final : public PContentParent,
static void BroadcastStringBundle(const StringBundleDescriptor&); static void BroadcastStringBundle(const StringBundleDescriptor&);
static void BroadcastFontListChanged();
static void BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex); static void BroadcastShmBlockAdded(uint32_t aGeneration, uint32_t aIndex);
static void BroadcastThemeUpdate(widget::ThemeChangeKind); static void BroadcastThemeUpdate(widget::ThemeChangeKind);

View File

@@ -100,6 +100,7 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/NativeThreadId.h";
using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h"; using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h"; using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.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::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h"; using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
using mozilla::EventMessage from "mozilla/EventForwards.h"; using mozilla::EventMessage from "mozilla/EventForwards.h";
@@ -697,18 +698,11 @@ child:
*/ */
[Priority=mediumhigh] async RebuildFontList(bool aFullRebuild); [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 * The font list or prefs have been updated in such a way that we might need
* to do a reflow and maybe reframe. * 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 * A new shmem block has been added to the font list; the child process

View File

@@ -1311,7 +1311,9 @@ void CoreTextFontList::RegisteredFontsChangedNotificationCallback(
// scratch // scratch
fl->UpdateFontList(); fl->UpdateFontList();
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes); auto flags = gfxPlatform::GlobalReflowFlags::NeedsReframe |
gfxPlatform::GlobalReflowFlags::FontsChanged;
gfxPlatform::ForceGlobalReflow(flags);
dom::ContentParent::NotifyUpdatedFonts(true); dom::ContentParent::NotifyUpdatedFonts(true);
} }

View File

@@ -162,7 +162,7 @@ void gfxDWriteFont::SystemTextQualityChanged() {
// flush cached stuff that depended on the old setting, and force // flush cached stuff that depended on the old setting, and force
// reflow everywhere to ensure we are using correct glyph metrics. // reflow everywhere to ensure we are using correct glyph metrics.
gfxPlatform::FlushFontAndWordCaches(); gfxPlatform::FlushFontAndWordCaches();
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No); gfxPlatform::ForceGlobalReflow(gfxPlatform::GlobalReflowFlags::None);
} }
mozilla::Atomic<bool> gfxDWriteFont::sForceGDIClassicEnabled{true}; mozilla::Atomic<bool> gfxDWriteFont::sForceGDIClassicEnabled{true};

View File

@@ -2710,8 +2710,11 @@ void gfxFcPlatformFontList::CheckFontUpdates(nsITimer* aTimer, void* aThis) {
FcConfig* current = FcConfigGetCurrent(); FcConfig* current = FcConfigGetCurrent();
if (current != pfl->GetLastConfig()) { if (current != pfl->GetLastConfig()) {
pfl->UpdateFontList(); pfl->UpdateFontList();
gfxPlatform::GlobalReflowFlags flags =
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes); gfxPlatform::GlobalReflowFlags::NeedsReframe |
gfxPlatform::GlobalReflowFlags::FontsChanged |
gfxPlatform::GlobalReflowFlags::BroadcastToChildren;
gfxPlatform::ForceGlobalReflow(flags);
mozilla::dom::ContentParent::NotifyUpdatedFonts(true); mozilla::dom::ContentParent::NotifyUpdatedFonts(true);
} }
} }

View File

@@ -2244,10 +2244,9 @@ void gfxPlatform::FlushFontAndWordCaches() {
} }
/* static */ /* static */
void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe, void gfxPlatform::ForceGlobalReflow(GlobalReflowFlags aFlags) {
BroadcastToChildren aBroadcastToChildren) {
MOZ_ASSERT(NS_IsMainThread()); 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 // Send a notification that will be observed by PresShells in this process
// only. // only.
if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) { if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
@@ -2255,11 +2254,11 @@ void gfxPlatform::ForceGlobalReflow(NeedsReframe aNeedsReframe,
obs->NotifyObservers(nullptr, "font-info-updated", needsReframe); obs->NotifyObservers(nullptr, "font-info-updated", needsReframe);
} }
if (XRE_IsParentProcess() && if (XRE_IsParentProcess() &&
aBroadcastToChildren == BroadcastToChildren::Yes) { aFlags & GlobalReflowFlags::BroadcastToChildren) {
// Propagate the change to child processes. // Propagate the change to child processes.
for (auto* process : for (auto* process :
dom::ContentParent::AllProcesses(dom::ContentParent::eLive)) { dom::ContentParent::AllProcesses(dom::ContentParent::eLive)) {
Unused << process->SendForceGlobalReflow(reframe); Unused << process->SendForceGlobalReflow(aFlags);
} }
} }
} }

View File

@@ -599,13 +599,28 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
* an effect on layout, such as font rendering settings that influence * an effect on layout, such as font rendering settings that influence
* metrics, or installed fonts. * metrics, or installed fonts.
* *
* By default it also broadcast it to child processes, but some callers might * Normally this is initiated in the parent process, and also broadcast to
* not need it if they implement their own notification. * child processes, but some callers might not need this if they implement
* their own notification.
*/ */
enum class NeedsReframe : bool { No, Yes }; enum class GlobalReflowFlags : uint8_t {
enum class BroadcastToChildren : bool { No, Yes }; None = 0,
static void ForceGlobalReflow(NeedsReframe, // Font data has been updated such that new fonts and/or character coverage
BroadcastToChildren = BroadcastToChildren::Yes); // 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(); static void FlushFontAndWordCaches();
@@ -1007,6 +1022,8 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
const gfxSkipChars kEmptySkipChars; const gfxSkipChars kEmptySkipChars;
}; };
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxPlatform::GlobalReflowFlags)
CMSMode GfxColorManagementMode(); CMSMode GfxColorManagementMode();
#endif /* GFX_PLATFORM_H */ #endif /* GFX_PLATFORM_H */

View File

@@ -204,7 +204,10 @@ gfxFontListPrefObserver::Observe(nsISupports* aSubject, const char* aTopic,
FontListPrefChanged(nullptr); FontListPrefChanged(nullptr);
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No); gfxPlatform::GlobalReflowFlags flags =
gfxPlatform::GlobalReflowFlags::BroadcastToChildren |
gfxPlatform::GlobalReflowFlags::FontsChanged;
gfxPlatform::ForceGlobalReflow(flags);
} }
return NS_OK; return NS_OK;
} }
@@ -584,8 +587,10 @@ bool gfxPlatformFontList::InitFontList() {
// There's no need to broadcast this reflow request to child processes, as // There's no need to broadcast this reflow request to child processes, as
// ContentParent::NotifyUpdatedFonts deals with it by re-entering into this // ContentParent::NotifyUpdatedFonts deals with it by re-entering into this
// function on child processes. // function on child processes.
ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::Yes, gfxPlatform::GlobalReflowFlags flags =
gfxPlatform::BroadcastToChildren::No); gfxPlatform::GlobalReflowFlags::NeedsReframe |
gfxPlatform::GlobalReflowFlags::FontsChanged;
ForceGlobalReflowLocked(flags);
mAliasTable.Clear(); mAliasTable.Clear();
mLocalNameTable.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, void gfxPlatformFontList::GenerateFontListKey(const nsACString& aKeyName,
nsACString& aResult) { nsACString& aResult) {
aResult = aKeyName; aResult = aKeyName;
@@ -1008,7 +1000,10 @@ void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
if (mStartedLoadingCmapsFrom != 0xffffffffu) { if (mStartedLoadingCmapsFrom != 0xffffffffu) {
InitializeCodepointsWithNoFonts(); InitializeCodepointsWithNoFonts();
mStartedLoadingCmapsFrom = 0xffffffffu; 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)); FindFamiliesFlags::eNoAddToNamesMissedWhenSearching));
}); });
if (forceReflow) { if (forceReflow) {
ForceGlobalReflowLocked(gfxPlatform::NeedsReframe::No); gfxPlatform::GlobalReflowFlags flags =
gfxPlatform::GlobalReflowFlags::FontsChanged;
ForceGlobalReflowLocked(flags);
} }
mOtherNamesMissed = nullptr; mOtherNamesMissed = nullptr;
@@ -2819,20 +2816,47 @@ void gfxPlatformFontList::CleanupLoader() {
gfxFontInfoLoader::CleanupLoader(); gfxFontInfoLoader::CleanupLoader();
} }
void gfxPlatformFontList::ForceGlobalReflowLocked( void gfxPlatformFontList::ForceGlobalReflow(
gfxPlatform::NeedsReframe aNeedsReframe, gfxPlatform::GlobalReflowFlags aFlags) {
gfxPlatform::BroadcastToChildren aBroadcastToChildren) {
if (!NS_IsMainThread()) { if (!NS_IsMainThread()) {
NS_DispatchToMainThread(NS_NewRunnableFunction( NS_DispatchToMainThread(NS_NewRunnableFunction(
"gfxPlatformFontList::ForceGlobalReflowLocked", "gfxPlatformFontList::ForceGlobalReflow",
[aNeedsReframe, aBroadcastToChildren] { [this, aFlags] { this->ForceGlobalReflow(aFlags); }));
gfxPlatform::ForceGlobalReflow(aNeedsReframe, aBroadcastToChildren);
}));
return; 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); AutoUnlock unlock(mLock);
gfxPlatform::ForceGlobalReflow(aNeedsReframe, aBroadcastToChildren); gfxPlatform::ForceGlobalReflow(aFlags);
} }
void gfxPlatformFontList::GetPrefsAndStartLoader() { void gfxPlatformFontList::GetPrefsAndStartLoader() {
@@ -3075,8 +3099,14 @@ void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() {
mLocalNameTable.Clear(); mLocalNameTable.Clear();
forceReflow = true; forceReflow = true;
} }
if (forceReflow) { // If there's a LoadCmapsRunnable alive, we ignore forceReflow because the
dom::ContentParent::BroadcastFontListChanged(); // 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);
} }
} }
} }

View File

@@ -269,8 +269,6 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
// Initialize font lists; return true on success, false if something fails. // Initialize font lists; return true on success, false if something fails.
bool InitFontList(); bool InitFontList();
void FontListChanged();
/** /**
* Gathers (from a platform's underlying font system) the information needed * Gathers (from a platform's underlying font system) the information needed
* to initialize a fontlist::Family with its Face members. * to initialize a fontlist::Family with its Face members.
@@ -894,10 +892,10 @@ class gfxPlatformFontList : public gfxFontInfoLoader {
bool LoadFontInfo() override; bool LoadFontInfo() override;
void CleanupLoader() override; void CleanupLoader() override;
void ForceGlobalReflowLocked( void ForceGlobalReflow(gfxPlatform::GlobalReflowFlags aFlags);
gfxPlatform::NeedsReframe aNeedsReframe,
gfxPlatform::BroadcastToChildren aBroadcastToChildren = void ForceGlobalReflowLocked(gfxPlatform::GlobalReflowFlags aFlags)
gfxPlatform::BroadcastToChildren::Yes) MOZ_REQUIRES(mLock); MOZ_REQUIRES(mLock);
// read the loader initialization prefs, and start it // read the loader initialization prefs, and start it
void GetPrefsAndStartLoader(); void GetPrefsAndStartLoader();

View File

@@ -35,6 +35,7 @@
#include "mozilla/Vector.h" #include "mozilla/Vector.h"
#include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/ipc/StructuredCloneData.h"
#include "mozilla/dom/UserActivation.h" #include "mozilla/dom/UserActivation.h"
#include "gfxPlatform.h"
#include "nsCSSPropertyID.h" #include "nsCSSPropertyID.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsIContentPolicy.h" #include "nsIContentPolicy.h"
@@ -840,6 +841,12 @@ struct ParamTraits<mozilla::dom::UserActivation::Modifiers> {
}; };
}; };
template <>
struct ParamTraits<gfxPlatform::GlobalReflowFlags>
: public BitFlagsEnumSerializer<gfxPlatform::GlobalReflowFlags,
gfxPlatform::GlobalReflowFlags::ALL_BITS> {
};
} /* namespace IPC */ } /* namespace IPC */
#endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */ #endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */