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