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