Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
sdf_atlas_cache.hpp
Go to the documentation of this file.
1#pragma once
2
3// Runtime SDF atlas cache with LRU eviction.
4//
5// `SdfAtlas` builds a fixed atlas up-front; many UIs want a growing
6// atlas that inserts glyphs lazily and drops least-recently-used
7// glyphs when the texture budget is hit. `SdfAtlasCache` sits on top
8// of `SdfAtlas` and tracks access recency per glyph so the GPU upload
9// path can invalidate only the pages that changed.
10
12
13#include <cstdint>
14#include <list>
15#include <unordered_map>
16
17namespace pulp::canvas {
18
19// Records a glyph's position in the cache and when it was last used.
20// `frame_last_used` tracks frame count so the cache can evict glyphs
21// that have not been drawn for N frames regardless of capacity.
24 std::uint64_t frame_last_used = 0;
25 bool dirty = true; // needs upload to GPU
26};
27
29public:
30 SdfAtlasCache() = default;
31
32 // Initialize the cache with a preallocated atlas for `initial_chars`
33 // at `base_size`. Returns false if the initial build fails.
34 bool initialize(const std::string& font_family,
35 const std::vector<char32_t>& initial_chars,
36 int base_size = 48,
37 int padding = 8,
38 int max_atlas_size = 2048);
39
40 // Touch a codepoint: update its frame_last_used, allocate space in
41 // the atlas if the glyph is missing and there is room. Returns a
42 // pointer to the cache record or nullptr when the atlas is full.
43 const CachedGlyph* touch(char32_t codepoint);
44
45 // Evict glyphs not used in the last `max_age_frames` frames. Returns
46 // the number of glyphs removed.
47 std::size_t evict_older_than(std::uint64_t max_age_frames);
48
49 // Dynamic atlas growth: ensure `codepoint` has a slot in the atlas,
50 // rebuilding with the union of currently cached codepoints + the
51 // new one if necessary. Returns true when the codepoint is resident
52 // on return (whether it was already present or newly added). Every
53 // newly inserted glyph lands with `dirty = true` so the GPU upload
54 // path knows to re-transfer the affected region.
55 bool ensure(char32_t codepoint);
56
57 // Advance the frame counter; call once per presented frame.
58 void next_frame() { ++current_frame_; }
59
60 std::uint64_t current_frame() const { return current_frame_; }
61 std::size_t size() const { return entries_.size(); }
62
63 const SdfAtlas& atlas() const { return atlas_; }
64 SdfAtlas& atlas() { return atlas_; }
65
66private:
67 SdfAtlas atlas_;
68 std::unordered_map<char32_t, CachedGlyph> entries_;
69 std::uint64_t current_frame_ = 0;
70 std::string font_family_;
71 int base_size_ = 48;
72 int padding_ = 8;
73 int max_size_ = 2048;
74};
75
76} // namespace pulp::canvas
std::size_t evict_older_than(std::uint64_t max_age_frames)
std::uint64_t current_frame() const
Definition sdf_atlas_cache.hpp:60
const SdfAtlas & atlas() const
Definition sdf_atlas_cache.hpp:63
SdfAtlas & atlas()
Definition sdf_atlas_cache.hpp:64
void next_frame()
Definition sdf_atlas_cache.hpp:58
bool ensure(char32_t codepoint)
const CachedGlyph * touch(char32_t codepoint)
bool initialize(const std::string &font_family, const std::vector< char32_t > &initial_chars, int base_size=48, int padding=8, int max_atlas_size=2048)
std::size_t size() const
Definition sdf_atlas_cache.hpp:61
Definition sdf_atlas.hpp:39
Definition affine_transform.hpp:24
Definition sdf_atlas_cache.hpp:22
bool dirty
Definition sdf_atlas_cache.hpp:25
std::uint64_t frame_last_used
Definition sdf_atlas_cache.hpp:24
SdfGlyph glyph
Definition sdf_atlas_cache.hpp:23
Definition sdf_atlas.hpp:25