gecko-dev/gfx/thebes/gfxFT2Fonts.h
Andrew Osmond 2ae0134b4c Bug 1780193 - Refactor gfxFontCache expiration behaviour to mitigate perf reductions. r=jfkthame
In this patch, we make gfxFont use normal AddRef/Release semantics, and
instead now hold a strong reference to it inside the cache. At all times
a font should be in the expiration tracker, and whenever a lookup is
performed, we mark it as used.

When the tracker attempts to expire an entry, we check to see if the
only strong reference is inside the cache itself. If so, it is deleted.
If not, we mark it as used again instead of expiring it.

This has the advantage of making gfxFont::Release cheaper when there is
only one outstanding reference left outside the cache. It used to
acquire the gfxFontCache mutex in order to reinsert the font into the
expiration tracker when the last strong reference was cleared. This is a
very common case since the typical use case is only the main thread is
interacting with the cache, one font reference at a time.

This does not completely restore us to the previous performance
observed, but it does reclaim half of the original design benefit while
remaining threadsafe.

Differential Revision: https://phabricator.services.mozilla.com/D153110
2022-07-29 14:48:38 +00:00

82 lines
2.6 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_FT2FONTS_H
#define GFX_FT2FONTS_H
#include "mozilla/MemoryReporting.h"
#include "gfxTypes.h"
#include "gfxFont.h"
#include "gfxFT2FontBase.h"
#include "gfxContext.h"
#include "gfxFontUtils.h"
#include "gfxUserFontSet.h"
class FT2FontEntry;
class gfxFT2Font final : public gfxFT2FontBase {
public: // new functions
gfxFT2Font(const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle,
int aLoadFlags);
FT2FontEntry* GetFontEntry();
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
const TextRunDrawParams& aRunParams) override;
bool ShouldHintMetrics() const override;
void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const override;
void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
FontCacheSizes* aSizes) const override;
protected:
~gfxFT2Font() override;
struct CachedGlyphData {
CachedGlyphData() : glyphIndex(0xffffffffU) {}
explicit CachedGlyphData(uint32_t gid) : glyphIndex(gid) {}
uint32_t glyphIndex;
int32_t lsbDelta;
int32_t rsbDelta;
int32_t xAdvance;
};
const CachedGlyphData* GetGlyphDataForChar(FT_Face aFace, uint32_t ch) {
CharGlyphMapEntryType* entry = mCharGlyphCache.PutEntry(ch);
if (!entry) return nullptr;
if (entry->GetData().glyphIndex == 0xffffffffU) {
// this is a new entry, fill it
FillGlyphDataForChar(aFace, ch, entry->GetModifiableData());
}
return &entry->GetData();
}
bool ShapeText(DrawTarget* aDrawTarget, const char16_t* aText,
uint32_t aOffset, uint32_t aLength, Script aScript,
nsAtom* aLanguage, bool aVertical, RoundingFlags aRounding,
gfxShapedText* aShapedText) override;
void FillGlyphDataForChar(FT_Face face, uint32_t ch, CachedGlyphData* gd);
void AddRange(const char16_t* aText, uint32_t aOffset, uint32_t aLength,
gfxShapedText* aShapedText);
typedef nsBaseHashtableET<nsUint32HashKey, CachedGlyphData>
CharGlyphMapEntryType;
typedef nsTHashtable<CharGlyphMapEntryType> CharGlyphMap;
CharGlyphMap mCharGlyphCache;
};
#endif /* GFX_FT2FONTS_H */