Skip to main content

fret_ui/tree/
paint_cache.rs

1use super::*;
2
3#[derive(Debug, Clone, Copy, PartialEq)]
4pub(super) struct PaintCacheKey {
5    width_bits: u32,
6    height_bits: u32,
7    scale_factor_bits: u32,
8    theme_revision: u64,
9    fg_present: bool,
10    fg_r_bits: u32,
11    fg_g_bits: u32,
12    fg_b_bits: u32,
13    fg_a_bits: u32,
14    text_style_present: bool,
15    text_style_fingerprint: u64,
16    child_a_bits: u32,
17    child_b_bits: u32,
18    child_c_bits: u32,
19    child_d_bits: u32,
20    child_tx_bits: u32,
21    child_ty_bits: u32,
22}
23
24impl PaintCacheKey {
25    pub(super) fn new(
26        bounds: Rect,
27        scale_factor: f32,
28        theme_revision: u64,
29        paint_style: crate::tree::paint_style::PaintStyleState,
30        inherited_text_style_fingerprint: Option<u64>,
31        child_transform: Transform2D,
32    ) -> Self {
33        let (fg_present, fg_r_bits, fg_g_bits, fg_b_bits, fg_a_bits) =
34            if let Some(fg) = paint_style.foreground {
35                (
36                    true,
37                    fg.r.to_bits(),
38                    fg.g.to_bits(),
39                    fg.b.to_bits(),
40                    fg.a.to_bits(),
41                )
42            } else {
43                (false, 0, 0, 0, 0)
44            };
45
46        Self {
47            width_bits: bounds.size.width.0.to_bits(),
48            height_bits: bounds.size.height.0.to_bits(),
49            scale_factor_bits: scale_factor.to_bits(),
50            theme_revision,
51            fg_present,
52            fg_r_bits,
53            fg_g_bits,
54            fg_b_bits,
55            fg_a_bits,
56            text_style_present: inherited_text_style_fingerprint.is_some(),
57            text_style_fingerprint: inherited_text_style_fingerprint.unwrap_or(0),
58            child_a_bits: child_transform.a.to_bits(),
59            child_b_bits: child_transform.b.to_bits(),
60            child_c_bits: child_transform.c.to_bits(),
61            child_d_bits: child_transform.d.to_bits(),
62            child_tx_bits: child_transform.tx.to_bits(),
63            child_ty_bits: child_transform.ty.to_bits(),
64        }
65    }
66}
67
68#[derive(Debug, Clone, Copy)]
69pub(super) struct PaintCacheEntry {
70    pub(super) generation: u64,
71    pub(super) key: PaintCacheKey,
72    pub(super) origin: Point,
73    pub(super) start: u32,
74    pub(super) end: u32,
75}
76
77#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
78pub enum PaintCachePolicy {
79    /// Enable caching unless the UI is in an inspection/probe mode (e.g. picking, semantics).
80    #[default]
81    Auto,
82    /// Always enable caching.
83    Enabled,
84    /// Always disable caching.
85    Disabled,
86}
87
88#[derive(Debug, Default)]
89pub(super) struct PaintCacheState {
90    pub(super) generation: u64,
91    pub(super) prev_ops: Vec<SceneOp>,
92    pub(super) prev_fingerprint: u64,
93    pub(super) source_generation: u64,
94    pub(super) target_generation: u64,
95    pub(super) hits: u32,
96    pub(super) misses: u32,
97    pub(super) replayed_ops: u32,
98}
99
100impl PaintCacheState {
101    pub(super) fn begin_frame(&mut self) {
102        self.source_generation = self.generation;
103        self.target_generation = self.generation.saturating_add(1);
104        self.hits = 0;
105        self.misses = 0;
106        self.replayed_ops = 0;
107    }
108
109    pub(super) fn finish_frame(&mut self) {
110        self.generation = self.target_generation;
111    }
112
113    pub(super) fn invalidate_recording(&mut self) {
114        self.prev_ops.clear();
115        self.prev_fingerprint = 0;
116        self.generation = self.generation.saturating_add(1);
117    }
118}