xref: /DragonOS/kernel/src/driver/video/fbdev/base/render_helper.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1 use core::{ops::Add, slice::Iter};
2 
3 use crate::mm::VirtAddr;
4 
5 use super::FbImage;
6 
7 pub struct BitIter<'a> {
8     fgcolor: u32,
9     bkcolor: u32,
10     _color_pattern: EndianPattern,
11     _dst_pattern: EndianPattern,
12     src: Iter<'a, u8>,
13     read_mask: u8,
14     byte_per_pixel: u32,
15     buffer: u32,
16     current: u8,
17     left_byte: u32,
18     done: bool,
19     consumed_bit: u32,
20     image_width: u32,
21 }
22 
23 impl<'a> BitIter<'a> {
24     pub fn new(
25         fgcolor: u32,
26         bkcolor: u32,
27         dst_pattern: EndianPattern,
28         color_pattern: EndianPattern,
29         byte_per_pixel: u32,
30         src: Iter<'a, u8>,
31         image_width: u32,
32     ) -> Self {
33         let mut fgcolor = fgcolor;
34         let mut bkcolor = bkcolor;
35         if dst_pattern != color_pattern {
36             fgcolor = Self::reverse(fgcolor, byte_per_pixel);
37             bkcolor = Self::reverse(bkcolor, byte_per_pixel);
38         }
39 
40         let mut ans = Self {
41             fgcolor,
42             bkcolor,
43             _color_pattern: color_pattern,
44             _dst_pattern: dst_pattern,
45             src,
46             read_mask: 0b10000000,
47             byte_per_pixel,
48             buffer: 0,
49             current: 0,
50             left_byte: 0,
51             done: false,
52             consumed_bit: 0,
53             image_width,
54         };
55         ans.current = *ans.src.next().unwrap();
56         return ans;
57     }
58 
59     fn reverse(num: u32, byte_per_pixel: u32) -> u32 {
60         let mask = 0x000000ff;
61         let mut ans = 0;
62         let mut num = num;
63         for _ in 0..3 {
64             ans |= mask & num;
65             ans <<= 8;
66             num >>= 8;
67         }
68         ans |= mask & num;
69         ans >>= (4 - byte_per_pixel) * 8;
70         return ans;
71     }
72 
73     fn move_mask(&mut self) -> bool {
74         self.consumed_bit += 1;
75         self.read_mask >>= 1;
76         if self.read_mask == 0b000000000 {
77             self.read_mask = 0b10000000;
78             self.current = match self.src.next() {
79                 Some(x) => *x,
80                 None => {
81                     return false;
82                 }
83             };
84             return true;
85         } else {
86             return true;
87         }
88     }
89 
90     fn full_buffer(&mut self) -> Result<PixelLineStatus, PixelLineStatus> {
91         let same_endian = if self._dst_pattern == self._color_pattern {
92             1
93         } else {
94             -1
95         };
96         let mut color = self.read_bit() << (self.left_byte << 3);
97         let mut buffer_pointer = if self._dst_pattern == self._color_pattern {
98             0
99         } else {
100             3
101         };
102         let mask = 0x000000ff << ((self.byte_per_pixel - 1) << 3);
103         let mut temp;
104         // while buffer_pointer >= 0 && buffer_pointer <= 3 {
105         while (0..=3).contains(&buffer_pointer) {
106             if self.consumed_bit >= self.image_width {
107                 self.consumed_bit = 0;
108                 return Ok(PixelLineStatus::Full(self.buffer));
109             }
110             temp = color & mask;
111             color <<= 8;
112             temp <<= (4 - self.byte_per_pixel) * 8;
113             temp >>= buffer_pointer * 8;
114             self.buffer |= temp;
115             buffer_pointer += same_endian;
116             self.left_byte += 1;
117             if self.left_byte >= self.byte_per_pixel {
118                 self.left_byte = 0;
119                 if !self.move_mask() {
120                     return Err(PixelLineStatus::Full(self.buffer));
121                 }
122                 color = self.read_bit();
123             }
124         }
125         if self.consumed_bit >= self.image_width {
126             self.consumed_bit = 0;
127             return Ok(PixelLineStatus::Full(self.buffer));
128         }
129         return Ok(PixelLineStatus::NotFull(self.buffer));
130     }
131 
132     fn read_bit(&self) -> u32 {
133         match self.read_mask & self.current {
134             0 => self.bkcolor,
135             _ => self.fgcolor,
136         }
137     }
138 }
139 
140 impl Iterator for BitIter<'_> {
141     type Item = (u32, bool);
142     fn next(&mut self) -> Option<Self::Item> {
143         if self.done {
144             return None;
145         }
146         match self.full_buffer() {
147             Ok(x) => {
148                 self.buffer = 0;
149                 return Some(x.unwarp());
150             }
151             Err(x) => {
152                 self.done = true;
153                 return Some(x.unwarp());
154             }
155         }
156     }
157 }
158 #[derive(PartialEq, PartialOrd)]
159 pub enum EndianPattern {
160     Big,
161     Little,
162 }
163 
164 pub enum PixelLineStatus {
165     Full(u32),
166     NotFull(u32),
167 }
168 
169 impl PixelLineStatus {
170     pub fn unwarp(self) -> (u32, bool) {
171         match self {
172             PixelLineStatus::Full(x) => (x, true),
173             PixelLineStatus::NotFull(x) => (x, false),
174         }
175     }
176 }
177 
178 /// # 结构功能
179 /// 安全的FrameBufferPointer
180 /// 使用该结构体访问FrameBuffer可以防止超出FrameBuffer区域的访问
181 /// 需要注意,使用该指针写入时,任何超出屏幕的写入都是无效的!即使仍然可以写入显存。
182 /// 此外由于FbImage中的x和y变量采用u32类型,所以并未考虑左越界和上越界的安全性(即Image.x<0或Image.y<0的情况)
183 /// ## 成员
184 ///
185 ///  - "dst" : 显存base address,通常是0xffffa1003ff00000
186 ///  - "limit" : 显存区域上界,可以通过公式计算:limit = dst + 分辨率高*分辨率宽*每个像素的**字节**数。也就是说任何对于显存的访问应该限制在[dst,limit)中
187 ///  - "current" : 当前相对于start_offset的位移
188 ///  - "start_offset" : 如果你要渲染某个Image,你可能不是总是从屏幕左上角(0,0)开始渲染,你可能从某个offset开始
189 ///  - "start_xpos" : 表示你要渲染的Image的x位置的字节位置
190 ///  - "current_xpos" : 当前渲染的x位置的字节位置
191 ///  - "limit_xpos" : 最大的渲染x位置的字节位置。 例:假设系统的分辨率为640,位深为24,你需要渲染的Image的x坐标为200,那么start_xpos=200*3=600,current_xpos=200*3+当前行已经渲染像素数*3,limit_xpos=640*3
192 #[derive(Debug)]
193 pub struct FrameP {
194     dst: VirtAddr,
195     limit: VirtAddr,
196     current: usize,
197     start_offset: usize,
198     start_xpos: usize,
199     current_xpos: usize,
200     limit_xpos: usize,
201 }
202 
203 impl FrameP {
204     pub fn new(
205         frame_height: usize,
206         frame_width: usize,
207         bitdepth: usize,
208         dst: VirtAddr,
209         image: &FbImage,
210     ) -> Self {
211         let byte_per_pixel = bitdepth / 8;
212         let limit = VirtAddr::new(frame_height * frame_width * byte_per_pixel) + dst;
213         Self {
214             dst,
215             limit,
216             current: 0,
217             start_offset: start_offset(image, bitdepth as u32, (frame_width * bitdepth / 8) as u32)
218                 as usize,
219             start_xpos: image.x as usize * byte_per_pixel,
220             current_xpos: image.x as usize * byte_per_pixel,
221             limit_xpos: frame_width * byte_per_pixel,
222         }
223     }
224 
225     /// # 函数功能
226     /// 写入某个数据并将指针增大
227     pub fn write<T>(&mut self, data: T) -> FramePointerStatus {
228         // 首先获取数据大小
229         let size = size_of::<T>();
230         // 复制显存指针防止改变self的dst
231         let mut dst = self.dst;
232 
233         // 你最终要写入的位置实际上是[dst+start_offset+current,dst+start_offset+current+size),所以我们要确定你写入的位置是否超过limit
234         if self.dst.data() + self.current + self.start_offset + size > self.limit.data() {
235             return FramePointerStatus::OutOfBuffer;
236         }
237         // 我们也不希望你的x超出屏幕右边,超出屏幕右边的部分会被忽略掉,因为如果写入显存会导致内存风险
238         else if self.current_xpos + size > self.limit_xpos {
239             return FramePointerStatus::OutOfScreen;
240         }
241         // 如果上面两个检查都通过了,我们就可以写入显存了
242         else {
243             // 这里是写入位置的实际虚拟地址
244             dst = dst.add(self.current + self.start_offset);
245         }
246         // 写入操作
247         unsafe {
248             *dst.as_ptr::<T>() = data;
249         }
250         // 写入后更新current和xpos
251         self.current += size;
252         self.current_xpos += size;
253         // 由于写入正常,我们返回正常的状态
254         return FramePointerStatus::Normal;
255     }
256 
257     /// # 函数功能
258     /// 移动指针**至**某个offset
259     /// todo: 当前函数应当只用于换行,否则可能会导致安全性问题,即offset应该是每行像素的开头
260     pub fn move_with_offset(&mut self, offset: u32) {
261         self.current = offset as usize;
262         // let x_pos=self.current%self.limit_xpos;
263         // match x_pos{
264         //     n if n<self.start_xpos=>{
265         //         // send_to_default_serial8250_port(format!("Sended by function move_with_offset: Check if there is misusage of offset,the image.x is:{:?} while the xpos indicated by the offset is:{:?},current FP:{:?}\n",self.start_offset,x_pos,self).as_bytes());
266         //     }
267         //     n if n>=self.limit_xpos=>{
268         //         // send_to_default_serial8250_port(format!("Sended by function move_with_offset: Check if there is misusage of offset,The offset:{:?} is so large that it would exceed the limit of frame buffer\n",offset).as_bytes());
269         //     }
270         //     _=>{
271 
272         //     }
273         // }
274         self.current_xpos = self.start_xpos;
275     }
276 }
277 
278 pub enum FramePointerStatus {
279     /// 表示状态正常
280     Normal,
281     /// 超出屏幕,一直到换行时才应该恢复到正常状态
282     OutOfScreen,
283     /// 超出缓存,此时应当立即停止渲染
284     OutOfBuffer,
285 }
286 
287 pub fn start_offset(image: &FbImage, bitdepth: u32, line_length: u32) -> u32 {
288     let x = image.x;
289     let y = image.y;
290     let mut bitstart = (y * line_length * 8) + (x * bitdepth);
291     let byte_per_pixel = core::mem::size_of::<u32>() as u32;
292     // 位转字节
293     bitstart /= 8;
294 
295     // 对齐到像素字节大小
296     bitstart &= !(byte_per_pixel - 1);
297     return bitstart;
298 }
299