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