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();
}
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();
}

View File

@@ -312,8 +312,8 @@ class ContentChild final : public PContentChild,
SharedMemoryHandle&& aMapHandle, const uint32_t& aMapSize,
nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& 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);

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,
uint32_t aIndex) {
auto* pfl = gfxPlatformFontList::PlatformFontList();

View File

@@ -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);

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::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

View File

@@ -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);
}

View File

@@ -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<bool> gfxDWriteFont::sForceGDIClassicEnabled{true};

View File

@@ -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);
}
}

View File

@@ -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<nsIObserverService> 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);
}
}
}

View File

@@ -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 */

View File

@@ -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);
}
}
}

View File

@@ -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();

View File

@@ -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<mozilla::dom::UserActivation::Modifiers> {
};
};
template <>
struct ParamTraits<gfxPlatform::GlobalReflowFlags>
: public BitFlagsEnumSerializer<gfxPlatform::GlobalReflowFlags,
gfxPlatform::GlobalReflowFlags::ALL_BITS> {
};
} /* namespace IPC */
#endif /* __IPC_GLUE_IPCMESSAGEUTILSSPECIALIZATIONS_H__ */