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