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