fuchsia_framebuffer/
lib.rs1use std::collections::BTreeSet;
6
7pub mod sysmem;
8
9#[cfg(test)]
10use std::ops::Range;
11
12pub type ImageId = u64;
14
15#[derive(Debug)]
17pub struct FrameSet {
18 image_count: usize,
19 available: BTreeSet<ImageId>,
20 taken: BTreeSet<ImageId>,
21}
22
23impl FrameSet {
24 pub fn new(available: BTreeSet<ImageId>) -> FrameSet {
25 FrameSet { image_count: available.len(), available, taken: BTreeSet::new() }
26 }
27
28 #[cfg(test)]
29 pub fn new_with_range(r: Range<ImageId>) -> FrameSet {
30 let mut available = BTreeSet::new();
31 for image_id in r {
32 available.insert(image_id);
33 }
34 Self::new(available)
35 }
36
37 pub fn take_image(&mut self) -> Option<ImageId> {
39 if let Some(first) = self.available.pop_first() {
40 self.taken.insert(first);
41 Some(first)
42 } else {
43 None
44 }
45 }
46
47 pub fn return_image(&mut self, image_id: ImageId) {
51 assert!(
52 self.taken.remove(&image_id),
53 "Attempted to return image {} which was not currently taken",
54 image_id
55 );
56 self.available.insert(image_id);
57 }
58
59 pub fn no_images_in_use(&self) -> bool {
61 self.taken.is_empty()
62 }
63
64 pub fn image_count_for_testing(&self) -> usize {
66 self.image_count
67 }
68
69 pub fn available_count_for_testing(&self) -> usize {
71 self.available.len()
72 }
73}
74
75#[cfg(test)]
76mod frameset_tests {
77 use crate::{FrameSet, ImageId};
78 use std::collections::BTreeSet;
79 use std::ops::Range;
80
81 const IMAGE_RANGE: Range<ImageId> = 200..203;
82
83 #[fuchsia::test]
84 fn test_initial_state() {
85 let fs = FrameSet::new_with_range(IMAGE_RANGE);
86 assert_eq!(fs.image_count_for_testing(), 3);
87 assert_eq!(fs.available_count_for_testing(), 3);
88 assert!(fs.no_images_in_use());
89 }
90
91 #[fuchsia::test]
92 fn test_take_and_return_image() {
93 let mut fs = FrameSet::new_with_range(IMAGE_RANGE);
94
95 let img1 = fs.take_image();
96 assert_eq!(img1, Some(200));
97 assert_eq!(fs.available_count_for_testing(), 2);
98 assert!(!fs.no_images_in_use());
99
100 let img2 = fs.take_image();
101 assert_eq!(img2, Some(201));
102 assert_eq!(fs.available_count_for_testing(), 1);
103
104 fs.return_image(img1.unwrap());
105 assert_eq!(fs.available_count_for_testing(), 2);
106 assert!(!fs.no_images_in_use());
107
108 fs.return_image(img2.unwrap());
109 assert_eq!(fs.available_count_for_testing(), 3);
110 assert!(fs.no_images_in_use());
111 }
112
113 #[fuchsia::test]
114 #[should_panic(expected = "Attempted to return image 100 which was not currently taken")]
115 fn test_return_untracked_image_panics() {
116 let mut fs = FrameSet::new_with_range(IMAGE_RANGE);
117 fs.return_image(100);
118 }
119
120 #[fuchsia::test]
121 #[should_panic(expected = "Attempted to return image 200 which was not currently taken")]
122 fn test_return_already_available_image_panics() {
123 let mut fs = FrameSet::new_with_range(IMAGE_RANGE);
124 fs.return_image(200);
126 }
127
128 #[fuchsia::test]
129 #[should_panic(expected = "Attempted to return image 200 which was not currently taken")]
130 fn test_double_return_panics() {
131 let mut fs = FrameSet::new_with_range(IMAGE_RANGE);
132 let img = fs.take_image().expect("image");
133 fs.return_image(img);
134 fs.return_image(img);
135 }
136
137 #[fuchsia::test]
138 fn test_take_image_from_empty_pool() {
139 let mut fs = FrameSet::new_with_range(200..201);
140
141 let img = fs.take_image();
142 assert_eq!(img, Some(200));
143 assert_eq!(fs.take_image(), None);
145
146 fs.return_image(img.unwrap());
147 let img_again = fs.take_image();
148 assert_eq!(img_again, Some(200));
149 }
150
151 #[fuchsia::test]
152 fn test_empty_initial_set() {
153 let mut fs = FrameSet::new(BTreeSet::new());
154 assert_eq!(fs.image_count_for_testing(), 0);
155 assert_eq!(fs.available_count_for_testing(), 0);
156 assert!(fs.no_images_in_use());
157 assert_eq!(fs.take_image(), None);
158 }
159}
160
161#[derive(Debug, Clone, Copy, PartialEq)]
164pub enum FrameUsage {
165 Cpu,
166 Gpu,
167}