azul_webrender_api/
display_item_cache.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use crate::display_item::*;
6use crate::display_list::*;
7use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
8
9#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
10pub struct CachedDisplayItem {
11    item: DisplayItem,
12    data: Vec<u8>,
13}
14
15impl CachedDisplayItem {
16    pub fn display_item(&self) -> &DisplayItem {
17        &self.item
18    }
19
20    pub fn data_as_item_range<T>(&self) -> ItemRange<T> {
21        ItemRange::new(&self.data)
22    }
23}
24
25impl MallocSizeOf for CachedDisplayItem {
26    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
27        self.data.size_of(ops)
28    }
29}
30
31impl From<DisplayItemRef<'_, '_>> for CachedDisplayItem {
32    fn from(item_ref: DisplayItemRef) -> Self {
33        let item = item_ref.item();
34
35        match item {
36            DisplayItem::Text(..) => CachedDisplayItem {
37                item: *item,
38                data: item_ref.glyphs().bytes().to_vec(),
39            },
40            _ => CachedDisplayItem {
41                item: *item,
42                data: Vec::new(),
43            },
44        }
45    }
46}
47
48#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
49struct CacheEntry {
50    items: Vec<CachedDisplayItem>,
51    occupied: bool,
52}
53
54#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
55pub struct DisplayItemCache {
56    entries: Vec<CacheEntry>,
57}
58
59impl DisplayItemCache {
60    fn add_item(&mut self, key: ItemKey, item: CachedDisplayItem) {
61        let mut entry = &mut self.entries[key as usize];
62        entry.items.push(item);
63        entry.occupied = true;
64    }
65
66    fn clear_entry(&mut self, key: ItemKey) {
67        let mut entry = &mut self.entries[key as usize];
68        entry.items.clear();
69        entry.occupied = false;
70    }
71
72    fn grow_if_needed(&mut self, capacity: usize) {
73        if capacity > self.entries.len() {
74            self.entries.resize_with(capacity, || CacheEntry {
75                items: Vec::new(),
76                occupied: false,
77            });
78        }
79    }
80
81    pub fn get_items(&self, key: ItemKey) -> &[CachedDisplayItem] {
82        let entry = &self.entries[key as usize];
83        debug_assert!(entry.occupied);
84        entry.items.as_slice()
85    }
86
87    pub fn new() -> Self {
88        Self {
89            entries: Vec::new(),
90        }
91    }
92
93    pub fn update(&mut self, display_list: &BuiltDisplayList) {
94        self.grow_if_needed(display_list.cache_size());
95
96        let mut iter = display_list.extra_data_iter();
97        let mut current_key: Option<ItemKey> = None;
98        loop {
99            let item = match iter.next() {
100                Some(item) => item,
101                None => break,
102            };
103
104            if let DisplayItem::RetainedItems(key) = item.item() {
105                current_key = Some(*key);
106                self.clear_entry(*key);
107                continue;
108            }
109
110            let key = current_key.expect("Missing RetainedItems marker");
111            let cached_item = CachedDisplayItem::from(item);
112            self.add_item(key, cached_item);
113        }
114    }
115}