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> {
new( fgcolor: u32, bkcolor: u32, dst_pattern: EndianPattern, color_pattern: EndianPattern, byte_per_pixel: u32, src: Iter<'a, u8>, image_width: u32, ) -> Self24 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
reverse(num: u32, byte_per_pixel: u32) -> u3259 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
move_mask(&mut self) -> bool73 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
full_buffer(&mut self) -> Result<PixelLineStatus, PixelLineStatus>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
read_bit(&self) -> u32132 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);
next(&mut self) -> Option<Self::Item>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 {
unwarp(self) -> (u32, bool)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 {
new( frame_height: usize, frame_width: usize, bitdepth: usize, dst: VirtAddr, image: &FbImage, ) -> Self204 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 /// 写入某个数据并将指针增大
write<T>(&mut self, data: T) -> FramePointerStatus227 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应该是每行像素的开头
move_with_offset(&mut self, offset: u32)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
start_offset(image: &FbImage, bitdepth: u32, line_length: u32) -> u32287 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