rast/graphics/
framebuffer.rs1use std::iter::{self, Iterator};
2
3use super::image::Image;
4
5fn fill_image<T: Sized + Copy>(attachment: &mut Image<T>, value: T) {
6 for (x, y) in attachment.coordinates() {
7 attachment.exchange(x, y, value);
8 }
9}
10
11pub struct Framebuffer {
12 width: usize,
13 height: usize,
14
15 color: Vec<Image<u32>>,
16 depth: Option<Image<f32>>,
17}
18
19#[derive(Debug)]
20pub struct ClearValue {
21 pub color: u32,
22 pub depth: f32,
23}
24
25pub struct MutableScanline<'a> {
26 pub y: usize,
27 pub color: Vec<&'a mut [u32]>,
28 pub depth: Option<&'a mut [f32]>,
29}
30
31impl Framebuffer {
32 pub fn new(width: usize, height: usize, num_color: usize, has_depth: bool) -> Framebuffer {
33 Framebuffer {
34 width: width,
35 height: height,
36
37 color: Vec::from_iter(iter::repeat_with(|| Image::new(width, height)).take(num_color)),
38 depth: match has_depth {
39 true => Some(Image::new(width, height)),
40 false => None,
41 },
42 }
43 }
44
45 pub fn size(&self) -> (usize, usize) {
46 (self.width, self.height)
47 }
48
49 pub fn color_attachments(&self) -> &Vec<Image<u32>> {
50 &self.color
51 }
52
53 pub fn depth_attachment(&self) -> &Option<Image<f32>> {
54 &self.depth
55 }
56
57 pub fn clear(&mut self, value: &ClearValue) {
58 for attachment in &mut self.color {
59 fill_image(attachment, value.color);
60 }
61
62 if let Some(depth) = &mut self.depth {
63 fill_image(depth, value.depth);
64 }
65 }
66
67 pub fn scanlines<'a>(&'a mut self, offset: usize, count: usize) -> Vec<MutableScanline<'a>> {
68 if offset >= self.height || offset + count > self.height {
69 panic!("Invalid scanline range!");
70 }
71
72 let start = offset * self.width;
73 let end = (offset + count) * self.width;
74
75 let mut color_cursors: Vec<_> = self
78 .color
79 .iter_mut()
80 .map(|attachment| &mut attachment.data_mut()[start..end])
81 .collect();
82
83 let mut depth_cursor = self
85 .depth
86 .as_mut()
87 .map(|attachment| &mut attachment.data_mut()[start..end]);
88
89 let mut scanlines = Vec::new();
90 for delta_y in 0..count {
91 let mut color = Vec::new();
92 let mut advanced_cursors = Vec::new();
93
94 for cursor in color_cursors {
97 let (first, second) = cursor.split_at_mut(self.width);
98
99 color.push(first);
100 advanced_cursors.push(second);
101 }
102
103 color_cursors = advanced_cursors;
104 scanlines.push(MutableScanline {
105 y: offset + delta_y,
106 color,
107
108 depth: match depth_cursor {
111 Some(cursor) => {
114 let (first, second) = cursor.split_at_mut(self.width);
115 depth_cursor = Some(second);
116
117 Some(first)
118 }
119
120 None => None,
122 },
123 });
124 }
125
126 scanlines
127 }
128}