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