xref: /DragonOS/kernel/src/driver/video/fbdev/base/mod.rs (revision f5c732d8dc4803803c9a9461b36164e85215e69f) !
1 use alloc::{string::String, sync::Arc, vec::Vec};
2 use render_helper::{FrameP, FramePointerStatus};
3 use system_error::SystemError;
4 
5 use crate::{
6     driver::{base::device::Device, tty::virtual_terminal::Color},
7     init::boot_params,
8     libs::rwlock::RwLock,
9     mm::{ucontext::LockedVMA, PhysAddr, VirtAddr},
10 };
11 
12 use self::{
13     fbmem::{FbDevice, FrameBufferManager},
14     render_helper::{BitIter, EndianPattern},
15 };
16 
17 const COLOR_TABLE_8: &[u32] = &[
18     0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
19     0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff,
20 ];
21 
22 const COLOR_TABLE_16: &[u32] = &[0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff];
23 
24 const COLOR_TABLE_32: &[u32] = &[0x00000000, 0xffffffff];
25 
26 pub mod fbcon;
27 pub mod fbmem;
28 pub mod fbsysfs;
29 pub mod modedb;
30 pub mod render_helper;
31 // 帧缓冲区id
32 int_like!(FbId, u32);
33 
34 lazy_static! {
35     pub static ref FRAME_BUFFER_SET: RwLock<Vec<Option<Arc<dyn FrameBuffer>>>> = {
36         let mut ret = Vec::new();
37         ret.resize(FrameBufferManager::FB_MAX, None);
38         RwLock::new(ret)
39     };
40 }
41 
42 impl FbId {
43     /// 帧缓冲区id的初始值(无效值)
44     pub const INIT: Self = Self::new(u32::MAX);
45 
46     /// 判断是否为无效的帧缓冲区id
47     #[allow(dead_code)]
is_valid(&self) -> bool48     pub const fn is_valid(&self) -> bool {
49         if self.0 == Self::INIT.0 || self.0 >= FrameBufferManager::FB_MAX as u32 {
50             return false;
51         }
52         return true;
53     }
54 }
55 
56 /// 帧缓冲区应该实现的接口
57 pub trait FrameBuffer: FrameBufferInfo + FrameBufferOps + Device {
58     /// 获取帧缓冲区的id
fb_id(&self) -> FbId59     fn fb_id(&self) -> FbId;
60 
61     /// 设置帧缓冲区的id
set_fb_id(&self, id: FbId)62     fn set_fb_id(&self, id: FbId);
63 
64     /// 通用的软件图像绘画
generic_imageblit(&self, image: &FbImage)65     fn generic_imageblit(&self, image: &FbImage) {
66         let boot_param = boot_params().read();
67         let x = image.x;
68         let y = image.y;
69         let byte_per_pixel = core::mem::size_of::<u32>() as u32;
70         let bit_per_pixel = self.current_fb_var().bits_per_pixel;
71 
72         // 计算图像在帧缓冲中的起始位
73         let bitstart = (y * self.current_fb_fix().line_length * 8) + (x * bit_per_pixel);
74         let start_index = bitstart & (32 - 1);
75         let pitch_index = (self.current_fb_fix().line_length & (byte_per_pixel - 1)) * 8;
76         let dst2 = boot_param.screen_info.lfb_virt_base;
77         if dst2.is_none() {
78             return;
79         }
80         let mut safe_pointer = FrameP::new(
81             self.current_fb_var().yres as usize,
82             self.current_fb_var().xres as usize,
83             self.current_fb_var().bits_per_pixel as usize,
84             dst2.unwrap(),
85             image,
86         );
87         let _ = self.fb_sync();
88 
89         if image.depth == 1 {
90             let fg;
91             let bg;
92             if self.current_fb_fix().visual == FbVisual::TrueColor
93                 || self.current_fb_fix().visual == FbVisual::DirectColor
94             {
95                 let fb_info_data = self.framebuffer_info_data().read();
96                 fg = fb_info_data.pesudo_palette[image.fg as usize];
97                 bg = fb_info_data.pesudo_palette[image.bg as usize];
98             } else {
99                 fg = image.fg;
100                 bg = image.bg;
101             }
102 
103             if 32 % bit_per_pixel == 0
104                 && start_index == 0
105                 && pitch_index == 0
106                 && image.width & (32 / bit_per_pixel - 1) == 0
107                 && (8..=32).contains(&bit_per_pixel)
108             {
109                 unsafe { self.fast_imageblit(image, &mut safe_pointer, fg, bg) }
110             } else {
111                 self.slow_imageblit(image, &mut safe_pointer, fg, bg)
112             }
113         } else {
114             todo!("color image blit todo");
115         }
116     }
117 
118     /// 优化的单色图像绘制函数
119     ///
120     /// 仅当 bits_per_pixel 为 8、16 或 32 时才能使用。
121     /// 要求 image->width 可以被像素或 dword (ppw) 整除。
122     /// 要求 fix->line_length 可以被 4 整除。
123     /// 扫描线的开始和结束都是 dword 对齐的。
fast_imageblit(&self, image: &FbImage, dst1: &mut FrameP, fg: u32, bg: u32)124     unsafe fn fast_imageblit(&self, image: &FbImage, dst1: &mut FrameP, fg: u32, bg: u32) {
125         let bpp = self.current_fb_var().bits_per_pixel;
126         let mut fgx = fg;
127         let mut bgx = bg;
128         let ppw = 32 / bpp;
129         let spitch = (image.width + 7) / 8;
130         let mut color_tab: [u32; 16] = [0; 16];
131 
132         let tab: &[u32] = match bpp {
133             8 => COLOR_TABLE_8,
134             16 => COLOR_TABLE_16,
135             32 => COLOR_TABLE_32,
136             _ => {
137                 return;
138             }
139         };
140 
141         for _ in (0..(ppw - 1)).rev() {
142             fgx <<= bpp;
143             bgx <<= bpp;
144             fgx |= fg;
145             bgx |= bg;
146         }
147 
148         let bitmask = (1 << ppw) - 1;
149         let eorx = fgx ^ bgx;
150         let k = image.width / ppw;
151 
152         for (idx, val) in tab.iter().enumerate() {
153             color_tab[idx] = (*val & eorx) ^ bgx;
154         }
155 
156         let mut shift;
157         let mut src;
158         let mut offset = 0;
159         let mut j = 0;
160         let mut count = 0;
161         for _ in (0..image.height).rev() {
162             shift = 8;
163             src = offset;
164             match ppw {
165                 4 => {
166                     // 8bpp
167                     j = k;
168                     while j >= 2 {
169                         dst1.write(color_tab[(image.data[src] as usize >> 4) & bitmask]);
170                         dst1.write(color_tab[(image.data[src] as usize) & bitmask]);
171                         j -= 2;
172                         src += 1;
173                     }
174                 }
175                 2 => {
176                     // 16bpp
177                     j = k;
178                     while j >= 4 {
179                         dst1.write(color_tab[(image.data[src] as usize >> 6) & bitmask]);
180                         dst1.write(color_tab[(image.data[src] as usize >> 4) & bitmask]);
181                         dst1.write(color_tab[(image.data[src] as usize >> 2) & bitmask]);
182                         dst1.write(color_tab[(image.data[src] as usize) & bitmask]);
183                         src += 1;
184                         j -= 4;
185                     }
186                 }
187                 1 => {
188                     // 32 bpp
189                     j = k;
190                     while j >= 8 {
191                         dst1.write(color_tab[(image.data[src] as usize >> 7) & bitmask]);
192                         dst1.write(color_tab[(image.data[src] as usize >> 6) & bitmask]);
193                         dst1.write(color_tab[(image.data[src] as usize >> 5) & bitmask]);
194                         dst1.write(color_tab[(image.data[src] as usize >> 4) & bitmask]);
195                         dst1.write(color_tab[(image.data[src] as usize >> 3) & bitmask]);
196                         dst1.write(color_tab[(image.data[src] as usize >> 2) & bitmask]);
197                         dst1.write(color_tab[(image.data[src] as usize >> 1) & bitmask]);
198                         dst1.write(color_tab[(image.data[src] as usize) & bitmask]);
199                         src += 1;
200                         j -= 8;
201                     }
202                 }
203                 _ => {}
204             }
205 
206             /*
207              * For image widths that are not a multiple of 8, there
208              * are trailing pixels left on the current line. Print
209              * them as well.
210              */
211             while j != 0 {
212                 shift -= ppw;
213                 dst1.write(color_tab[(image.data[src] as usize >> shift) & bitmask]);
214                 if shift == 0 {
215                     shift = 8;
216                     src += 1;
217                 }
218                 j -= 1;
219             }
220 
221             count += 1;
222             dst1.move_with_offset(self.current_fb_fix().line_length * count);
223             offset += spitch as usize;
224         }
225     }
226 
slow_imageblit(&self, _image: &FbImage, safe_dst: &mut FrameP, _fg: u32, _bg: u32)227     fn slow_imageblit(&self, _image: &FbImage, safe_dst: &mut FrameP, _fg: u32, _bg: u32) {
228         let mut count = 0;
229         let mut pt_status = FramePointerStatus::Normal;
230         let iter = BitIter::new(
231             _fg,
232             _bg,
233             EndianPattern::Big,
234             EndianPattern::Little,
235             self.current_fb_var().bits_per_pixel / 8,
236             _image.data.iter(),
237             _image.width,
238         );
239         for (content, full) in iter {
240             match pt_status {
241                 FramePointerStatus::OutOfBuffer => {
242                     return;
243                 }
244                 FramePointerStatus::OutOfScreen => {}
245                 FramePointerStatus::Normal => {
246                     pt_status = safe_dst.write(content);
247                 }
248             }
249             if full {
250                 count += 1;
251                 safe_dst.move_with_offset(self.current_fb_fix().line_length * count);
252                 pt_status = FramePointerStatus::Normal;
253             }
254         }
255     }
256 }
257 
258 #[derive(Debug, Default)]
259 pub struct FrameBufferInfoData {
260     /// 颜色映射
261     pub color_map: Vec<Color>,
262     /// 颜色映射表
263     pub pesudo_palette: Vec<u32>,
264 }
265 
266 impl FrameBufferInfoData {
new() -> Self267     pub fn new() -> Self {
268         Self {
269             ..Default::default()
270         }
271     }
272 }
273 
274 /// 帧缓冲区信息
275 #[allow(dead_code)]
276 pub trait FrameBufferInfo: FrameBufferOps {
framebuffer_info_data(&self) -> &RwLock<FrameBufferInfoData>277     fn framebuffer_info_data(&self) -> &RwLock<FrameBufferInfoData>;
278 
279     /// Amount of ioremapped VRAM or 0
screen_size(&self) -> usize280     fn screen_size(&self) -> usize;
281 
282     /// 获取当前的可变帧缓冲信息
current_fb_var(&self) -> FbVarScreenInfo283     fn current_fb_var(&self) -> FbVarScreenInfo;
284 
285     /// 获取当前的固定帧缓冲信息
current_fb_fix(&self) -> FixedScreenInfo286     fn current_fb_fix(&self) -> FixedScreenInfo;
287 
288     /// 获取当前的视频模式
video_mode(&self) -> Option<&FbVideoMode>289     fn video_mode(&self) -> Option<&FbVideoMode>;
290 
291     /// 获取当前帧缓冲区对应的`/sys/class/graphics/fb0`或者`/sys/class/graphics/fb1`等的设备结构体
fb_device(&self) -> Option<Arc<FbDevice>>292     fn fb_device(&self) -> Option<Arc<FbDevice>>;
293 
294     /// 设置当前帧缓冲区对应的`/sys/class/graphics/fb0`或者`/sys/class/graphics/fb1`等的设备结构体
set_fb_device(&self, device: Option<Arc<FbDevice>>)295     fn set_fb_device(&self, device: Option<Arc<FbDevice>>);
296 
297     /// 获取帧缓冲区的状态
state(&self) -> FbState298     fn state(&self) -> FbState;
299 
300     /// 颜色位深
color_depth(&self) -> u32301     fn color_depth(&self) -> u32 {
302         return 8;
303 
304         // 以下逻辑没问题,但是当前没有初始化好var,所以先直接返回当前vasafb的8
305 
306         // let var = self.current_fb_var();
307         // let fix = self.current_fb_fix();
308         // if fix.visual == FbVisual::Mono01 || fix.visual == FbVisual::Mono10 {
309         //     return 1;
310         // } else {
311         //     if var.green.length == var.blue.length
312         //         && var.green.length == var.red.length
313         //         && var.green.offset == var.blue.offset
314         //         && var.green.offset == var.red.offset
315         //     {
316         //         error!("return {}", var.green.length);
317         //         return var.green.length;
318         //     } else {
319         //         return var.green.length + var.blue.length + var.red.length;
320         //     }
321         // }
322     }
323 
324     /// ## 设置调色板
set_color_map(&self, cmap: Vec<Color>) -> Result<(), SystemError>325     fn set_color_map(&self, cmap: Vec<Color>) -> Result<(), SystemError> {
326         let ret = self.fb_set_color_map(cmap.clone());
327         if ret.is_err() && ret.clone().unwrap_err() == SystemError::ENOSYS {
328             for (idx, color) in cmap.iter().enumerate() {
329                 if self
330                     .fb_set_color_register(idx as u16, color.red, color.green, color.blue)
331                     .is_err()
332                 {
333                     break;
334                 }
335             }
336 
337             self.framebuffer_info_data().write().color_map = cmap;
338         } else {
339             if ret.is_ok() {
340                 self.framebuffer_info_data().write().color_map = cmap;
341             }
342             return ret;
343         }
344 
345         Ok(())
346     }
347 }
348 
349 /// 帧缓冲区操作
350 ///
351 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/linux/fb.h#237
352 #[allow(dead_code)]
353 pub trait FrameBufferOps {
fb_open(&self, user: bool)354     fn fb_open(&self, user: bool);
fb_release(&self, user: bool)355     fn fb_release(&self, user: bool);
356 
357     /// 读取帧缓冲区的内容。
358     ///
359     /// 对于具有奇特非线性布局的帧缓冲区或正常内存映射访问无法工作的帧缓冲区,可以使用此方法。
fb_read(&self, _buf: &mut [u8], _pos: usize) -> Result<usize, SystemError>360     fn fb_read(&self, _buf: &mut [u8], _pos: usize) -> Result<usize, SystemError> {
361         Err(SystemError::ENOSYS)
362     }
363 
364     /// 将帧缓冲区的内容写入。
365     ///
366     /// 对于具有奇特非线性布局的帧缓冲区或正常内存映射访问无法工作的帧缓冲区,可以使用此方法。
fb_write(&self, _buf: &[u8], _pos: usize) -> Result<usize, SystemError>367     fn fb_write(&self, _buf: &[u8], _pos: usize) -> Result<usize, SystemError> {
368         Err(SystemError::ENOSYS)
369     }
370 
371     /// 设置帧缓冲区的颜色寄存器。
372     ///
373     /// 颜色寄存器的数量和含义取决于帧缓冲区的硬件。
374     ///
375     /// ## 参数
376     ///
377     /// - `regno`:寄存器编号。
378     /// - `red`:红色分量。
379     /// - `green`:绿色分量。
380     /// - `blue`:蓝色分量。
fb_set_color_register( &self, regno: u16, red: u16, green: u16, blue: u16, ) -> Result<(), SystemError>381     fn fb_set_color_register(
382         &self,
383         regno: u16,
384         red: u16,
385         green: u16,
386         blue: u16,
387     ) -> Result<(), SystemError>;
388 
389     /// 设置帧缓冲区的黑屏模式
fb_blank(&self, blank_mode: BlankMode) -> Result<(), SystemError>390     fn fb_blank(&self, blank_mode: BlankMode) -> Result<(), SystemError>;
391 
392     /// 在帧缓冲区中绘制一个矩形。
fb_fillrect(&self, _data: FillRectData) -> Result<(), SystemError>393     fn fb_fillrect(&self, _data: FillRectData) -> Result<(), SystemError> {
394         Err(SystemError::ENOSYS)
395     }
396 
397     /// 将数据从一处复制到另一处。
fb_copyarea(&self, _data: CopyAreaData)398     fn fb_copyarea(&self, _data: CopyAreaData);
399 
400     /// 将帧缓冲区的内容映射到用户空间。
fb_mmap(&self, _vma: &Arc<LockedVMA>) -> Result<(), SystemError>401     fn fb_mmap(&self, _vma: &Arc<LockedVMA>) -> Result<(), SystemError> {
402         Err(SystemError::ENOSYS)
403     }
404 
405     /// 卸载与该帧缓冲区相关的所有资源
fb_destroy(&self)406     fn fb_destroy(&self);
407 
408     /// 画光标
fb_cursor(&self, _cursor: &FbCursor) -> Result<(), SystemError>409     fn fb_cursor(&self, _cursor: &FbCursor) -> Result<(), SystemError> {
410         return Err(SystemError::ENOSYS);
411     }
412 
413     /// 画软光标(暂时简要实现)
soft_cursor(&self, cursor: FbCursor) -> Result<(), SystemError>414     fn soft_cursor(&self, cursor: FbCursor) -> Result<(), SystemError> {
415         let mut image = cursor.image.clone();
416         if cursor.enable {
417             match cursor.rop {
418                 true => {
419                     for i in 0..image.data.len() {
420                         image.data[i] ^= cursor.mask[i];
421                     }
422                 }
423                 false => {
424                     for i in 0..image.data.len() {
425                         image.data[i] &= cursor.mask[i];
426                     }
427                 }
428             }
429         }
430 
431         self.fb_image_blit(&image);
432 
433         Ok(())
434     }
435 
fb_sync(&self) -> Result<(), SystemError>436     fn fb_sync(&self) -> Result<(), SystemError> {
437         return Err(SystemError::ENOSYS);
438     }
439 
440     /// 绘画位图
fb_image_blit(&self, image: &FbImage)441     fn fb_image_blit(&self, image: &FbImage);
442 
fb_set_color_map(&self, _cmap: Vec<Color>) -> Result<(), SystemError>443     fn fb_set_color_map(&self, _cmap: Vec<Color>) -> Result<(), SystemError> {
444         return Err(SystemError::ENOSYS);
445     }
446 }
447 
448 /// 帧缓冲区的状态
449 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
450 pub enum FbState {
451     Running = 0,
452     Suspended = 1,
453 }
454 
455 /// 屏幕黑屏模式。
456 #[allow(dead_code)]
457 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
458 pub enum BlankMode {
459     /// 取消屏幕黑屏, 垂直同步和水平同步均打开
460     Unblank,
461     /// 屏幕黑屏, 垂直同步和水平同步均打开
462     Normal,
463     /// 屏幕黑屏, 水平同步打开, 垂直同步关闭
464     HSync,
465     /// 屏幕黑屏, 水平同步关闭, 垂直同步打开
466     VSync,
467     /// 屏幕黑屏, 水平同步和垂直同步均关闭
468     Powerdown,
469 }
470 
471 /// `FillRectData` 结构体用于表示一个矩形区域并填充特定颜色。
472 ///
473 /// # 结构体字段
474 /// * `dx`:
475 /// * `dy`:
476 /// * `width`:
477 /// * `height`: 矩形的高度
478 /// * `color`: 用于填充矩形的颜色,是一个32位无符号整数
479 /// * `rop`: 光栅操作(Raster Operation),用于定义如何将颜色应用到矩形区域
480 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
481 pub struct FillRectData {
482     /// 矩形左上角的x坐标(相对于屏幕)
483     pub dx: u32,
484     /// 矩形左上角的y坐标(相对于屏幕)
485     pub dy: u32,
486     /// 矩形的宽度
487     pub width: u32,
488     /// 矩形的高度
489     pub height: u32,
490     /// 用于填充矩形的颜色,是一个32位无符号整数
491     pub color: u32,
492     /// 光栅操作(Raster Operation),用于定义如何将颜色应用到矩形区域
493     pub rop: FillRectROP,
494 }
495 
496 impl FillRectData {
497     #[allow(dead_code)]
new(dx: u32, dy: u32, width: u32, height: u32, color: u32, rop: FillRectROP) -> Self498     pub fn new(dx: u32, dy: u32, width: u32, height: u32, color: u32, rop: FillRectROP) -> Self {
499         Self {
500             dx,
501             dy,
502             width,
503             height,
504             color,
505             rop,
506         }
507     }
508 }
509 
510 /// 光栅操作(Raster Operation),用于定义如何将颜色应用到矩形区域
511 #[allow(dead_code)]
512 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
513 pub enum FillRectROP {
514     /// 复制操作,即直接将指定颜色应用到矩形区域,覆盖原有颜色。
515     Copy,
516     /// 异或操作,即将指定颜色与矩形区域原有颜色进行异或操作,结果颜色应用到矩形区域。
517     Xor,
518 }
519 
520 /// `CopyAreaData` 结构体用于表示一个矩形区域,并指定从哪个源位置复制数据。
521 ///
522 /// 注意,源位置必须是有意义的(即包围的矩形都必须得在屏幕内)
523 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
524 pub struct CopyAreaData {
525     /// 目标矩形左上角的x坐标
526     pub dx: i32,
527     /// 目标矩形左上角的y坐标
528     pub dy: i32,
529     /// 矩形的宽度
530     pub width: u32,
531     /// 矩形的高度
532     pub height: u32,
533     /// 源矩形左上角的x坐标
534     pub sx: i32,
535     /// 源矩形左上角的y坐标
536     pub sy: i32,
537 }
538 
539 impl CopyAreaData {
540     #[allow(dead_code)]
new(dx: i32, dy: i32, width: u32, height: u32, sx: i32, sy: i32) -> Self541     pub fn new(dx: i32, dy: i32, width: u32, height: u32, sx: i32, sy: i32) -> Self {
542         Self {
543             dx,
544             dy,
545             width,
546             height,
547             sx,
548             sy,
549         }
550     }
551 }
552 
553 /// `FbVarScreenInfo` 结构体用于描述屏幕的各种属性。
554 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
555 pub struct FbVarScreenInfo {
556     /// 可见分辨率的宽度
557     pub xres: u32,
558     /// 可见分辨率的高度
559     pub yres: u32,
560     /// 虚拟分辨率的宽度
561     pub xres_virtual: u32,
562     /// 虚拟分辨率的高度
563     pub yres_virtual: u32,
564     /// 从虚拟到可见分辨率的偏移量(宽度方向)
565     pub xoffset: u32,
566     /// 从虚拟到可见分辨率的偏移量(高度方向)
567     pub yoffset: u32,
568     /// 每像素的位数
569     pub bits_per_pixel: u32,
570     /// 颜色模式
571     pub color_mode: FbColorMode,
572     /// 红色位域
573     pub red: FbBitfield,
574     /// 绿色位域
575     pub green: FbBitfield,
576     /// 蓝色位域
577     pub blue: FbBitfield,
578     /// 透明度位域
579     pub transp: FbBitfield,
580     /// 像素格式
581     pub pixel_format: FbPixelFormat,
582     /// 激活标志(参见FB_ACTIVATE_*)
583     pub activate: FbActivateFlags,
584     /// 帧缓冲区的高度(像素) None表示未知
585     pub height: Option<u32>,
586     /// 帧缓冲区的宽度(像素) None表示未知
587     pub width: Option<u32>,
588     /// 像素时钟(皮秒)
589     pub pixclock: u32,
590     /// 左边距
591     pub left_margin: u32,
592     /// 右边距
593     pub right_margin: u32,
594     /// 上边距
595     pub upper_margin: u32,
596     /// 下边距
597     pub lower_margin: u32,
598     /// 水平同步的长度
599     pub hsync_len: u32,
600     /// 垂直同步的长度
601     pub vsync_len: u32,
602     /// 同步标志(参见FB_SYNC_*)
603     pub sync: FbSyncFlags,
604     /// 视频模式(参见FB_VMODE_*)
605     pub vmode: FbVModeFlags,
606     /// 逆时针旋转的角度
607     pub rotate_angle: u32,
608     /// 颜色空间
609     pub colorspace: V4l2Colorspace,
610 }
611 
612 impl Default for FbVarScreenInfo {
default() -> Self613     fn default() -> Self {
614         Self {
615             xres: Default::default(),
616             yres: Default::default(),
617             xres_virtual: Default::default(),
618             yres_virtual: Default::default(),
619             xoffset: Default::default(),
620             yoffset: Default::default(),
621             bits_per_pixel: Default::default(),
622             color_mode: Default::default(),
623             red: Default::default(),
624             green: Default::default(),
625             blue: Default::default(),
626             transp: Default::default(),
627             pixel_format: Default::default(),
628             activate: Default::default(),
629             height: None,
630             width: None,
631             pixclock: Default::default(),
632             left_margin: Default::default(),
633             right_margin: Default::default(),
634             upper_margin: Default::default(),
635             lower_margin: Default::default(),
636             hsync_len: Default::default(),
637             vsync_len: Default::default(),
638             sync: FbSyncFlags::empty(),
639             vmode: FbVModeFlags::empty(),
640             rotate_angle: Default::default(),
641             colorspace: Default::default(),
642         }
643     }
644 }
645 
646 /// 帧缓冲区的颜色模式
647 ///
648 /// 默认为彩色
649 #[allow(dead_code)]
650 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
651 pub enum FbColorMode {
652     /// 灰度
653     GrayScale,
654     /// 彩色
655     #[default]
656     Color,
657     /// FOURCC
658     FourCC,
659 }
660 
661 /// `FbBitfield` 结构体用于描述颜色字段的位域。
662 ///
663 /// 所有的偏移量都是从右边开始,位于一个精确为'bits_per_pixel'宽度的"像素"值内。
664 /// 一个像素之后是一个位流,并且未经修改地写入视频内存。
665 ///
666 /// 对于伪颜色:所有颜色组件的偏移和长度应该相同。
667 /// 偏移指定了调色板索引在像素值中的最低有效位的位置。
668 /// 长度表示可用的调色板条目的数量(即条目数 = 1 << 长度)。
669 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
670 pub struct FbBitfield {
671     /// 位域的起始位置
672     pub offset: u32,
673     /// 位域的长度
674     pub length: u32,
675     /// 最高有效位是否在右边
676     pub msb_right: bool,
677 }
678 
679 impl FbBitfield {
680     #[allow(dead_code)]
new(offset: u32, length: u32, msb_right: bool) -> Self681     pub fn new(offset: u32, length: u32, msb_right: bool) -> Self {
682         Self {
683             offset,
684             length,
685             msb_right,
686         }
687     }
688 }
689 
690 bitflags! {
691     /// `FbActivateFlags` 用于描述帧缓冲区的激活标志。
692     ///
693     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/include/uapi/linux/fb.h#198
694     pub struct FbActivateFlags: u32 {
695         /// 立即设置值(或vbl)
696         const FB_ACTIVATE_NOW = 0;
697         /// 在下一次打开时激活
698         const FB_ACTIVATE_NXTOPEN = 1;
699         /// don't set, round up impossible values
700         const FB_ACTIVATE_TEST = 2;
701         const FB_ACTIVATE_MASK = 15;
702 
703         /// 在下一个vbl上激活值
704         const FB_ACTIVATE_VBL = 16;
705         /// 在vbl上更改色彩映射
706         const FB_ACTIVATE_CHANGE_CMAP_VBL = 32;
707         /// 更改此fb上的所有VC
708         const FB_ACTIVATE_ALL = 64;
709         /// 即使没有变化也强制应用
710         const FB_ACTIVATE_FORCE = 128;
711         /// 使视频模式无效
712         const FB_ACTIVATE_INV_MODE = 256;
713         /// 用于KDSET vt ioctl
714         const FB_ACTIVATE_KD_TEXT = 512;
715     }
716 }
717 
718 impl Default for FbActivateFlags {
default() -> Self719     fn default() -> Self {
720         FbActivateFlags::FB_ACTIVATE_NOW
721     }
722 }
723 
724 #[allow(dead_code)]
725 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
726 pub enum FbPixelFormat {
727     #[default]
728     Standard,
729     /// Hold And Modify
730     HAM,
731     /// order of pixels in each byte is reversed
732     Reserved,
733 }
734 
735 bitflags! {
736     pub struct FbSyncFlags: u32 {
737         /// 水平同步高电平有效
738         const FB_SYNC_HOR_HIGH_ACT = 1;
739         /// 垂直同步高电平有效
740         const FB_SYNC_VERT_HIGH_ACT = 2;
741         /// 外部同步
742         const FB_SYNC_EXT = 4;
743         /// 复合同步高电平有效
744         const FB_SYNC_COMP_HIGH_ACT = 8;
745         /// 广播视频时序
746         const FB_SYNC_BROADCAST = 16;
747         /// sync on green
748         const FB_SYNC_ON_GREEN = 32;
749     }
750 }
751 
752 bitflags! {
753     /// `FbVModeFlags` 用于描述帧缓冲区的视频模式。
754     pub struct FbVModeFlags: u32 {
755         /// 非交错
756         const FB_VMODE_NONINTERLACED = 0;
757         /// 交错
758         const FB_VMODE_INTERLACED = 1;
759         /// 双扫描
760         const FB_VMODE_DOUBLE = 2;
761         /// 交错:首先是顶行
762         const FB_VMODE_ODD_FLD_FIRST = 4;
763         /// 掩码
764         const FB_VMODE_MASK = 255;
765         /// ywrap代替平移
766         const FB_VMODE_YWRAP = 256;
767         /// 平滑xpan可能(内部使用)
768         const FB_VMODE_SMOOTH_XPAN = 512;
769         /// 不更新x/yoffset
770         const FB_VMODE_CONUPDATE = 512;
771     }
772 }
773 
774 /// 视频颜色空间
775 #[allow(dead_code)]
776 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
777 pub enum V4l2Colorspace {
778     /// 默认颜色空间,即让驱动程序自行判断。只能用于视频捕获。
779     #[default]
780     Default = 0,
781     /// SMPTE 170M:用于广播NTSC/PAL SDTV
782     Smpte170m = 1,
783     /// 过时的1998年前的SMPTE 240M HDTV标准,已被Rec 709取代
784     Smpte240m = 2,
785     /// Rec.709:用于HDTV
786     Rec709 = 3,
787     /// 已弃用,不要使用。没有驱动程序会返回这个。这是基于对bt878数据表的误解。
788     Bt878 = 4,
789     /// NTSC 1953颜色空间。只有在处理非常非常旧的NTSC录音时才有意义。已被SMPTE 170M取代。
790     System470M = 5,
791     /// EBU Tech 3213 PAL/SECAM颜色空间。
792     System470Bg = 6,
793     /// 实际上是V4L2_COLORSPACE_SRGB,V4L2_YCBCR_ENC_601和V4L2_QUANTIZATION_FULL_RANGE的简写。用于(Motion-)JPEG。
794     Jpeg = 7,
795     /// 用于RGB颜色空间,如大多数网络摄像头所产生的。
796     Srgb = 8,
797     /// opRGB颜色空间
798     Oprgb = 9,
799     /// BT.2020颜色空间,用于UHDTV。
800     Bt2020 = 10,
801     /// Raw颜色空间:用于RAW未处理的图像
802     Raw = 11,
803     /// DCI-P3颜色空间,用于电影投影机
804     DciP3 = 12,
805 
806     /// Largest supported colorspace value, assigned by the compiler, used
807     /// by the framework to check for invalid values.
808     Last,
809 }
810 
811 /// `FixedScreenInfo` 结构体用于描述屏幕的固定属性。
812 #[allow(dead_code)]
813 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
814 pub struct FixedScreenInfo {
815     // 字符串,用于标识屏幕,例如 "TT Builtin"
816     pub id: [char; 16],
817     // 帧缓冲区的起始物理地址
818     pub smem_start: Option<PhysAddr>,
819     // 帧缓冲区的长度
820     pub smem_len: usize,
821     // 屏幕类型,参考 FB_TYPE_
822     pub fb_type: FbType,
823     // 用于表示交错平面的小端辅助类型
824     pub type_aux: u32,
825     // 视觉类型,参考 FB_VISUAL_
826     pub visual: FbVisual,
827     // 水平缩放步长,如果无硬件缩放,则为0
828     pub xpanstep: u16,
829     // 垂直缩放步长,如果无硬件缩放,则为0
830     pub ypanstep: u16,
831     // 垂直环绕步长,如果无硬件环绕,则为0
832     pub ywrapstep: u16,
833     // 一行的大小(以字节为单位)
834     pub line_length: u32,
835     // 内存映射I/O端口的起始物理地址
836     pub mmio_start: Option<PhysAddr>,
837     // 内存映射I/O的长度
838     pub mmio_len: usize,
839     // 表示驱动器拥有的特定芯片/卡片类型
840     pub accel: FbAccel,
841     // 表示支持的特性,参考 FB_CAP_
842     pub capabilities: FbCapability,
843 }
844 
845 impl FixedScreenInfo {
846     /// 将字符串转换为长度为16的字符数组(包含结尾的`\0`)
847     ///
848     /// ## 参数
849     ///
850     /// - `name`: 字符串,长度不超过15,超过的部分将被截断
851     ///
852     /// ## 返回
853     ///
854     /// 长度为16的字符数组
name2id(name: &str) -> [char; 16]855     pub const fn name2id(name: &str) -> [char; 16] {
856         let mut id = [0u8 as char; 16];
857         let mut i = 0;
858 
859         while i < 15 && i < name.len() {
860             id[i] = name.as_bytes()[i] as char;
861             i += 1;
862         }
863 
864         id[i] = '\0';
865         return id;
866     }
867 }
868 
869 impl Default for FixedScreenInfo {
default() -> Self870     fn default() -> Self {
871         Self {
872             id: Default::default(),
873             smem_start: None,
874             smem_len: Default::default(),
875             fb_type: FbType::PackedPixels,
876             type_aux: Default::default(),
877             visual: FbVisual::Mono10,
878             xpanstep: Default::default(),
879             ypanstep: Default::default(),
880             ywrapstep: Default::default(),
881             line_length: Default::default(),
882             mmio_start: None,
883             mmio_len: Default::default(),
884             accel: Default::default(),
885             capabilities: Default::default(),
886         }
887     }
888 }
889 
890 /// 帧缓冲类型
891 #[allow(dead_code)]
892 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
893 pub enum FbType {
894     /// 压缩像素
895     PackedPixels = 0,
896     /// 非交错平面
897     Planes = 1,
898     /// 交错平面
899     InterleavedPlanes = 2,
900     /// 文本/属性
901     Text = 3,
902     /// EGA/VGA平面
903     VgaPlanes = 4,
904     /// 由V4L2 FOURCC标识的类型
905     FourCC = 5,
906 }
907 
908 /// 帧缓冲视觉类型
909 #[allow(dead_code)]
910 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
911 pub enum FbVisual {
912     /// 单色。1=黑色 0=白色
913     Mono01 = 0,
914     /// 单色。1=白色 0=黑色
915     Mono10 = 1,
916     /// 真彩色
917     TrueColor = 2,
918     /// 伪彩色(如Atari)
919     PseudoColor = 3,
920     /// 直接颜色
921     DirectColor = 4,
922     /// 只读的伪彩色
923     StaticPseudoColor = 5,
924     /// 由FOURCC标识的类型
925     FourCC,
926 }
927 
928 #[allow(dead_code)]
929 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
930 pub enum FbCapability {
931     #[default]
932     Default = 0,
933     /// 设备支持基于FOURCC的格式。
934     FourCC,
935 }
936 
937 /// 视频模式
938 #[allow(dead_code)]
939 #[derive(Debug, Clone, Eq, PartialEq)]
940 pub struct FbVideoMode {
941     /// 可选的名称
942     pub name: Option<String>,
943     /// 可选的刷新率
944     pub refresh: Option<u32>,
945     /// 水平分辨率
946     pub xres: u32,
947     /// 垂直分辨率
948     pub yres: u32,
949     /// 像素时钟
950     pub pixclock: u32,
951     /// 左边距
952     pub left_margin: u32,
953     /// 右边距
954     pub right_margin: u32,
955     /// 上边距
956     pub upper_margin: u32,
957     /// 下边距
958     pub lower_margin: u32,
959     /// 水平同步长度
960     pub hsync_len: u32,
961     /// 垂直同步长度
962     pub vsync_len: u32,
963     /// 同步
964     pub sync: FbSyncFlags,
965     /// 视频模式
966     pub vmode: FbVModeFlags,
967     /// 标志
968     pub flag: u32,
969 }
970 
971 #[allow(dead_code)]
972 #[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
973 pub enum FbAccel {
974     /// 没有硬件加速器
975     #[default]
976     None,
977 
978     AtariBlitter = 1,
979     AmigaBlitter = 2,
980     S3Trio64 = 3,
981     NCR77C32BLT = 4,
982     S3Virge = 5,
983     AtiMach64GX = 6,
984     DECTGA = 7,
985     AtiMach64CT = 8,
986     AtiMach64VT = 9,
987     AtiMach64GT = 10,
988     SunCreator = 11,
989     SunCGSix = 12,
990     SunLeo = 13,
991     IMSTwinTurbo = 14,
992     Acc3DLabsPermedia2 = 15,
993     MatroxMGA2064W = 16,
994     MatroxMGA1064SG = 17,
995     MatroxMGA2164W = 18,
996     MatroxMGA2164WAGP = 19,
997     MatroxMGAG400 = 20,
998     NV3 = 21,
999     NV4 = 22,
1000     NV5 = 23,
1001     NV6 = 24,
1002     XGIVolariV = 25,
1003     XGIVolariZ = 26,
1004     Omap1610 = 27,
1005     TridentTGUI = 28,
1006     Trident3DImage = 29,
1007     TridentBlade3D = 30,
1008     TridentBladeXP = 31,
1009     CirrusAlpine = 32,
1010     NeoMagicNM2070 = 90,
1011     NeoMagicNM2090 = 91,
1012     NeoMagicNM2093 = 92,
1013     NeoMagicNM2097 = 93,
1014     NeoMagicNM2160 = 94,
1015     NeoMagicNM2200 = 95,
1016     NeoMagicNM2230 = 96,
1017     NeoMagicNM2360 = 97,
1018     NeoMagicNM2380 = 98,
1019     PXA3XX = 99,
1020 
1021     Savage4 = 0x80,
1022     Savage3D = 0x81,
1023     Savage3DMV = 0x82,
1024     Savage2000 = 0x83,
1025     SavageMXMV = 0x84,
1026     SavageMX = 0x85,
1027     SavageIXMV = 0x86,
1028     SavageIX = 0x87,
1029     ProSavagePM = 0x88,
1030     ProSavageKM = 0x89,
1031     S3Twister = 0x8a,
1032     S3TwisterK = 0x8b,
1033     SuperSavage = 0x8c,
1034     ProSavageDDR = 0x8d,
1035     ProSavageDDRK = 0x8e,
1036     // Add other accelerators here
1037 }
1038 
1039 #[allow(dead_code)]
1040 #[derive(Debug, Copy, Clone)]
1041 pub struct BootTimeScreenInfo {
1042     pub origin_x: u8,
1043     pub origin_y: u8,
1044     /// text mode时,每行的字符数
1045     pub origin_video_cols: u8,
1046     /// text mode时,行数
1047     pub origin_video_lines: u8,
1048     /// 标记屏幕是否为VGA类型
1049     pub is_vga: bool,
1050     /// video mode type
1051     pub video_type: BootTimeVideoType,
1052 
1053     // 以下字段用于线性帧缓冲区
1054     /// 线性帧缓冲区的起始物理地址
1055     pub lfb_base: PhysAddr,
1056     /// 线性帧缓冲区在初始化阶段被映射到的起始虚拟地址
1057     ///
1058     /// 这个值可能会被设置2次:
1059     ///
1060     /// - 内存管理初始化之前,early init阶段,临时映射
1061     /// - 内存管理初始化完毕,重新映射时被设置
1062     pub lfb_virt_base: Option<VirtAddr>,
1063     /// 线性帧缓冲区的长度
1064     pub lfb_size: usize,
1065     /// 线性帧缓冲区的宽度(像素)
1066     pub lfb_width: u32,
1067     /// 线性帧缓冲区的高度(像素)
1068     pub lfb_height: u32,
1069     /// 线性帧缓冲区的深度(位数)
1070     pub lfb_depth: u8,
1071     /// 红色位域的大小
1072     pub red_size: u8,
1073     /// 红色位域的偏移量(左移位数)
1074     pub red_pos: u8,
1075     /// 绿色位域的大小
1076     pub green_size: u8,
1077     /// 绿色位域的偏移量(左移位数)
1078     pub green_pos: u8,
1079     /// 蓝色位域的大小
1080     pub blue_size: u8,
1081     /// 蓝色位域的偏移量(左移位数)
1082     pub blue_pos: u8,
1083 }
1084 
1085 impl BootTimeScreenInfo {
1086     pub const DEFAULT: Self = Self {
1087         origin_x: 0,
1088         origin_y: 0,
1089         is_vga: false,
1090         lfb_base: PhysAddr::new(0),
1091         lfb_size: 0,
1092         lfb_width: 0,
1093         lfb_height: 0,
1094         red_size: 0,
1095         red_pos: 0,
1096         green_size: 0,
1097         green_pos: 0,
1098         blue_size: 0,
1099         blue_pos: 0,
1100         video_type: BootTimeVideoType::UnDefined,
1101         origin_video_cols: 0,
1102         origin_video_lines: 0,
1103         lfb_virt_base: None,
1104         lfb_depth: 0,
1105     };
1106 }
1107 
1108 /// Video types for different display hardware
1109 #[allow(dead_code)]
1110 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
1111 pub enum BootTimeVideoType {
1112     UnDefined,
1113     /// Monochrome Text Display
1114     Mda,
1115     /// CGA Display
1116     Cga,
1117     /// EGA/VGA in Monochrome Mode
1118     EgaM,
1119     /// EGA in Color Mode
1120     EgaC,
1121     /// VGA+ in Color Mode
1122     VgaC,
1123     /// VESA VGA in graphic mode
1124     Vlfb,
1125     /// ACER PICA-61 local S3 video
1126     PicaS3,
1127     /// MIPS Magnum 4000 G364 video
1128     MipsG364,
1129     /// Various SGI graphics hardware
1130     Sgi,
1131     /// DEC TGA
1132     TgaC,
1133     /// Sun frame buffer
1134     Sun,
1135     /// Sun PCI based frame buffer
1136     SunPci,
1137     /// PowerMacintosh frame buffer
1138     Pmac,
1139     /// EFI graphic mode
1140     Efi,
1141 }
1142 
1143 impl From<u8> for BootTimeVideoType {
from(value: u8) -> Self1144     fn from(value: u8) -> Self {
1145         match value {
1146             0 => BootTimeVideoType::UnDefined,
1147             0x10 => BootTimeVideoType::Mda,
1148             0x11 => BootTimeVideoType::Cga,
1149             0x20 => BootTimeVideoType::EgaM,
1150             0x21 => BootTimeVideoType::EgaC,
1151             0x22 => BootTimeVideoType::VgaC,
1152             0x23 => BootTimeVideoType::Vlfb,
1153             0x30 => BootTimeVideoType::PicaS3,
1154             0x31 => BootTimeVideoType::MipsG364,
1155             0x33 => BootTimeVideoType::Sgi,
1156             0x40 => BootTimeVideoType::TgaC,
1157             0x50 => BootTimeVideoType::Sun,
1158             0x51 => BootTimeVideoType::SunPci,
1159             0x60 => BootTimeVideoType::Pmac,
1160             0x70 => BootTimeVideoType::Efi,
1161 
1162             _ => BootTimeVideoType::UnDefined,
1163         }
1164     }
1165 }
1166 
1167 #[derive(Debug, Default)]
1168 pub struct FbCursor {
1169     /// 设置选项
1170     pub set_mode: FbCursorSetMode,
1171     /// 开关选项
1172     pub enable: bool,
1173     /// 表示光标图像的位操作,true表示XOR,false表示COPY
1174     pub rop: bool,
1175     /// 表示光标掩码(mask)的数据。掩码用于定义光标的形状,指定了哪些像素是光标的一部分。
1176     pub mask: Vec<u8>,
1177 
1178     /// 表示光标的热点位置,即在光标图像中被认为是"焦点"的位置
1179     pub hot_x: u32,
1180     pub hot_y: u32,
1181 
1182     /// 光标图像
1183     pub image: FbImage,
1184 }
1185 
1186 bitflags! {
1187     /// 硬件光标控制
1188     #[derive(Default)]
1189     pub struct FbCursorSetMode:u8 {
1190         /// 设置位图
1191         const FB_CUR_SETIMAGE = 0x01;
1192         /// 设置位置
1193         const FB_CUR_SETPOS   = 0x02;
1194         /// 设置热点
1195         const FB_CUR_SETHOT   = 0x04;
1196         /// ColorMap
1197         const FB_CUR_SETCMAP  = 0x08;
1198         /// 形状
1199         const FB_CUR_SETSHAPE = 0x10;
1200         /// Size
1201         const FB_CUR_SETSIZE  = 0x20;
1202         /// 全设置
1203         const FB_CUR_SETALL   = 0xFF;
1204     }
1205 }
1206 
1207 #[allow(dead_code)]
1208 #[derive(Debug, Clone, Copy)]
1209 pub enum ScrollMode {
1210     Move,
1211     PanMove,
1212     WrapMove,
1213     Redraw,
1214     PanRedraw,
1215 }
1216 
1217 impl Default for ScrollMode {
1218     /// ## 默认Move
default() -> Self1219     fn default() -> Self {
1220         Self::Move
1221     }
1222 }
1223 
1224 #[derive(Debug, Default, Clone)]
1225 pub struct FbImage {
1226     pub x: u32,
1227     pub y: u32,
1228     pub width: u32,
1229     pub height: u32,
1230     pub fg: u32,
1231     pub bg: u32,
1232     pub depth: u8,
1233     pub data: Vec<u8>,
1234 }
1235