xref: /DragonOS/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
152da9a59SGnoCiYeH use alloc::{sync::Arc, vec::Vec};
2*2eab6dd7S曾俊 use log::warn;
352da9a59SGnoCiYeH use system_error::SystemError;
452da9a59SGnoCiYeH 
552da9a59SGnoCiYeH use crate::{
652da9a59SGnoCiYeH     driver::{
752da9a59SGnoCiYeH         tty::{
852da9a59SGnoCiYeH             console::ConsoleSwitch,
952da9a59SGnoCiYeH             virtual_terminal::{
1052da9a59SGnoCiYeH                 virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData},
1152da9a59SGnoCiYeH                 Color,
1252da9a59SGnoCiYeH             },
1352da9a59SGnoCiYeH         },
1452da9a59SGnoCiYeH         video::fbdev::base::{
1552da9a59SGnoCiYeH             CopyAreaData, FbCursor, FbCursorSetMode, FbImage, FbVisual, FillRectData, FillRectROP,
1652da9a59SGnoCiYeH             FrameBuffer, ScrollMode, FRAME_BUFFER_SET,
1752da9a59SGnoCiYeH         },
1852da9a59SGnoCiYeH     },
1952da9a59SGnoCiYeH     libs::{
2052da9a59SGnoCiYeH         font::FontDesc,
2152da9a59SGnoCiYeH         spinlock::{SpinLock, SpinLockGuard},
2252da9a59SGnoCiYeH     },
2352da9a59SGnoCiYeH };
2452da9a59SGnoCiYeH 
2552da9a59SGnoCiYeH use super::{FbConAttr, FrameBufferConsole, FrameBufferConsoleData};
2652da9a59SGnoCiYeH 
2752da9a59SGnoCiYeH #[derive(Debug)]
2852da9a59SGnoCiYeH pub struct BlittingFbConsole {
2952da9a59SGnoCiYeH     fb: SpinLock<Option<Arc<dyn FrameBuffer>>>,
3052da9a59SGnoCiYeH     fbcon_data: SpinLock<FrameBufferConsoleData>,
3152da9a59SGnoCiYeH }
3252da9a59SGnoCiYeH 
3352da9a59SGnoCiYeH unsafe impl Send for BlittingFbConsole {}
3452da9a59SGnoCiYeH unsafe impl Sync for BlittingFbConsole {}
3552da9a59SGnoCiYeH 
3652da9a59SGnoCiYeH impl BlittingFbConsole {
new() -> Result<Self, SystemError>3752da9a59SGnoCiYeH     pub fn new() -> Result<Self, SystemError> {
3852da9a59SGnoCiYeH         Ok(Self {
3952da9a59SGnoCiYeH             fb: SpinLock::new(None),
4052da9a59SGnoCiYeH             fbcon_data: SpinLock::new(FrameBufferConsoleData::default()),
4152da9a59SGnoCiYeH         })
4252da9a59SGnoCiYeH     }
4352da9a59SGnoCiYeH 
fb(&self) -> Arc<dyn FrameBuffer>44418ad41fSLoGin     fn fb(&self) -> Arc<dyn FrameBuffer> {
4552da9a59SGnoCiYeH         self.fb.lock().clone().unwrap()
4652da9a59SGnoCiYeH     }
4752da9a59SGnoCiYeH 
get_color(&self, vc_data: &VirtualConsoleData, c: u16, is_fg: bool) -> u3248418ad41fSLoGin     fn get_color(&self, vc_data: &VirtualConsoleData, c: u16, is_fg: bool) -> u32 {
4952da9a59SGnoCiYeH         let fb_info = self.fb();
5052da9a59SGnoCiYeH         let mut color = 0;
5152da9a59SGnoCiYeH 
5252da9a59SGnoCiYeH         let depth = fb_info.color_depth();
5352da9a59SGnoCiYeH 
5452da9a59SGnoCiYeH         if depth != 1 {
5552da9a59SGnoCiYeH             if is_fg {
5652da9a59SGnoCiYeH                 let fg_shift = if vc_data.hi_font_mask != 0 { 9 } else { 8 };
5752da9a59SGnoCiYeH                 color = (c as u32 >> fg_shift) & 0x0f
5852da9a59SGnoCiYeH             } else {
5952da9a59SGnoCiYeH                 let bg_shift = if vc_data.hi_font_mask != 0 { 13 } else { 12 };
6052da9a59SGnoCiYeH                 color = (c as u32 >> bg_shift) & 0x0f
6152da9a59SGnoCiYeH             }
6252da9a59SGnoCiYeH         }
6352da9a59SGnoCiYeH 
6452da9a59SGnoCiYeH         match depth {
6552da9a59SGnoCiYeH             1 => {
6652da9a59SGnoCiYeH                 let col = self.mono_color();
6752da9a59SGnoCiYeH                 let fg;
6852da9a59SGnoCiYeH                 let bg;
6952da9a59SGnoCiYeH                 if fb_info.current_fb_fix().visual != FbVisual::Mono01 {
7052da9a59SGnoCiYeH                     fg = col;
7152da9a59SGnoCiYeH                     bg = 0;
7252da9a59SGnoCiYeH                 } else {
7352da9a59SGnoCiYeH                     fg = 0;
7452da9a59SGnoCiYeH                     bg = col;
7552da9a59SGnoCiYeH                 }
7652da9a59SGnoCiYeH                 color = if is_fg { fg } else { bg };
7752da9a59SGnoCiYeH             }
7852da9a59SGnoCiYeH             2 => {
7952da9a59SGnoCiYeH                 /*
8052da9a59SGnoCiYeH                     颜色深度为2,即16色,
8152da9a59SGnoCiYeH                    将16色的颜色值映射到4色的灰度,
8252da9a59SGnoCiYeH                    其中颜色0映射为黑色,颜色1到6映射为白色,
8352da9a59SGnoCiYeH                    颜色7到8映射为灰色,其他颜色映射为强烈的白色。
8452da9a59SGnoCiYeH                 */
85b5b571e0SLoGin                 if (1..=6).contains(&color) {
8652da9a59SGnoCiYeH                     // 白色
8752da9a59SGnoCiYeH                     color = 2;
88b5b571e0SLoGin                 } else if (7..=8).contains(&color) {
8952da9a59SGnoCiYeH                     // 灰色
9052da9a59SGnoCiYeH                     color = 1;
9152da9a59SGnoCiYeH                 } else {
9252da9a59SGnoCiYeH                     // 强白
9352da9a59SGnoCiYeH                     color = 3;
9452da9a59SGnoCiYeH                 }
9552da9a59SGnoCiYeH             }
9652da9a59SGnoCiYeH             3 => {
9752da9a59SGnoCiYeH                 /*
9852da9a59SGnoCiYeH                    颜色深度为3,即256色,仅保留颜色的低3位,即颜色 0 到 7
9952da9a59SGnoCiYeH                 */
10052da9a59SGnoCiYeH                 color &= 7;
10152da9a59SGnoCiYeH             }
10252da9a59SGnoCiYeH             _ => {}
10352da9a59SGnoCiYeH         }
10452da9a59SGnoCiYeH         color
10552da9a59SGnoCiYeH     }
10652da9a59SGnoCiYeH 
10752da9a59SGnoCiYeH     /// ## 计算单色调的函数
mono_color(&self) -> u32108418ad41fSLoGin     fn mono_color(&self) -> u32 {
10952da9a59SGnoCiYeH         let fb_info = self.fb();
11052da9a59SGnoCiYeH         let mut max_len = fb_info
11152da9a59SGnoCiYeH             .current_fb_var()
11252da9a59SGnoCiYeH             .green
11352da9a59SGnoCiYeH             .length
11452da9a59SGnoCiYeH             .max(fb_info.current_fb_var().red.length);
11552da9a59SGnoCiYeH 
11652da9a59SGnoCiYeH         max_len = max_len.max(fb_info.current_fb_var().blue.length);
11752da9a59SGnoCiYeH 
11852da9a59SGnoCiYeH         return (!(0xfff << max_len)) & 0xff;
11952da9a59SGnoCiYeH     }
12052da9a59SGnoCiYeH 
bit_put_string( &self, vc_data: &VirtualConsoleData, buf: &[u16], attr: FbConAttr, cnt: u32, cellsize: u32, image: &mut FbImage, )121418ad41fSLoGin     fn bit_put_string(
12252da9a59SGnoCiYeH         &self,
12352da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
12452da9a59SGnoCiYeH         buf: &[u16],
12552da9a59SGnoCiYeH         attr: FbConAttr,
12652da9a59SGnoCiYeH         cnt: u32,
12752da9a59SGnoCiYeH         cellsize: u32,
12852da9a59SGnoCiYeH         image: &mut FbImage,
12952da9a59SGnoCiYeH     ) {
13052da9a59SGnoCiYeH         let charmask = if vc_data.hi_font_mask != 0 {
13152da9a59SGnoCiYeH             0x1ff
13252da9a59SGnoCiYeH         } else {
13352da9a59SGnoCiYeH             0xff
13452da9a59SGnoCiYeH         };
13552da9a59SGnoCiYeH 
13652da9a59SGnoCiYeH         let mut offset;
13752da9a59SGnoCiYeH         let image_line_byte = image.width as usize / 8;
13852da9a59SGnoCiYeH 
13952da9a59SGnoCiYeH         let byte_width = vc_data.font.width as usize / 8;
14052da9a59SGnoCiYeH         let font_height = vc_data.font.height as usize;
14152da9a59SGnoCiYeH         // let mut char_offset = 0;
142b5b571e0SLoGin         for (char_offset, char_item) in buf.iter().enumerate().take(cnt as usize) {
14352da9a59SGnoCiYeH             // 在字符表中的index
144b5b571e0SLoGin             let ch = char_item & charmask;
14552da9a59SGnoCiYeH             // 计算出在font表中的偏移量
14652da9a59SGnoCiYeH             let font_offset = ch as usize * cellsize as usize;
14752da9a59SGnoCiYeH             let font_offset_end = font_offset + cellsize as usize;
14852da9a59SGnoCiYeH             // 设置image的data
14952da9a59SGnoCiYeH 
15052da9a59SGnoCiYeH             let src = &vc_data.font.data[font_offset..font_offset_end];
151b5b571e0SLoGin             let mut dst = vec![0; src.len()];
15252da9a59SGnoCiYeH             dst.copy_from_slice(src);
15352da9a59SGnoCiYeH 
15452da9a59SGnoCiYeH             if !attr.is_empty() {
15552da9a59SGnoCiYeH                 attr.update_attr(&mut dst, src, vc_data)
15652da9a59SGnoCiYeH             }
15752da9a59SGnoCiYeH 
15852da9a59SGnoCiYeH             offset = char_offset * byte_width;
15952da9a59SGnoCiYeH             let mut dst_offset = 0;
16052da9a59SGnoCiYeH             for _ in 0..font_height {
16152da9a59SGnoCiYeH                 let dst_offset_next = dst_offset + byte_width;
16252da9a59SGnoCiYeH                 image.data[offset..offset + byte_width]
16352da9a59SGnoCiYeH                     .copy_from_slice(&dst[dst_offset..dst_offset_next]);
16452da9a59SGnoCiYeH 
16552da9a59SGnoCiYeH                 offset += image_line_byte;
16652da9a59SGnoCiYeH                 dst_offset = dst_offset_next;
16752da9a59SGnoCiYeH             }
16852da9a59SGnoCiYeH         }
16952da9a59SGnoCiYeH 
17052da9a59SGnoCiYeH         self.fb().fb_image_blit(image);
17152da9a59SGnoCiYeH     }
17252da9a59SGnoCiYeH }
17352da9a59SGnoCiYeH 
17452da9a59SGnoCiYeH impl ConsoleSwitch for BlittingFbConsole {
con_init( &self, vc_data: &mut VirtualConsoleData, init: bool, ) -> Result<(), system_error::SystemError>17552da9a59SGnoCiYeH     fn con_init(
17652da9a59SGnoCiYeH         &self,
17752da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
17852da9a59SGnoCiYeH         init: bool,
17952da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
18052da9a59SGnoCiYeH         let fb_set_guard = FRAME_BUFFER_SET.read();
18152da9a59SGnoCiYeH         let fb = fb_set_guard.get(vc_data.index);
18252da9a59SGnoCiYeH         if fb.is_none() {
18352da9a59SGnoCiYeH             return Err(SystemError::EINVAL);
18452da9a59SGnoCiYeH         }
18552da9a59SGnoCiYeH         let fb = fb.unwrap();
18652da9a59SGnoCiYeH         if fb.is_none() {
18752da9a59SGnoCiYeH             panic!(
18852da9a59SGnoCiYeH                 "The Framebuffer with FbID {} has not been initialized yet.",
18952da9a59SGnoCiYeH                 vc_data.index
19052da9a59SGnoCiYeH             )
19152da9a59SGnoCiYeH         }
19252da9a59SGnoCiYeH 
19352da9a59SGnoCiYeH         let fb = fb.as_ref().unwrap().clone();
19452da9a59SGnoCiYeH 
19552da9a59SGnoCiYeH         if init {
19652da9a59SGnoCiYeH             // 初始化字体
19752da9a59SGnoCiYeH             let var = fb.current_fb_var();
19852da9a59SGnoCiYeH             let font = FontDesc::get_default_font(var.xres, var.yres, 0, 0);
19952da9a59SGnoCiYeH             vc_data.font.data = font.data.to_vec();
20052da9a59SGnoCiYeH             vc_data.font.width = font.width;
20152da9a59SGnoCiYeH             vc_data.font.height = font.height;
20252da9a59SGnoCiYeH             vc_data.font.count = font.char_count;
20352da9a59SGnoCiYeH         } else {
204*2eab6dd7S曾俊             warn!("The frontend Framebuffer is not implemented");
20552da9a59SGnoCiYeH         }
20652da9a59SGnoCiYeH 
20752da9a59SGnoCiYeH         vc_data.color_mode = fb.color_depth() != 1;
20852da9a59SGnoCiYeH         vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
20952da9a59SGnoCiYeH 
21052da9a59SGnoCiYeH         if vc_data.font.count == 256 {
21152da9a59SGnoCiYeH             // ascii
21252da9a59SGnoCiYeH             vc_data.hi_font_mask = 0;
21352da9a59SGnoCiYeH         } else {
21452da9a59SGnoCiYeH             vc_data.hi_font_mask = 0x100;
21552da9a59SGnoCiYeH             if vc_data.color_mode {
21652da9a59SGnoCiYeH                 vc_data.complement_mask <<= 1;
21752da9a59SGnoCiYeH             }
21852da9a59SGnoCiYeH         }
21952da9a59SGnoCiYeH 
22052da9a59SGnoCiYeH         // TODO: 考虑rotate
22152da9a59SGnoCiYeH         if init {
22252da9a59SGnoCiYeH             vc_data.cols = (fb.current_fb_var().xres / vc_data.font.width) as usize;
22352da9a59SGnoCiYeH             vc_data.rows = (fb.current_fb_var().yres / vc_data.font.height) as usize;
22452da9a59SGnoCiYeH 
22552da9a59SGnoCiYeH             vc_data.pos = vc_data.state.x + vc_data.state.y * vc_data.cols;
22652da9a59SGnoCiYeH 
22752da9a59SGnoCiYeH             let new_size = vc_data.cols * vc_data.rows;
22852da9a59SGnoCiYeH             vc_data.screen_buf.resize(new_size, 0);
22952da9a59SGnoCiYeH         } else {
23052da9a59SGnoCiYeH             unimplemented!("Resize is not supported at the moment!");
23152da9a59SGnoCiYeH         }
23252da9a59SGnoCiYeH 
23352da9a59SGnoCiYeH         // 初始化fb
23452da9a59SGnoCiYeH         *self.fb.lock() = Some(fb);
23552da9a59SGnoCiYeH 
23652da9a59SGnoCiYeH         Ok(())
23752da9a59SGnoCiYeH     }
23852da9a59SGnoCiYeH 
con_deinit(&self) -> Result<(), system_error::SystemError>23952da9a59SGnoCiYeH     fn con_deinit(&self) -> Result<(), system_error::SystemError> {
24052da9a59SGnoCiYeH         todo!()
24152da9a59SGnoCiYeH     }
24252da9a59SGnoCiYeH 
con_clear( &self, vc_data: &mut VirtualConsoleData, sy: usize, sx: usize, height: usize, width: usize, ) -> Result<(), system_error::SystemError>24352da9a59SGnoCiYeH     fn con_clear(
24452da9a59SGnoCiYeH         &self,
24552da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
24652da9a59SGnoCiYeH         sy: usize,
24752da9a59SGnoCiYeH         sx: usize,
24852da9a59SGnoCiYeH         height: usize,
24952da9a59SGnoCiYeH         width: usize,
25052da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
25152da9a59SGnoCiYeH         let fb_data = self.fbcon_data();
25252da9a59SGnoCiYeH 
25352da9a59SGnoCiYeH         if height == 0 || width == 0 {
25452da9a59SGnoCiYeH             return Ok(());
25552da9a59SGnoCiYeH         }
25652da9a59SGnoCiYeH 
25752da9a59SGnoCiYeH         let y_break = (fb_data.display.virt_rows - fb_data.display.yscroll) as usize;
258b5b571e0SLoGin         if sy < y_break && sy + height > y_break {
25952da9a59SGnoCiYeH             // 分两次clear
26052da9a59SGnoCiYeH             let b = y_break - sy;
26152da9a59SGnoCiYeH             let _ = self.clear(
262b5b571e0SLoGin                 vc_data,
26352da9a59SGnoCiYeH                 fb_data.display.real_y(sy as u32),
26452da9a59SGnoCiYeH                 sx as u32,
26552da9a59SGnoCiYeH                 b as u32,
26652da9a59SGnoCiYeH                 width as u32,
26752da9a59SGnoCiYeH             );
26852da9a59SGnoCiYeH             let _ = self.clear(
269b5b571e0SLoGin                 vc_data,
27052da9a59SGnoCiYeH                 fb_data.display.real_y((sy + b) as u32),
27152da9a59SGnoCiYeH                 sx as u32,
27252da9a59SGnoCiYeH                 (height - b) as u32,
27352da9a59SGnoCiYeH                 width as u32,
27452da9a59SGnoCiYeH             );
27552da9a59SGnoCiYeH         } else {
27652da9a59SGnoCiYeH             let _ = self.clear(
277b5b571e0SLoGin                 vc_data,
27852da9a59SGnoCiYeH                 fb_data.display.real_y(sy as u32),
27952da9a59SGnoCiYeH                 sx as u32,
28052da9a59SGnoCiYeH                 height as u32,
28152da9a59SGnoCiYeH                 width as u32,
28252da9a59SGnoCiYeH             );
28352da9a59SGnoCiYeH         }
28452da9a59SGnoCiYeH 
28552da9a59SGnoCiYeH         Ok(())
28652da9a59SGnoCiYeH     }
28752da9a59SGnoCiYeH 
con_putc( &self, vc_data: &VirtualConsoleData, ch: u16, xpos: u32, ypos: u32, ) -> Result<(), system_error::SystemError>28852da9a59SGnoCiYeH     fn con_putc(
28952da9a59SGnoCiYeH         &self,
29052da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
29152da9a59SGnoCiYeH         ch: u16,
29252da9a59SGnoCiYeH         xpos: u32,
29352da9a59SGnoCiYeH         ypos: u32,
29452da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
29552da9a59SGnoCiYeH         self.con_putcs(vc_data, &[ch], 1, ypos, xpos)
29652da9a59SGnoCiYeH     }
29752da9a59SGnoCiYeH 
con_putcs( &self, vc_data: &VirtualConsoleData, buf: &[u16], count: usize, ypos: u32, xpos: u32, ) -> Result<(), SystemError>29852da9a59SGnoCiYeH     fn con_putcs(
29952da9a59SGnoCiYeH         &self,
30052da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
30152da9a59SGnoCiYeH         buf: &[u16],
30252da9a59SGnoCiYeH         count: usize,
30352da9a59SGnoCiYeH         ypos: u32,
30452da9a59SGnoCiYeH         xpos: u32,
30552da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
30652da9a59SGnoCiYeH         if count == 0 {
30752da9a59SGnoCiYeH             return Ok(());
30852da9a59SGnoCiYeH         }
30952da9a59SGnoCiYeH         let fbcon_data = self.fbcon_data();
31052da9a59SGnoCiYeH         let c = buf[0];
31152da9a59SGnoCiYeH         self.put_string(
31252da9a59SGnoCiYeH             vc_data,
31352da9a59SGnoCiYeH             buf,
31452da9a59SGnoCiYeH             count as u32,
31552da9a59SGnoCiYeH             fbcon_data.display.real_y(ypos),
31652da9a59SGnoCiYeH             xpos,
31752da9a59SGnoCiYeH             self.get_color(vc_data, c, true),
31852da9a59SGnoCiYeH             self.get_color(vc_data, c, false),
31952da9a59SGnoCiYeH         )
32052da9a59SGnoCiYeH     }
32152da9a59SGnoCiYeH 
con_getxy( &self, vc_data: &VirtualConsoleData, pos: usize, ) -> Result<(usize, usize, usize), SystemError>32252da9a59SGnoCiYeH     fn con_getxy(
32352da9a59SGnoCiYeH         &self,
32452da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
32552da9a59SGnoCiYeH         pos: usize,
32652da9a59SGnoCiYeH     ) -> Result<(usize, usize, usize), SystemError> {
32752da9a59SGnoCiYeH         if pos < vc_data.screen_buf.len() {
32852da9a59SGnoCiYeH             let x = pos % vc_data.cols;
32952da9a59SGnoCiYeH             let y = pos / vc_data.cols;
33052da9a59SGnoCiYeH             let mut next_line_start = pos + (vc_data.cols - x);
33152da9a59SGnoCiYeH             if next_line_start >= vc_data.screen_buf.len() {
33252da9a59SGnoCiYeH                 next_line_start = 0
33352da9a59SGnoCiYeH             }
33452da9a59SGnoCiYeH             return Ok((next_line_start, x, y));
33552da9a59SGnoCiYeH         } else {
33652da9a59SGnoCiYeH             return Ok((0, 0, 0));
33752da9a59SGnoCiYeH         }
33852da9a59SGnoCiYeH     }
33952da9a59SGnoCiYeH 
340b5b571e0SLoGin     #[allow(clippy::if_same_then_else)]
con_cursor( &self, vc_data: &VirtualConsoleData, op: crate::driver::tty::virtual_terminal::virtual_console::CursorOperation, )34152da9a59SGnoCiYeH     fn con_cursor(
34252da9a59SGnoCiYeH         &self,
34352da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
34452da9a59SGnoCiYeH         op: crate::driver::tty::virtual_terminal::virtual_console::CursorOperation,
34552da9a59SGnoCiYeH     ) {
34652da9a59SGnoCiYeH         let mut fbcon_data = self.fbcon_data();
34752da9a59SGnoCiYeH 
34852da9a59SGnoCiYeH         let c = vc_data.screen_buf[vc_data.pos];
34952da9a59SGnoCiYeH 
35052da9a59SGnoCiYeH         if vc_data.cursor_type.contains(VcCursor::CUR_SW) {
35152da9a59SGnoCiYeH             // 取消硬光标Timer,但是现在没有硬光标,先写在这
35252da9a59SGnoCiYeH         } else {
35352da9a59SGnoCiYeH             // 添加硬光标Timer
35452da9a59SGnoCiYeH         }
35552da9a59SGnoCiYeH 
35652da9a59SGnoCiYeH         fbcon_data.cursor_flash = op != CursorOperation::Erase;
35752da9a59SGnoCiYeH 
35852da9a59SGnoCiYeH         drop(fbcon_data);
35952da9a59SGnoCiYeH 
36052da9a59SGnoCiYeH         self.cursor(
36152da9a59SGnoCiYeH             vc_data,
36252da9a59SGnoCiYeH             op,
36352da9a59SGnoCiYeH             self.get_color(vc_data, c, true),
36452da9a59SGnoCiYeH             self.get_color(vc_data, c, false),
36552da9a59SGnoCiYeH         );
36652da9a59SGnoCiYeH     }
36752da9a59SGnoCiYeH 
con_set_palette( &self, vc_data: &VirtualConsoleData, color_table: &[u8], ) -> Result<(), SystemError>36852da9a59SGnoCiYeH     fn con_set_palette(
36952da9a59SGnoCiYeH         &self,
37052da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
37152da9a59SGnoCiYeH         color_table: &[u8],
37252da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
37352da9a59SGnoCiYeH         let fb_info = self.fb();
37452da9a59SGnoCiYeH         let depth = fb_info.color_depth();
37552da9a59SGnoCiYeH         let mut palette = Vec::new();
37652da9a59SGnoCiYeH         palette.resize(16, Color::default());
37752da9a59SGnoCiYeH         if depth > 3 {
37852da9a59SGnoCiYeH             let vc_palette = &vc_data.palette;
37952da9a59SGnoCiYeH             for i in 0..16 {
38052da9a59SGnoCiYeH                 let idx = color_table[i];
38152da9a59SGnoCiYeH                 let col = palette.get_mut(idx as usize).unwrap();
38252da9a59SGnoCiYeH                 col.red = (vc_palette[i].red << 8) | vc_palette[i].red;
38352da9a59SGnoCiYeH                 col.green = (vc_palette[i].green << 8) | vc_palette[i].green;
38452da9a59SGnoCiYeH                 col.blue = (vc_palette[i].blue << 8) | vc_palette[i].blue;
38552da9a59SGnoCiYeH             }
38652da9a59SGnoCiYeH         } else {
38752da9a59SGnoCiYeH             todo!()
38852da9a59SGnoCiYeH         }
38952da9a59SGnoCiYeH 
39052da9a59SGnoCiYeH         self.fb().set_color_map(palette)?;
39152da9a59SGnoCiYeH 
39252da9a59SGnoCiYeH         Ok(())
39352da9a59SGnoCiYeH     }
39452da9a59SGnoCiYeH 
39552bcb59eSGnoCiYeH     #[inline(never)]
con_scroll( &self, vc_data: &mut VirtualConsoleData, top: usize, bottom: usize, dir: crate::driver::tty::virtual_terminal::virtual_console::ScrollDir, mut count: usize, ) -> bool39652da9a59SGnoCiYeH     fn con_scroll(
39752da9a59SGnoCiYeH         &self,
39852da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
39952da9a59SGnoCiYeH         top: usize,
40052da9a59SGnoCiYeH         bottom: usize,
40152da9a59SGnoCiYeH         dir: crate::driver::tty::virtual_terminal::virtual_console::ScrollDir,
40252da9a59SGnoCiYeH         mut count: usize,
40352da9a59SGnoCiYeH     ) -> bool {
40452da9a59SGnoCiYeH         self.con_cursor(vc_data, CursorOperation::Erase);
40552da9a59SGnoCiYeH 
40652da9a59SGnoCiYeH         let fbcon_data = self.fbcon_data();
40752da9a59SGnoCiYeH         let scroll_mode = fbcon_data.display.scroll_mode;
40852da9a59SGnoCiYeH 
40952da9a59SGnoCiYeH         drop(fbcon_data);
41052da9a59SGnoCiYeH 
41152da9a59SGnoCiYeH         match dir {
41252da9a59SGnoCiYeH             ScrollDir::Up => {
41352da9a59SGnoCiYeH                 if count > vc_data.rows {
41452da9a59SGnoCiYeH                     count = vc_data.rows;
41552da9a59SGnoCiYeH                 }
41652da9a59SGnoCiYeH 
41752da9a59SGnoCiYeH                 match scroll_mode {
41852da9a59SGnoCiYeH                     ScrollMode::Move => {
41952da9a59SGnoCiYeH                         let start = top * vc_data.cols;
42052da9a59SGnoCiYeH                         let end = bottom * vc_data.cols;
42152da9a59SGnoCiYeH                         vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
42252da9a59SGnoCiYeH 
42352da9a59SGnoCiYeH                         let _ = self.bmove(
42452da9a59SGnoCiYeH                             vc_data,
42552da9a59SGnoCiYeH                             top as i32,
42652da9a59SGnoCiYeH                             0,
42752da9a59SGnoCiYeH                             top as i32 - count as i32,
42852da9a59SGnoCiYeH                             0,
42952da9a59SGnoCiYeH                             (bottom - top) as u32,
43052da9a59SGnoCiYeH                             vc_data.cols as u32,
43152da9a59SGnoCiYeH                         );
43252da9a59SGnoCiYeH 
43352da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
43452da9a59SGnoCiYeH 
43552da9a59SGnoCiYeH                         let offset = vc_data.cols * (bottom - count);
43652da9a59SGnoCiYeH                         for i in
43752da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
43852da9a59SGnoCiYeH                         {
43952da9a59SGnoCiYeH                             *i = vc_data.erase_char;
44052da9a59SGnoCiYeH                         }
44152da9a59SGnoCiYeH 
44252da9a59SGnoCiYeH                         return true;
44352da9a59SGnoCiYeH                     }
44452da9a59SGnoCiYeH                     ScrollMode::PanMove => todo!(),
44552da9a59SGnoCiYeH                     ScrollMode::WrapMove => todo!(),
44652da9a59SGnoCiYeH                     ScrollMode::Redraw => {
44752da9a59SGnoCiYeH                         let start = top * vc_data.cols;
44852da9a59SGnoCiYeH                         let end = bottom * vc_data.cols;
44952da9a59SGnoCiYeH                         vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
45052da9a59SGnoCiYeH 
45152da9a59SGnoCiYeH                         let data = &vc_data.screen_buf[start..(bottom - count) * vc_data.cols];
45252da9a59SGnoCiYeH 
45352da9a59SGnoCiYeH                         for line in top..(bottom - count) {
45452da9a59SGnoCiYeH                             let mut start = line * vc_data.cols;
45552da9a59SGnoCiYeH                             let end = start + vc_data.cols;
45652da9a59SGnoCiYeH                             let mut offset = start;
45752da9a59SGnoCiYeH                             let mut attr = 1;
45852da9a59SGnoCiYeH                             let mut x = 0;
45952da9a59SGnoCiYeH                             while offset < end {
46052da9a59SGnoCiYeH                                 let c = data[offset];
46152da9a59SGnoCiYeH 
46252da9a59SGnoCiYeH                                 if attr != c & 0xff00 {
46352da9a59SGnoCiYeH                                     // 属性变化,输出完上一个的并且更新属性
46452da9a59SGnoCiYeH                                     attr = c & 0xff00;
46552da9a59SGnoCiYeH 
46652da9a59SGnoCiYeH                                     let count = offset - start;
46752da9a59SGnoCiYeH                                     let _ = self.con_putcs(
46852da9a59SGnoCiYeH                                         vc_data,
46952da9a59SGnoCiYeH                                         &data[start..offset],
47052da9a59SGnoCiYeH                                         count,
47152da9a59SGnoCiYeH                                         line as u32,
47252da9a59SGnoCiYeH                                         x,
47352da9a59SGnoCiYeH                                     );
47452da9a59SGnoCiYeH                                     start = offset;
47552da9a59SGnoCiYeH                                     x += count as u32;
47652da9a59SGnoCiYeH                                 }
47752da9a59SGnoCiYeH 
47852da9a59SGnoCiYeH                                 offset += 1;
47952da9a59SGnoCiYeH                             }
48052da9a59SGnoCiYeH                             let _ = self.con_putcs(
48152da9a59SGnoCiYeH                                 vc_data,
48252da9a59SGnoCiYeH                                 &data[start..offset],
48352da9a59SGnoCiYeH                                 offset - start,
48452da9a59SGnoCiYeH                                 line as u32,
48552da9a59SGnoCiYeH                                 x,
48652da9a59SGnoCiYeH                             );
48752da9a59SGnoCiYeH                         }
48852da9a59SGnoCiYeH 
48952da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
49052da9a59SGnoCiYeH 
49152da9a59SGnoCiYeH                         let offset = vc_data.cols * (bottom - count);
49252da9a59SGnoCiYeH                         for i in
49352da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
49452da9a59SGnoCiYeH                         {
49552da9a59SGnoCiYeH                             *i = vc_data.erase_char;
49652da9a59SGnoCiYeH                         }
49752da9a59SGnoCiYeH 
49852da9a59SGnoCiYeH                         return true;
49952da9a59SGnoCiYeH                     }
50052da9a59SGnoCiYeH                     ScrollMode::PanRedraw => todo!(),
50152da9a59SGnoCiYeH                 }
50252da9a59SGnoCiYeH             }
50352da9a59SGnoCiYeH             ScrollDir::Down => {
50452da9a59SGnoCiYeH                 if count > vc_data.rows {
50552da9a59SGnoCiYeH                     count = vc_data.rows;
50652da9a59SGnoCiYeH                 }
50752da9a59SGnoCiYeH 
50852da9a59SGnoCiYeH                 match scroll_mode {
50952bcb59eSGnoCiYeH                     ScrollMode::Move => {
51052bcb59eSGnoCiYeH                         let start = top * vc_data.cols;
51152bcb59eSGnoCiYeH                         let end = bottom * vc_data.cols;
51252bcb59eSGnoCiYeH                         vc_data.screen_buf[start..end].rotate_right(count * vc_data.cols);
51352bcb59eSGnoCiYeH 
51452bcb59eSGnoCiYeH                         let _ = self.bmove(
51552bcb59eSGnoCiYeH                             vc_data,
51652bcb59eSGnoCiYeH                             top as i32,
51752bcb59eSGnoCiYeH                             0,
51852bcb59eSGnoCiYeH                             top as i32 + count as i32,
51952bcb59eSGnoCiYeH                             0,
52052bcb59eSGnoCiYeH                             (bottom - top - count) as u32,
52152bcb59eSGnoCiYeH                             vc_data.cols as u32,
52252bcb59eSGnoCiYeH                         );
52352bcb59eSGnoCiYeH 
52452bcb59eSGnoCiYeH                         let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols);
52552bcb59eSGnoCiYeH 
52652bcb59eSGnoCiYeH                         let offset = vc_data.cols * count;
52752bcb59eSGnoCiYeH                         for i in vc_data.screen_buf[start..(start + offset)].iter_mut() {
52852bcb59eSGnoCiYeH                             *i = vc_data.erase_char;
52952bcb59eSGnoCiYeH                         }
53052bcb59eSGnoCiYeH 
53152bcb59eSGnoCiYeH                         return true;
53252bcb59eSGnoCiYeH                     }
53352da9a59SGnoCiYeH                     ScrollMode::PanMove => todo!(),
53452da9a59SGnoCiYeH                     ScrollMode::WrapMove => todo!(),
53552da9a59SGnoCiYeH                     ScrollMode::Redraw => {
53652da9a59SGnoCiYeH                         // self.scroll_redraw(
53752da9a59SGnoCiYeH                         //     vc_data,
53852da9a59SGnoCiYeH                         //     bottom - 1,
53952da9a59SGnoCiYeH                         //     bottom - top - count,
54052da9a59SGnoCiYeH                         //     count * vc_data.cols,
54152da9a59SGnoCiYeH                         //     false,
54252da9a59SGnoCiYeH                         // );
54352da9a59SGnoCiYeH 
54452da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols);
54552da9a59SGnoCiYeH 
54652da9a59SGnoCiYeH                         let offset = vc_data.cols * top;
54752da9a59SGnoCiYeH                         for i in
54852da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
54952da9a59SGnoCiYeH                         {
55052da9a59SGnoCiYeH                             *i = vc_data.erase_char;
55152da9a59SGnoCiYeH                         }
55252da9a59SGnoCiYeH 
55352da9a59SGnoCiYeH                         return true;
55452da9a59SGnoCiYeH                     }
55552da9a59SGnoCiYeH                     ScrollMode::PanRedraw => todo!(),
55652da9a59SGnoCiYeH                 }
55752da9a59SGnoCiYeH             }
55852da9a59SGnoCiYeH         }
55952da9a59SGnoCiYeH     }
56052da9a59SGnoCiYeH }
56152da9a59SGnoCiYeH 
56252da9a59SGnoCiYeH impl FrameBufferConsole for BlittingFbConsole {
bmove( &self, vc_data: &VirtualConsoleData, sy: i32, sx: i32, dy: i32, dx: i32, height: u32, width: u32, ) -> Result<(), SystemError>56352da9a59SGnoCiYeH     fn bmove(
56452da9a59SGnoCiYeH         &self,
56552da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
56652da9a59SGnoCiYeH         sy: i32,
56752da9a59SGnoCiYeH         sx: i32,
56852da9a59SGnoCiYeH         dy: i32,
56952da9a59SGnoCiYeH         dx: i32,
57052da9a59SGnoCiYeH         height: u32,
57152da9a59SGnoCiYeH         width: u32,
57252da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
57352da9a59SGnoCiYeH         let area = CopyAreaData::new(
57452da9a59SGnoCiYeH             dx * vc_data.font.width as i32,
57552da9a59SGnoCiYeH             dy * vc_data.font.height as i32,
57652da9a59SGnoCiYeH             width * vc_data.font.width,
57752da9a59SGnoCiYeH             height * vc_data.font.height,
57852da9a59SGnoCiYeH             sx * vc_data.font.width as i32,
57952da9a59SGnoCiYeH             sy * vc_data.font.height as i32,
58052da9a59SGnoCiYeH         );
58152da9a59SGnoCiYeH 
58252bcb59eSGnoCiYeH         self.fb().fb_copyarea(area);
58352bcb59eSGnoCiYeH         Ok(())
58452da9a59SGnoCiYeH     }
58552da9a59SGnoCiYeH 
clear( &self, vc_data: &VirtualConsoleData, sy: u32, sx: u32, height: u32, width: u32, ) -> Result<(), SystemError>58652da9a59SGnoCiYeH     fn clear(
58752da9a59SGnoCiYeH         &self,
58852da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
58952da9a59SGnoCiYeH         sy: u32,
59052da9a59SGnoCiYeH         sx: u32,
59152da9a59SGnoCiYeH         height: u32,
59252da9a59SGnoCiYeH         width: u32,
59352da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
59452da9a59SGnoCiYeH         let region = FillRectData::new(
59552da9a59SGnoCiYeH             sx * vc_data.font.width,
59652da9a59SGnoCiYeH             sy * vc_data.font.height,
59752da9a59SGnoCiYeH             width * vc_data.font.width,
59852da9a59SGnoCiYeH             height * vc_data.font.height,
59952da9a59SGnoCiYeH             self.get_color(vc_data, vc_data.erase_char, false),
60052da9a59SGnoCiYeH             FillRectROP::Copy,
60152da9a59SGnoCiYeH         );
60252da9a59SGnoCiYeH 
60352da9a59SGnoCiYeH         self.fb().fb_fillrect(region)?;
60452da9a59SGnoCiYeH 
60552da9a59SGnoCiYeH         Ok(())
60652da9a59SGnoCiYeH     }
60752da9a59SGnoCiYeH 
put_string( &self, vc_data: &VirtualConsoleData, data: &[u16], mut count: u32, y: u32, x: u32, fg: u32, bg: u32, ) -> Result<(), SystemError>60852da9a59SGnoCiYeH     fn put_string(
60952da9a59SGnoCiYeH         &self,
61052da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
61152da9a59SGnoCiYeH         data: &[u16],
61252da9a59SGnoCiYeH         mut count: u32,
61352da9a59SGnoCiYeH         y: u32,
61452da9a59SGnoCiYeH         x: u32,
61552da9a59SGnoCiYeH         fg: u32,
61652da9a59SGnoCiYeH         bg: u32,
61752da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
61852da9a59SGnoCiYeH         // 向上取整
61952da9a59SGnoCiYeH         let width = (vc_data.font.width + 7) / 8;
62052da9a59SGnoCiYeH         let cellsize = width * vc_data.font.height;
62152da9a59SGnoCiYeH         let fb_info = self.fb();
62252da9a59SGnoCiYeH         // 一次能输出的最大字数,避免帧缓冲区溢出
62352da9a59SGnoCiYeH         let max_cnt = (fb_info.current_fb_var().xres * fb_info.current_fb_var().yres) / cellsize;
62452da9a59SGnoCiYeH         let attr = FbConAttr::get_attr(data[0], fb_info.color_depth());
62552da9a59SGnoCiYeH 
62652da9a59SGnoCiYeH         let mut image = FbImage {
62752da9a59SGnoCiYeH             x: x * vc_data.font.width,
62852da9a59SGnoCiYeH             y: y * vc_data.font.height,
62952da9a59SGnoCiYeH             width: 0,
63052da9a59SGnoCiYeH             height: vc_data.font.height,
63152da9a59SGnoCiYeH             fg,
63252da9a59SGnoCiYeH             bg,
63352da9a59SGnoCiYeH             depth: 1,
63452da9a59SGnoCiYeH             data: Default::default(),
63552da9a59SGnoCiYeH         };
63652da9a59SGnoCiYeH 
63752da9a59SGnoCiYeH         image.data.resize(cellsize as usize * count as usize, 0);
63852da9a59SGnoCiYeH 
63952da9a59SGnoCiYeH         while count > 0 {
64052da9a59SGnoCiYeH             let cnt = count.min(max_cnt);
64152da9a59SGnoCiYeH 
64252da9a59SGnoCiYeH             image.width = vc_data.font.width * cnt;
64352da9a59SGnoCiYeH 
64452da9a59SGnoCiYeH             self.bit_put_string(vc_data, data, attr, cnt, cellsize, &mut image);
64552da9a59SGnoCiYeH 
64652da9a59SGnoCiYeH             image.x += cnt * vc_data.font.width;
64752da9a59SGnoCiYeH             count -= cnt;
64852da9a59SGnoCiYeH         }
64952da9a59SGnoCiYeH 
65052da9a59SGnoCiYeH         Ok(())
65152da9a59SGnoCiYeH     }
65252da9a59SGnoCiYeH 
fbcon_data(&self) -> SpinLockGuard<super::FrameBufferConsoleData>65352da9a59SGnoCiYeH     fn fbcon_data(&self) -> SpinLockGuard<super::FrameBufferConsoleData> {
65452da9a59SGnoCiYeH         self.fbcon_data.lock()
65552da9a59SGnoCiYeH     }
65652da9a59SGnoCiYeH 
cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32)65752da9a59SGnoCiYeH     fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32) {
65852da9a59SGnoCiYeH         let mut fbcon_data = self.fbcon_data();
65952da9a59SGnoCiYeH         let fb_info = self.fb();
66052da9a59SGnoCiYeH         let mut cursor = FbCursor::default();
66152da9a59SGnoCiYeH         let charmask = if vc_data.hi_font_mask != 0 {
66252da9a59SGnoCiYeH             0x1ff
66352da9a59SGnoCiYeH         } else {
66452da9a59SGnoCiYeH             0xff
66552da9a59SGnoCiYeH         };
66652da9a59SGnoCiYeH 
66752da9a59SGnoCiYeH         // 向上取整
66852da9a59SGnoCiYeH         let w = (vc_data.font.width + 7) / 8;
66952da9a59SGnoCiYeH         let y = fbcon_data.display.real_y(vc_data.state.y as u32);
67052da9a59SGnoCiYeH 
67152da9a59SGnoCiYeH         let c = vc_data.screen_buf[vc_data.pos];
67252da9a59SGnoCiYeH         let attr = FbConAttr::get_attr(c, fb_info.color_depth());
67352da9a59SGnoCiYeH         let char_offset = (c as usize & charmask) * ((w * vc_data.font.height) as usize);
67452da9a59SGnoCiYeH 
675b5b571e0SLoGin         if fbcon_data.cursor_state.image.data != vc_data.font.data[char_offset..]
67652da9a59SGnoCiYeH             || fbcon_data.cursor_reset
67752da9a59SGnoCiYeH         {
67852da9a59SGnoCiYeH             fbcon_data.cursor_state.image.data = vc_data.font.data[char_offset..].to_vec();
67952da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETIMAGE);
68052da9a59SGnoCiYeH         }
68152da9a59SGnoCiYeH 
68252da9a59SGnoCiYeH         if !attr.is_empty() {
68352da9a59SGnoCiYeH             fbcon_data
68452da9a59SGnoCiYeH                 .cursor_data
68552da9a59SGnoCiYeH                 .resize(w as usize * vc_data.font.height as usize, 0);
68652da9a59SGnoCiYeH 
68752da9a59SGnoCiYeH             attr.update_attr(
68852da9a59SGnoCiYeH                 &mut fbcon_data.cursor_data,
68952da9a59SGnoCiYeH                 &vc_data.font.data[char_offset..],
69052da9a59SGnoCiYeH                 vc_data,
69152da9a59SGnoCiYeH             );
69252da9a59SGnoCiYeH         }
69352da9a59SGnoCiYeH 
69452da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.fg != fg
69552da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.bg != bg
69652da9a59SGnoCiYeH             || fbcon_data.cursor_reset
69752da9a59SGnoCiYeH         {
69852da9a59SGnoCiYeH             fbcon_data.cursor_state.image.fg = fg;
69952da9a59SGnoCiYeH             fbcon_data.cursor_state.image.bg = bg;
70052da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETCMAP);
70152da9a59SGnoCiYeH         }
70252da9a59SGnoCiYeH 
70352da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.x != (vc_data.font.width * vc_data.state.x as u32)
70452da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.y != (vc_data.font.height * y)
70552da9a59SGnoCiYeH             || fbcon_data.cursor_reset
70652da9a59SGnoCiYeH         {
70752da9a59SGnoCiYeH             fbcon_data.cursor_state.image.x = vc_data.font.width * vc_data.state.x as u32;
70852da9a59SGnoCiYeH             fbcon_data.cursor_state.image.y = vc_data.font.height * y;
70952da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETPOS);
71052da9a59SGnoCiYeH         }
71152da9a59SGnoCiYeH 
71252da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.height != vc_data.font.height
71352da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.width != vc_data.font.width
71452da9a59SGnoCiYeH             || fbcon_data.cursor_reset
71552da9a59SGnoCiYeH         {
71652da9a59SGnoCiYeH             fbcon_data.cursor_state.image.height = vc_data.font.height;
71752da9a59SGnoCiYeH             fbcon_data.cursor_state.image.width = vc_data.font.width;
71852da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSIZE);
71952da9a59SGnoCiYeH         }
72052da9a59SGnoCiYeH 
72152da9a59SGnoCiYeH         if fbcon_data.cursor_state.hot_x > 0
72252da9a59SGnoCiYeH             || fbcon_data.cursor_state.hot_y > 0
72352da9a59SGnoCiYeH             || fbcon_data.cursor_reset
72452da9a59SGnoCiYeH         {
72552da9a59SGnoCiYeH             fbcon_data.cursor_state.hot_x = 0;
72652da9a59SGnoCiYeH             cursor.hot_y = 0;
72752da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETHOT);
72852da9a59SGnoCiYeH         }
72952da9a59SGnoCiYeH 
73052da9a59SGnoCiYeH         if cursor.set_mode.contains(FbCursorSetMode::FB_CUR_SETSIZE)
73152da9a59SGnoCiYeH             || vc_data.cursor_type != fbcon_data.display.cursor_shape
73252da9a59SGnoCiYeH             || fbcon_data.cursor_state.mask.is_empty()
73352da9a59SGnoCiYeH             || fbcon_data.cursor_reset
73452da9a59SGnoCiYeH         {
73552da9a59SGnoCiYeH             fbcon_data.display.cursor_shape = vc_data.cursor_type;
73652da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSHAPE);
73752da9a59SGnoCiYeH 
73852da9a59SGnoCiYeH             let cur_height;
73952da9a59SGnoCiYeH             match fbcon_data.display.cursor_shape.cursor_size() {
74052da9a59SGnoCiYeH                 VcCursor::CUR_NONE => {
74152da9a59SGnoCiYeH                     cur_height = 0;
74252da9a59SGnoCiYeH                 }
74352da9a59SGnoCiYeH                 VcCursor::CUR_UNDERLINE => {
74452da9a59SGnoCiYeH                     if vc_data.font.height < 10 {
74552da9a59SGnoCiYeH                         cur_height = 1;
74652da9a59SGnoCiYeH                     } else {
74752da9a59SGnoCiYeH                         cur_height = 2;
74852da9a59SGnoCiYeH                     }
74952da9a59SGnoCiYeH                 }
75052da9a59SGnoCiYeH                 VcCursor::CUR_LOWER_THIRD => {
75152da9a59SGnoCiYeH                     cur_height = vc_data.font.height / 3;
75252da9a59SGnoCiYeH                 }
75352da9a59SGnoCiYeH                 VcCursor::CUR_LOWER_HALF => {
75452da9a59SGnoCiYeH                     cur_height = vc_data.font.height >> 1;
75552da9a59SGnoCiYeH                 }
75652da9a59SGnoCiYeH                 VcCursor::CUR_TWO_THIRDS => {
75752da9a59SGnoCiYeH                     cur_height = (vc_data.font.height << 1) / 3;
75852da9a59SGnoCiYeH                 }
75952da9a59SGnoCiYeH                 _ => {
76052da9a59SGnoCiYeH                     cur_height = vc_data.font.height;
76152da9a59SGnoCiYeH                 }
76252da9a59SGnoCiYeH             }
76352da9a59SGnoCiYeH 
76452da9a59SGnoCiYeH             // 表示空白部分
76552da9a59SGnoCiYeH             let mut size = (vc_data.font.height - cur_height) * w;
76652da9a59SGnoCiYeH             while size > 0 {
76752da9a59SGnoCiYeH                 size -= 1;
76852da9a59SGnoCiYeH                 fbcon_data.cursor_state.mask.push(0x00);
76952da9a59SGnoCiYeH             }
77052da9a59SGnoCiYeH             size = cur_height * w;
77152da9a59SGnoCiYeH             // 表示光标显示部分
77252da9a59SGnoCiYeH             while size > 0 {
77352da9a59SGnoCiYeH                 size -= 1;
77452da9a59SGnoCiYeH                 fbcon_data.cursor_state.mask.push(0xff);
77552da9a59SGnoCiYeH             }
77652da9a59SGnoCiYeH         }
77752da9a59SGnoCiYeH 
77852da9a59SGnoCiYeH         match op {
77952da9a59SGnoCiYeH             CursorOperation::Erase => {
78052da9a59SGnoCiYeH                 fbcon_data.cursor_state.enable = false;
78152da9a59SGnoCiYeH             }
78252da9a59SGnoCiYeH             _ => {
78352da9a59SGnoCiYeH                 fbcon_data.cursor_state.enable = !vc_data.cursor_type.contains(VcCursor::CUR_SW);
78452da9a59SGnoCiYeH             }
78552da9a59SGnoCiYeH         }
78652da9a59SGnoCiYeH 
78752da9a59SGnoCiYeH         if !attr.is_empty() {
78852da9a59SGnoCiYeH             cursor.image.data = fbcon_data.cursor_data.clone();
78952da9a59SGnoCiYeH         } else {
79052da9a59SGnoCiYeH             cursor.image.data = vc_data.font.data
79152da9a59SGnoCiYeH                 [char_offset..char_offset + (w as usize * vc_data.font.height as usize)]
79252da9a59SGnoCiYeH                 .to_vec();
79352da9a59SGnoCiYeH         }
79452da9a59SGnoCiYeH         cursor.image.fg = fbcon_data.cursor_state.image.fg;
79552da9a59SGnoCiYeH         cursor.image.bg = fbcon_data.cursor_state.image.bg;
79652da9a59SGnoCiYeH         cursor.image.x = fbcon_data.cursor_state.image.x;
79752da9a59SGnoCiYeH         cursor.image.y = fbcon_data.cursor_state.image.y;
79852da9a59SGnoCiYeH         cursor.image.height = fbcon_data.cursor_state.image.height;
79952da9a59SGnoCiYeH         cursor.image.width = fbcon_data.cursor_state.image.width;
80052da9a59SGnoCiYeH         cursor.hot_x = fbcon_data.cursor_state.hot_x;
80152da9a59SGnoCiYeH         cursor.hot_y = fbcon_data.cursor_state.hot_y;
80252da9a59SGnoCiYeH         cursor.mask = fbcon_data.cursor_state.mask.clone();
80352da9a59SGnoCiYeH         cursor.enable = fbcon_data.cursor_state.enable;
80452da9a59SGnoCiYeH         cursor.image.depth = 1;
80552da9a59SGnoCiYeH         cursor.rop = true;
80652da9a59SGnoCiYeH 
80752da9a59SGnoCiYeH         if fb_info.fb_cursor(&cursor).is_err() {
80852da9a59SGnoCiYeH             let _ = fb_info.soft_cursor(cursor);
80952da9a59SGnoCiYeH         }
81052da9a59SGnoCiYeH 
81152da9a59SGnoCiYeH         fbcon_data.cursor_reset = false;
81252da9a59SGnoCiYeH     }
81352da9a59SGnoCiYeH }
814