From 95eafaecd15811e1738ab9c7d821cf85e6fb9506 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Mon, 4 May 2026 15:41:10 +0200 Subject: [PATCH] Smarter cache eviction --- lib/EpdFont/FontDecompressor.cpp | 38 ++++++++++++++++++++++------ lib/EpdFont/FontDecompressor.h | 2 +- lib/GfxRenderer/FontCacheManager.cpp | 7 +++-- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/lib/EpdFont/FontDecompressor.cpp b/lib/EpdFont/FontDecompressor.cpp index e95883ab..1b347673 100644 --- a/lib/EpdFont/FontDecompressor.cpp +++ b/lib/EpdFont/FontDecompressor.cpp @@ -219,13 +219,6 @@ int32_t FontDecompressor::findGlyphIndex(const EpdFontData* fontData, uint32_t c int FontDecompressor::prewarmCache(const EpdFontData* fontData, const char* utf8Text) { if (!fontData || !fontData->groups || !utf8Text) return 0; - // Allocate the next available slot (caller must call freePageBuffer/clearCache to reset) - if (pageSlotCount >= MAX_PAGE_SLOTS) { - LOG_ERR("FDC", "All %u page buffer slots full, cannot prewarm fontData=%p", MAX_PAGE_SLOTS, (void*)fontData); - return -1; - } - PageSlot& slot = pageSlots[pageSlotCount]; - // Step 1: Collect unique glyph indices needed for this page uint32_t neededGlyphs[MAX_PAGE_GLYPHS]; uint16_t glyphCount = 0; @@ -239,7 +232,29 @@ int FontDecompressor::prewarmCache(const EpdFontData* fontData, const char* utf8 int32_t glyphIdx = findGlyphIndex(fontData, cp); if (glyphIdx < 0) continue; - // Deduplicate + // Deduplicate against already prewarmed slots + bool alreadyCached = false; + for (uint8_t s = 0; s < pageSlotCount; s++) { + if (pageSlots[s].fontData != fontData || pageSlots[s].glyphCount == 0) continue; + int left = 0, right = pageSlots[s].glyphCount - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (pageSlots[s].glyphs[mid].glyphIndex == static_cast(glyphIdx)) { + if (pageSlots[s].glyphs[mid].bufferOffset != UINT32_MAX) { + alreadyCached = true; + } + break; + } + if (pageSlots[s].glyphs[mid].glyphIndex < static_cast(glyphIdx)) + left = mid + 1; + else + right = mid - 1; + } + if (alreadyCached) break; + } + if (alreadyCached) continue; + + // Deduplicate within the current page pass bool found = false; for (uint16_t i = 0; i < glyphCount; i++) { if (neededGlyphs[i] == static_cast(glyphIdx)) { @@ -297,6 +312,13 @@ int FontDecompressor::prewarmCache(const EpdFontData* fontData, const char* utf8 if (glyphCount == 0) return 0; + // Allocate the next available slot + if (pageSlotCount >= MAX_PAGE_SLOTS) { + LOG_ERR("FDC", "All %u page buffer slots full, cannot prewarm fontData=%p", MAX_PAGE_SLOTS, (void*)fontData); + return -1; + } + PageSlot& slot = pageSlots[pageSlotCount]; + // Step 2: Compute total buffer size and collect unique groups uint32_t totalBytes = 0; uint16_t neededGroups[128]; diff --git a/lib/EpdFont/FontDecompressor.h b/lib/EpdFont/FontDecompressor.h index afb9c61c..8f574dba 100644 --- a/lib/EpdFont/FontDecompressor.h +++ b/lib/EpdFont/FontDecompressor.h @@ -7,7 +7,7 @@ class FontDecompressor { public: static constexpr uint16_t MAX_PAGE_GLYPHS = 512; - static constexpr uint8_t MAX_PAGE_SLOTS = 8; // Provide enough slots for heavily stylized HTML pages + static constexpr uint8_t MAX_PAGE_SLOTS = 4; // One per font style (R/B/I/BI) FontDecompressor() = default; ~FontDecompressor(); diff --git a/lib/GfxRenderer/FontCacheManager.cpp b/lib/GfxRenderer/FontCacheManager.cpp index 36620f2e..ff13fb8d 100644 --- a/lib/GfxRenderer/FontCacheManager.cpp +++ b/lib/GfxRenderer/FontCacheManager.cpp @@ -24,8 +24,6 @@ void FontCacheManager::clearCache() { } void FontCacheManager::prewarmCache(int fontId, const char* utf8Text, uint8_t styleMask) { - clearCache(); - // SD card font prewarm path: prewarm all requested styles in one call auto sdIt = sdCardFonts_.find(fontId); if (sdIt != sdCardFonts_.end()) { @@ -52,6 +50,11 @@ void FontCacheManager::prewarmCache(int fontId, const char* utf8Text, uint8_t st const EpdFontData* data = fontMap_.at(fontId).getData(style); if (!data || !data->groups) continue; int missed = fontDecompressor_->prewarmCache(data, utf8Text); + if (missed < 0) { + LOG_DBG("FCM", "prewarmCache: Cache slots full! Clearing and retrying slot allocation."); + clearCache(); + missed = fontDecompressor_->prewarmCache(data, utf8Text); + } if (missed > 0) { LOG_DBG("FCM", "prewarmCache: %d glyph(s) not cached for style %d", missed, i); }