rp_cvideo_core/
display_buffer.rs1#[cfg(test)]
2#[path = "../test/test_display_buffer.rs"]
3mod tests;
4
5use core::marker::PhantomData;
6
7pub struct DisplayBuffer<'t, FieldCount: NoFields> {
12 pub(crate) buffer: &'t mut [u32],
13
14 pub(crate) buffer_pixel_offsets: [usize; 2],
18
19 pub columns: u32,
21
22 pub lines: u32,
24
25 pub(crate) stride: usize,
27
28 pub(crate) _fc: PhantomData<FieldCount>,
29}
30
31trait Sealed {}
32
33#[allow(private_bounds)]
35pub trait Canvas: Sealed {
36 fn width(&self) -> u32;
37 fn height(&self) -> u32;
38 fn get_line_mut(&mut self, y: usize) -> &mut [u32];
39 fn get_line(&mut self, y: usize) -> &[u32];
40 fn set_pixel(&mut self, x: usize, y: usize, value: bool);
41 fn get_pixel(&self, x: usize, y: usize) -> bool;
42 fn fill(&mut self, value: bool);
43 fn buffer(&self) -> &[u32];
44
45 unsafe fn buffer_mut(&mut self) -> &mut [u32];
46}
47
48impl Sealed for DisplayBuffer<'_, OneField> {}
49impl Sealed for DisplayBuffer<'_, TwoFields> {}
50
51impl DisplayBuffer<'_, OneField> {
52 fn pixel_index(&self, x: usize, y: usize) -> (usize, usize) {
56 (
57 self.buffer_pixel_offsets[0] + self.stride * y + x / 32,
58 x % 32,
59 )
60 }
61
62 const fn display_line_size(&self) -> usize {
66 self.columns as usize / 32 + 1
69 }
70}
71
72impl Canvas for DisplayBuffer<'_, OneField> {
73 #[allow(missing_docs)]
74 fn width(&self) -> u32 {
75 self.columns
76 }
77
78 #[allow(missing_docs)]
79 fn height(&self) -> u32 {
80 self.lines
81 }
82
83 fn get_line_mut(&mut self, y: usize) -> &mut [u32] {
87 let start = self.buffer_pixel_offsets[0] + self.stride * y;
88 let display_line_size = self.display_line_size();
89 &mut self.buffer[start..start + display_line_size]
90 }
91
92 fn get_line(&mut self, y: usize) -> &[u32] {
96 self.get_line_mut(y)
97 }
98
99 #[allow(missing_docs)]
100 fn set_pixel(&mut self, x: usize, y: usize, value: bool) {
101 let (word, bit) = self.pixel_index(x, y);
102 if value {
103 self.buffer[word] |= 1 << bit;
104 } else {
105 self.buffer[word] &= !(1 << bit);
106 }
107 }
108
109 #[allow(missing_docs)]
110 fn get_pixel(&self, x: usize, y: usize) -> bool {
111 let (word, bit) = self.pixel_index(x, y);
112 self.buffer[word] & (1 << bit) != 0
113 }
114
115 #[allow(missing_docs)]
116 fn fill(&mut self, value: bool) {
117 let fill_value = if value { u32::MAX } else { 0 };
118 let row_size = self.display_line_size();
119
120 for row in 0..self.lines as usize {
121 let row_offset = self.pixel_index(0, row).0;
122 let row_slice = &mut self.buffer[row_offset..row_offset + row_size];
123 row_slice.fill(fill_value);
124 }
125 }
126
127 fn buffer(&self) -> &[u32] {
131 self.buffer
132 }
133
134 unsafe fn buffer_mut(&mut self) -> &mut [u32] {
142 self.buffer
143 }
144}
145
146impl<'t> DisplayBuffer<'t, TwoFields> {
147 const fn display_line_size(&self) -> usize {
151 self.columns as usize / 32 + 1
154 }
155
156 fn pixel_index(&self, x: usize, y: usize) -> (usize, usize) {
161 let y2 = y / 2;
162
163 (
164 self.buffer_pixel_offsets[y & 1] + self.stride * y2 + x / 32,
165 x % 32,
166 )
167 }
168}
169
170impl Canvas for DisplayBuffer<'_, TwoFields> {
171 #[allow(missing_docs)]
172 fn width(&self) -> u32 {
173 self.columns
174 }
175
176 #[allow(missing_docs)]
177 fn height(&self) -> u32 {
178 self.lines
179 }
180
181 fn get_line_mut(&mut self, y: usize) -> &mut [u32] {
185 let y2 = y / 2;
186 let start = self.buffer_pixel_offsets[y & 1] + self.stride * y2;
187 let display_line_size = self.display_line_size();
188 &mut self.buffer[start..start + display_line_size]
189 }
190
191 fn get_line(&mut self, y: usize) -> &[u32] {
195 self.get_line_mut(y)
196 }
197
198 #[allow(missing_docs)]
199 fn set_pixel(&mut self, x: usize, y: usize, value: bool) {
200 let (word, bit) = self.pixel_index(x, y);
201 if value {
202 self.buffer[word] |= 1 << bit;
203 } else {
204 self.buffer[word] &= !(1 << bit);
205 }
206 }
207
208 #[allow(missing_docs)]
209 fn get_pixel(&self, x: usize, y: usize) -> bool {
210 let (word, bit) = self.pixel_index(x, y);
211 self.buffer[word] & (1 << bit) != 0
212 }
213
214 #[allow(missing_docs)]
215 fn fill(&mut self, value: bool) {
216 let fill_value = if value { u32::MAX } else { 0 };
217 let row_size = self.display_line_size();
218
219 for row in 0..self.lines as usize {
220 let row_offset = self.pixel_index(0, row).0;
221 let row_slice = &mut self.buffer[row_offset..row_offset + row_size];
222 row_slice.fill(fill_value);
223 }
224 }
225
226 fn buffer(&self) -> &[u32] {
230 self.buffer
231 }
232
233 unsafe fn buffer_mut(&mut self) -> &mut [u32] {
241 self.buffer
242 }
243}
244
245pub trait NoFields: Copy {
246 const N: usize;
247}
248
249#[derive(Copy, Clone)]
251pub struct OneField;
252
253#[derive(Copy, Clone)]
255pub struct TwoFields;
256
257impl NoFields for OneField {
258 const N: usize = 1;
259}
260
261impl NoFields for TwoFields {
262 const N: usize = 2;
263}