xref: /DragonOS/kernel/src/driver/video/fbdev/base/fbcon/framebuffer_console.rs (revision 52da9a59374752b4d01907b052135a0d317781dd)
1*52da9a59SGnoCiYeH use alloc::{sync::Arc, vec::Vec};
2*52da9a59SGnoCiYeH use system_error::SystemError;
3*52da9a59SGnoCiYeH 
4*52da9a59SGnoCiYeH use crate::{
5*52da9a59SGnoCiYeH     driver::{
6*52da9a59SGnoCiYeH         tty::{
7*52da9a59SGnoCiYeH             console::ConsoleSwitch,
8*52da9a59SGnoCiYeH             virtual_terminal::{
9*52da9a59SGnoCiYeH                 virtual_console::{CursorOperation, ScrollDir, VcCursor, VirtualConsoleData},
10*52da9a59SGnoCiYeH                 Color,
11*52da9a59SGnoCiYeH             },
12*52da9a59SGnoCiYeH         },
13*52da9a59SGnoCiYeH         video::fbdev::base::{
14*52da9a59SGnoCiYeH             CopyAreaData, FbCursor, FbCursorSetMode, FbImage, FbVisual, FillRectData, FillRectROP,
15*52da9a59SGnoCiYeH             FrameBuffer, ScrollMode, FRAME_BUFFER_SET,
16*52da9a59SGnoCiYeH         },
17*52da9a59SGnoCiYeH     },
18*52da9a59SGnoCiYeH     libs::{
19*52da9a59SGnoCiYeH         font::FontDesc,
20*52da9a59SGnoCiYeH         spinlock::{SpinLock, SpinLockGuard},
21*52da9a59SGnoCiYeH     },
22*52da9a59SGnoCiYeH };
23*52da9a59SGnoCiYeH 
24*52da9a59SGnoCiYeH use super::{FbConAttr, FrameBufferConsole, FrameBufferConsoleData};
25*52da9a59SGnoCiYeH 
26*52da9a59SGnoCiYeH #[derive(Debug)]
27*52da9a59SGnoCiYeH pub struct BlittingFbConsole {
28*52da9a59SGnoCiYeH     fb: SpinLock<Option<Arc<dyn FrameBuffer>>>,
29*52da9a59SGnoCiYeH     fbcon_data: SpinLock<FrameBufferConsoleData>,
30*52da9a59SGnoCiYeH }
31*52da9a59SGnoCiYeH 
32*52da9a59SGnoCiYeH unsafe impl Send for BlittingFbConsole {}
33*52da9a59SGnoCiYeH unsafe impl Sync for BlittingFbConsole {}
34*52da9a59SGnoCiYeH 
35*52da9a59SGnoCiYeH impl BlittingFbConsole {
36*52da9a59SGnoCiYeH     pub fn new() -> Result<Self, SystemError> {
37*52da9a59SGnoCiYeH         Ok(Self {
38*52da9a59SGnoCiYeH             fb: SpinLock::new(None),
39*52da9a59SGnoCiYeH             fbcon_data: SpinLock::new(FrameBufferConsoleData::default()),
40*52da9a59SGnoCiYeH         })
41*52da9a59SGnoCiYeH     }
42*52da9a59SGnoCiYeH 
43*52da9a59SGnoCiYeH     pub fn fb(&self) -> Arc<dyn FrameBuffer> {
44*52da9a59SGnoCiYeH         self.fb.lock().clone().unwrap()
45*52da9a59SGnoCiYeH     }
46*52da9a59SGnoCiYeH 
47*52da9a59SGnoCiYeH     pub fn get_color(&self, vc_data: &VirtualConsoleData, c: u16, is_fg: bool) -> u32 {
48*52da9a59SGnoCiYeH         let fb_info = self.fb();
49*52da9a59SGnoCiYeH         let mut color = 0;
50*52da9a59SGnoCiYeH 
51*52da9a59SGnoCiYeH         let depth = fb_info.color_depth();
52*52da9a59SGnoCiYeH 
53*52da9a59SGnoCiYeH         if depth != 1 {
54*52da9a59SGnoCiYeH             if is_fg {
55*52da9a59SGnoCiYeH                 let fg_shift = if vc_data.hi_font_mask != 0 { 9 } else { 8 };
56*52da9a59SGnoCiYeH                 color = (c as u32 >> fg_shift) & 0x0f
57*52da9a59SGnoCiYeH             } else {
58*52da9a59SGnoCiYeH                 let bg_shift = if vc_data.hi_font_mask != 0 { 13 } else { 12 };
59*52da9a59SGnoCiYeH                 color = (c as u32 >> bg_shift) & 0x0f
60*52da9a59SGnoCiYeH             }
61*52da9a59SGnoCiYeH         }
62*52da9a59SGnoCiYeH 
63*52da9a59SGnoCiYeH         match depth {
64*52da9a59SGnoCiYeH             1 => {
65*52da9a59SGnoCiYeH                 let col = self.mono_color();
66*52da9a59SGnoCiYeH                 let fg;
67*52da9a59SGnoCiYeH                 let bg;
68*52da9a59SGnoCiYeH                 if fb_info.current_fb_fix().visual != FbVisual::Mono01 {
69*52da9a59SGnoCiYeH                     fg = col;
70*52da9a59SGnoCiYeH                     bg = 0;
71*52da9a59SGnoCiYeH                 } else {
72*52da9a59SGnoCiYeH                     fg = 0;
73*52da9a59SGnoCiYeH                     bg = col;
74*52da9a59SGnoCiYeH                 }
75*52da9a59SGnoCiYeH                 color = if is_fg { fg } else { bg };
76*52da9a59SGnoCiYeH             }
77*52da9a59SGnoCiYeH             2 => {
78*52da9a59SGnoCiYeH                 /*
79*52da9a59SGnoCiYeH                     颜色深度为2,即16色,
80*52da9a59SGnoCiYeH                    将16色的颜色值映射到4色的灰度,
81*52da9a59SGnoCiYeH                    其中颜色0映射为黑色,颜色1到6映射为白色,
82*52da9a59SGnoCiYeH                    颜色7到8映射为灰色,其他颜色映射为强烈的白色。
83*52da9a59SGnoCiYeH                 */
84*52da9a59SGnoCiYeH                 if color >= 1 && color <= 6 {
85*52da9a59SGnoCiYeH                     // 白色
86*52da9a59SGnoCiYeH                     color = 2;
87*52da9a59SGnoCiYeH                 } else if color >= 7 && color <= 8 {
88*52da9a59SGnoCiYeH                     // 灰色
89*52da9a59SGnoCiYeH                     color = 1;
90*52da9a59SGnoCiYeH                 } else {
91*52da9a59SGnoCiYeH                     // 强白
92*52da9a59SGnoCiYeH                     color = 3;
93*52da9a59SGnoCiYeH                 }
94*52da9a59SGnoCiYeH             }
95*52da9a59SGnoCiYeH             3 => {
96*52da9a59SGnoCiYeH                 /*
97*52da9a59SGnoCiYeH                    颜色深度为3,即256色,仅保留颜色的低3位,即颜色 0 到 7
98*52da9a59SGnoCiYeH                 */
99*52da9a59SGnoCiYeH                 color &= 7;
100*52da9a59SGnoCiYeH             }
101*52da9a59SGnoCiYeH             _ => {}
102*52da9a59SGnoCiYeH         }
103*52da9a59SGnoCiYeH         color
104*52da9a59SGnoCiYeH     }
105*52da9a59SGnoCiYeH 
106*52da9a59SGnoCiYeH     /// ## 计算单色调的函数
107*52da9a59SGnoCiYeH     pub fn mono_color(&self) -> u32 {
108*52da9a59SGnoCiYeH         let fb_info = self.fb();
109*52da9a59SGnoCiYeH         let mut max_len = fb_info
110*52da9a59SGnoCiYeH             .current_fb_var()
111*52da9a59SGnoCiYeH             .green
112*52da9a59SGnoCiYeH             .length
113*52da9a59SGnoCiYeH             .max(fb_info.current_fb_var().red.length);
114*52da9a59SGnoCiYeH 
115*52da9a59SGnoCiYeH         max_len = max_len.max(fb_info.current_fb_var().blue.length);
116*52da9a59SGnoCiYeH 
117*52da9a59SGnoCiYeH         return (!(0xfff << max_len)) & 0xff;
118*52da9a59SGnoCiYeH     }
119*52da9a59SGnoCiYeH 
120*52da9a59SGnoCiYeH     pub fn bit_put_string(
121*52da9a59SGnoCiYeH         &self,
122*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
123*52da9a59SGnoCiYeH         buf: &[u16],
124*52da9a59SGnoCiYeH         attr: FbConAttr,
125*52da9a59SGnoCiYeH         cnt: u32,
126*52da9a59SGnoCiYeH         cellsize: u32,
127*52da9a59SGnoCiYeH         image: &mut FbImage,
128*52da9a59SGnoCiYeH     ) {
129*52da9a59SGnoCiYeH         let charmask = if vc_data.hi_font_mask != 0 {
130*52da9a59SGnoCiYeH             0x1ff
131*52da9a59SGnoCiYeH         } else {
132*52da9a59SGnoCiYeH             0xff
133*52da9a59SGnoCiYeH         };
134*52da9a59SGnoCiYeH 
135*52da9a59SGnoCiYeH         let mut offset;
136*52da9a59SGnoCiYeH         let image_line_byte = image.width as usize / 8;
137*52da9a59SGnoCiYeH 
138*52da9a59SGnoCiYeH         let byte_width = vc_data.font.width as usize / 8;
139*52da9a59SGnoCiYeH         let font_height = vc_data.font.height as usize;
140*52da9a59SGnoCiYeH         // let mut char_offset = 0;
141*52da9a59SGnoCiYeH         for char_offset in 0..cnt as usize {
142*52da9a59SGnoCiYeH             // 在字符表中的index
143*52da9a59SGnoCiYeH             let ch = buf[char_offset] & charmask;
144*52da9a59SGnoCiYeH             // 计算出在font表中的偏移量
145*52da9a59SGnoCiYeH             let font_offset = ch as usize * cellsize as usize;
146*52da9a59SGnoCiYeH             let font_offset_end = font_offset + cellsize as usize;
147*52da9a59SGnoCiYeH             // 设置image的data
148*52da9a59SGnoCiYeH 
149*52da9a59SGnoCiYeH             let src = &vc_data.font.data[font_offset..font_offset_end];
150*52da9a59SGnoCiYeH             let mut dst = Vec::new();
151*52da9a59SGnoCiYeH             dst.resize(src.len(), 0);
152*52da9a59SGnoCiYeH             dst.copy_from_slice(src);
153*52da9a59SGnoCiYeH 
154*52da9a59SGnoCiYeH             if !attr.is_empty() {
155*52da9a59SGnoCiYeH                 attr.update_attr(&mut dst, src, vc_data)
156*52da9a59SGnoCiYeH             }
157*52da9a59SGnoCiYeH 
158*52da9a59SGnoCiYeH             offset = char_offset * byte_width;
159*52da9a59SGnoCiYeH             let mut dst_offset = 0;
160*52da9a59SGnoCiYeH             for _ in 0..font_height {
161*52da9a59SGnoCiYeH                 let dst_offset_next = dst_offset + byte_width;
162*52da9a59SGnoCiYeH                 image.data[offset..offset + byte_width]
163*52da9a59SGnoCiYeH                     .copy_from_slice(&dst[dst_offset..dst_offset_next]);
164*52da9a59SGnoCiYeH 
165*52da9a59SGnoCiYeH                 offset += image_line_byte;
166*52da9a59SGnoCiYeH                 dst_offset = dst_offset_next;
167*52da9a59SGnoCiYeH             }
168*52da9a59SGnoCiYeH         }
169*52da9a59SGnoCiYeH 
170*52da9a59SGnoCiYeH         self.fb().fb_image_blit(image);
171*52da9a59SGnoCiYeH     }
172*52da9a59SGnoCiYeH }
173*52da9a59SGnoCiYeH 
174*52da9a59SGnoCiYeH impl ConsoleSwitch for BlittingFbConsole {
175*52da9a59SGnoCiYeH     fn con_init(
176*52da9a59SGnoCiYeH         &self,
177*52da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
178*52da9a59SGnoCiYeH         init: bool,
179*52da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
180*52da9a59SGnoCiYeH         let fb_set_guard = FRAME_BUFFER_SET.read();
181*52da9a59SGnoCiYeH         let fb = fb_set_guard.get(vc_data.index);
182*52da9a59SGnoCiYeH         if fb.is_none() {
183*52da9a59SGnoCiYeH             return Err(SystemError::EINVAL);
184*52da9a59SGnoCiYeH         }
185*52da9a59SGnoCiYeH         let fb = fb.unwrap();
186*52da9a59SGnoCiYeH         if fb.is_none() {
187*52da9a59SGnoCiYeH             panic!(
188*52da9a59SGnoCiYeH                 "The Framebuffer with FbID {} has not been initialized yet.",
189*52da9a59SGnoCiYeH                 vc_data.index
190*52da9a59SGnoCiYeH             )
191*52da9a59SGnoCiYeH         }
192*52da9a59SGnoCiYeH 
193*52da9a59SGnoCiYeH         let fb = fb.as_ref().unwrap().clone();
194*52da9a59SGnoCiYeH 
195*52da9a59SGnoCiYeH         if init {
196*52da9a59SGnoCiYeH             // 初始化字体
197*52da9a59SGnoCiYeH             let var = fb.current_fb_var();
198*52da9a59SGnoCiYeH             let font = FontDesc::get_default_font(var.xres, var.yres, 0, 0);
199*52da9a59SGnoCiYeH             vc_data.font.data = font.data.to_vec();
200*52da9a59SGnoCiYeH             vc_data.font.width = font.width;
201*52da9a59SGnoCiYeH             vc_data.font.height = font.height;
202*52da9a59SGnoCiYeH             vc_data.font.count = font.char_count;
203*52da9a59SGnoCiYeH         } else {
204*52da9a59SGnoCiYeH             kwarn!("The frontend Framebuffer is not implemented");
205*52da9a59SGnoCiYeH         }
206*52da9a59SGnoCiYeH 
207*52da9a59SGnoCiYeH         vc_data.color_mode = fb.color_depth() != 1;
208*52da9a59SGnoCiYeH         vc_data.complement_mask = if vc_data.color_mode { 0x7700 } else { 0x0800 };
209*52da9a59SGnoCiYeH 
210*52da9a59SGnoCiYeH         if vc_data.font.count == 256 {
211*52da9a59SGnoCiYeH             // ascii
212*52da9a59SGnoCiYeH             vc_data.hi_font_mask = 0;
213*52da9a59SGnoCiYeH         } else {
214*52da9a59SGnoCiYeH             vc_data.hi_font_mask = 0x100;
215*52da9a59SGnoCiYeH             if vc_data.color_mode {
216*52da9a59SGnoCiYeH                 vc_data.complement_mask <<= 1;
217*52da9a59SGnoCiYeH             }
218*52da9a59SGnoCiYeH         }
219*52da9a59SGnoCiYeH 
220*52da9a59SGnoCiYeH         // TODO: 考虑rotate
221*52da9a59SGnoCiYeH         if init {
222*52da9a59SGnoCiYeH             vc_data.cols = (fb.current_fb_var().xres / vc_data.font.width) as usize;
223*52da9a59SGnoCiYeH             vc_data.rows = (fb.current_fb_var().yres / vc_data.font.height) as usize;
224*52da9a59SGnoCiYeH 
225*52da9a59SGnoCiYeH             vc_data.pos = vc_data.state.x + vc_data.state.y * vc_data.cols;
226*52da9a59SGnoCiYeH 
227*52da9a59SGnoCiYeH             let new_size = vc_data.cols * vc_data.rows;
228*52da9a59SGnoCiYeH             vc_data.screen_buf.resize(new_size, 0);
229*52da9a59SGnoCiYeH         } else {
230*52da9a59SGnoCiYeH             unimplemented!("Resize is not supported at the moment!");
231*52da9a59SGnoCiYeH         }
232*52da9a59SGnoCiYeH 
233*52da9a59SGnoCiYeH         // 初始化fb
234*52da9a59SGnoCiYeH         *self.fb.lock() = Some(fb);
235*52da9a59SGnoCiYeH 
236*52da9a59SGnoCiYeH         Ok(())
237*52da9a59SGnoCiYeH     }
238*52da9a59SGnoCiYeH 
239*52da9a59SGnoCiYeH     fn con_deinit(&self) -> Result<(), system_error::SystemError> {
240*52da9a59SGnoCiYeH         todo!()
241*52da9a59SGnoCiYeH     }
242*52da9a59SGnoCiYeH 
243*52da9a59SGnoCiYeH     fn con_clear(
244*52da9a59SGnoCiYeH         &self,
245*52da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
246*52da9a59SGnoCiYeH         sy: usize,
247*52da9a59SGnoCiYeH         sx: usize,
248*52da9a59SGnoCiYeH         height: usize,
249*52da9a59SGnoCiYeH         width: usize,
250*52da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
251*52da9a59SGnoCiYeH         let fb_data = self.fbcon_data();
252*52da9a59SGnoCiYeH 
253*52da9a59SGnoCiYeH         if height == 0 || width == 0 {
254*52da9a59SGnoCiYeH             return Ok(());
255*52da9a59SGnoCiYeH         }
256*52da9a59SGnoCiYeH 
257*52da9a59SGnoCiYeH         let y_break = (fb_data.display.virt_rows - fb_data.display.yscroll) as usize;
258*52da9a59SGnoCiYeH         if sy < y_break && sy + height - 1 >= y_break {
259*52da9a59SGnoCiYeH             // 分两次clear
260*52da9a59SGnoCiYeH             let b = y_break - sy;
261*52da9a59SGnoCiYeH             let _ = self.clear(
262*52da9a59SGnoCiYeH                 &vc_data,
263*52da9a59SGnoCiYeH                 fb_data.display.real_y(sy as u32),
264*52da9a59SGnoCiYeH                 sx as u32,
265*52da9a59SGnoCiYeH                 b as u32,
266*52da9a59SGnoCiYeH                 width as u32,
267*52da9a59SGnoCiYeH             );
268*52da9a59SGnoCiYeH             let _ = self.clear(
269*52da9a59SGnoCiYeH                 &vc_data,
270*52da9a59SGnoCiYeH                 fb_data.display.real_y((sy + b) as u32),
271*52da9a59SGnoCiYeH                 sx as u32,
272*52da9a59SGnoCiYeH                 (height - b) as u32,
273*52da9a59SGnoCiYeH                 width as u32,
274*52da9a59SGnoCiYeH             );
275*52da9a59SGnoCiYeH         } else {
276*52da9a59SGnoCiYeH             let _ = self.clear(
277*52da9a59SGnoCiYeH                 &vc_data,
278*52da9a59SGnoCiYeH                 fb_data.display.real_y(sy as u32),
279*52da9a59SGnoCiYeH                 sx as u32,
280*52da9a59SGnoCiYeH                 height as u32,
281*52da9a59SGnoCiYeH                 width as u32,
282*52da9a59SGnoCiYeH             );
283*52da9a59SGnoCiYeH         }
284*52da9a59SGnoCiYeH 
285*52da9a59SGnoCiYeH         Ok(())
286*52da9a59SGnoCiYeH     }
287*52da9a59SGnoCiYeH 
288*52da9a59SGnoCiYeH     fn con_putc(
289*52da9a59SGnoCiYeH         &self,
290*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
291*52da9a59SGnoCiYeH         ch: u16,
292*52da9a59SGnoCiYeH         xpos: u32,
293*52da9a59SGnoCiYeH         ypos: u32,
294*52da9a59SGnoCiYeH     ) -> Result<(), system_error::SystemError> {
295*52da9a59SGnoCiYeH         self.con_putcs(vc_data, &[ch], 1, ypos, xpos)
296*52da9a59SGnoCiYeH     }
297*52da9a59SGnoCiYeH 
298*52da9a59SGnoCiYeH     fn con_putcs(
299*52da9a59SGnoCiYeH         &self,
300*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
301*52da9a59SGnoCiYeH         buf: &[u16],
302*52da9a59SGnoCiYeH         count: usize,
303*52da9a59SGnoCiYeH         ypos: u32,
304*52da9a59SGnoCiYeH         xpos: u32,
305*52da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
306*52da9a59SGnoCiYeH         if count == 0 {
307*52da9a59SGnoCiYeH             return Ok(());
308*52da9a59SGnoCiYeH         }
309*52da9a59SGnoCiYeH         let fbcon_data = self.fbcon_data();
310*52da9a59SGnoCiYeH         let c = buf[0];
311*52da9a59SGnoCiYeH         self.put_string(
312*52da9a59SGnoCiYeH             vc_data,
313*52da9a59SGnoCiYeH             buf,
314*52da9a59SGnoCiYeH             count as u32,
315*52da9a59SGnoCiYeH             fbcon_data.display.real_y(ypos),
316*52da9a59SGnoCiYeH             xpos,
317*52da9a59SGnoCiYeH             self.get_color(vc_data, c, true),
318*52da9a59SGnoCiYeH             self.get_color(vc_data, c, false),
319*52da9a59SGnoCiYeH         )
320*52da9a59SGnoCiYeH     }
321*52da9a59SGnoCiYeH 
322*52da9a59SGnoCiYeH     fn con_getxy(
323*52da9a59SGnoCiYeH         &self,
324*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
325*52da9a59SGnoCiYeH         pos: usize,
326*52da9a59SGnoCiYeH     ) -> Result<(usize, usize, usize), SystemError> {
327*52da9a59SGnoCiYeH         if pos < vc_data.screen_buf.len() {
328*52da9a59SGnoCiYeH             let x = pos % vc_data.cols;
329*52da9a59SGnoCiYeH             let y = pos / vc_data.cols;
330*52da9a59SGnoCiYeH             let mut next_line_start = pos + (vc_data.cols - x);
331*52da9a59SGnoCiYeH             if next_line_start >= vc_data.screen_buf.len() {
332*52da9a59SGnoCiYeH                 next_line_start = 0
333*52da9a59SGnoCiYeH             }
334*52da9a59SGnoCiYeH             return Ok((next_line_start, x, y));
335*52da9a59SGnoCiYeH         } else {
336*52da9a59SGnoCiYeH             return Ok((0, 0, 0));
337*52da9a59SGnoCiYeH         }
338*52da9a59SGnoCiYeH     }
339*52da9a59SGnoCiYeH 
340*52da9a59SGnoCiYeH     fn con_cursor(
341*52da9a59SGnoCiYeH         &self,
342*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
343*52da9a59SGnoCiYeH         op: crate::driver::tty::virtual_terminal::virtual_console::CursorOperation,
344*52da9a59SGnoCiYeH     ) {
345*52da9a59SGnoCiYeH         let mut fbcon_data = self.fbcon_data();
346*52da9a59SGnoCiYeH 
347*52da9a59SGnoCiYeH         let c = vc_data.screen_buf[vc_data.pos];
348*52da9a59SGnoCiYeH 
349*52da9a59SGnoCiYeH         if vc_data.cursor_type.contains(VcCursor::CUR_SW) {
350*52da9a59SGnoCiYeH             // 取消硬光标Timer,但是现在没有硬光标,先写在这
351*52da9a59SGnoCiYeH         } else {
352*52da9a59SGnoCiYeH             // 添加硬光标Timer
353*52da9a59SGnoCiYeH         }
354*52da9a59SGnoCiYeH 
355*52da9a59SGnoCiYeH         fbcon_data.cursor_flash = op != CursorOperation::Erase;
356*52da9a59SGnoCiYeH 
357*52da9a59SGnoCiYeH         drop(fbcon_data);
358*52da9a59SGnoCiYeH 
359*52da9a59SGnoCiYeH         self.cursor(
360*52da9a59SGnoCiYeH             vc_data,
361*52da9a59SGnoCiYeH             op,
362*52da9a59SGnoCiYeH             self.get_color(vc_data, c, true),
363*52da9a59SGnoCiYeH             self.get_color(vc_data, c, false),
364*52da9a59SGnoCiYeH         );
365*52da9a59SGnoCiYeH     }
366*52da9a59SGnoCiYeH 
367*52da9a59SGnoCiYeH     fn con_set_palette(
368*52da9a59SGnoCiYeH         &self,
369*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
370*52da9a59SGnoCiYeH         color_table: &[u8],
371*52da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
372*52da9a59SGnoCiYeH         let fb_info = self.fb();
373*52da9a59SGnoCiYeH         let depth = fb_info.color_depth();
374*52da9a59SGnoCiYeH         let mut palette = Vec::new();
375*52da9a59SGnoCiYeH         palette.resize(16, Color::default());
376*52da9a59SGnoCiYeH         if depth > 3 {
377*52da9a59SGnoCiYeH             let vc_palette = &vc_data.palette;
378*52da9a59SGnoCiYeH             for i in 0..16 {
379*52da9a59SGnoCiYeH                 let idx = color_table[i];
380*52da9a59SGnoCiYeH                 let col = palette.get_mut(idx as usize).unwrap();
381*52da9a59SGnoCiYeH                 col.red = (vc_palette[i].red << 8) | vc_palette[i].red;
382*52da9a59SGnoCiYeH                 col.green = (vc_palette[i].green << 8) | vc_palette[i].green;
383*52da9a59SGnoCiYeH                 col.blue = (vc_palette[i].blue << 8) | vc_palette[i].blue;
384*52da9a59SGnoCiYeH             }
385*52da9a59SGnoCiYeH         } else {
386*52da9a59SGnoCiYeH             todo!()
387*52da9a59SGnoCiYeH         }
388*52da9a59SGnoCiYeH 
389*52da9a59SGnoCiYeH         self.fb().set_color_map(palette)?;
390*52da9a59SGnoCiYeH 
391*52da9a59SGnoCiYeH         Ok(())
392*52da9a59SGnoCiYeH     }
393*52da9a59SGnoCiYeH 
394*52da9a59SGnoCiYeH     fn con_scroll(
395*52da9a59SGnoCiYeH         &self,
396*52da9a59SGnoCiYeH         vc_data: &mut VirtualConsoleData,
397*52da9a59SGnoCiYeH         top: usize,
398*52da9a59SGnoCiYeH         bottom: usize,
399*52da9a59SGnoCiYeH         dir: crate::driver::tty::virtual_terminal::virtual_console::ScrollDir,
400*52da9a59SGnoCiYeH         mut count: usize,
401*52da9a59SGnoCiYeH     ) -> bool {
402*52da9a59SGnoCiYeH         self.con_cursor(vc_data, CursorOperation::Erase);
403*52da9a59SGnoCiYeH 
404*52da9a59SGnoCiYeH         let fbcon_data = self.fbcon_data();
405*52da9a59SGnoCiYeH         let scroll_mode = fbcon_data.display.scroll_mode;
406*52da9a59SGnoCiYeH 
407*52da9a59SGnoCiYeH         drop(fbcon_data);
408*52da9a59SGnoCiYeH 
409*52da9a59SGnoCiYeH         match dir {
410*52da9a59SGnoCiYeH             ScrollDir::Up => {
411*52da9a59SGnoCiYeH                 if count > vc_data.rows {
412*52da9a59SGnoCiYeH                     count = vc_data.rows;
413*52da9a59SGnoCiYeH                 }
414*52da9a59SGnoCiYeH 
415*52da9a59SGnoCiYeH                 match scroll_mode {
416*52da9a59SGnoCiYeH                     ScrollMode::Move => {
417*52da9a59SGnoCiYeH                         let start = top * vc_data.cols;
418*52da9a59SGnoCiYeH                         let end = bottom * vc_data.cols;
419*52da9a59SGnoCiYeH                         vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
420*52da9a59SGnoCiYeH 
421*52da9a59SGnoCiYeH                         let _ = self.bmove(
422*52da9a59SGnoCiYeH                             vc_data,
423*52da9a59SGnoCiYeH                             top as i32,
424*52da9a59SGnoCiYeH                             0,
425*52da9a59SGnoCiYeH                             top as i32 - count as i32,
426*52da9a59SGnoCiYeH                             0,
427*52da9a59SGnoCiYeH                             (bottom - top) as u32,
428*52da9a59SGnoCiYeH                             vc_data.cols as u32,
429*52da9a59SGnoCiYeH                         );
430*52da9a59SGnoCiYeH 
431*52da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
432*52da9a59SGnoCiYeH 
433*52da9a59SGnoCiYeH                         let offset = vc_data.cols * (bottom - count);
434*52da9a59SGnoCiYeH                         for i in
435*52da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
436*52da9a59SGnoCiYeH                         {
437*52da9a59SGnoCiYeH                             *i = vc_data.erase_char;
438*52da9a59SGnoCiYeH                         }
439*52da9a59SGnoCiYeH 
440*52da9a59SGnoCiYeH                         return true;
441*52da9a59SGnoCiYeH                     }
442*52da9a59SGnoCiYeH                     ScrollMode::PanMove => todo!(),
443*52da9a59SGnoCiYeH                     ScrollMode::WrapMove => todo!(),
444*52da9a59SGnoCiYeH                     ScrollMode::Redraw => {
445*52da9a59SGnoCiYeH                         let start = top * vc_data.cols;
446*52da9a59SGnoCiYeH                         let end = bottom * vc_data.cols;
447*52da9a59SGnoCiYeH                         vc_data.screen_buf[start..end].rotate_left(count * vc_data.cols);
448*52da9a59SGnoCiYeH 
449*52da9a59SGnoCiYeH                         let data = &vc_data.screen_buf[start..(bottom - count) * vc_data.cols];
450*52da9a59SGnoCiYeH 
451*52da9a59SGnoCiYeH                         for line in top..(bottom - count) {
452*52da9a59SGnoCiYeH                             let mut start = line * vc_data.cols;
453*52da9a59SGnoCiYeH                             let end = start + vc_data.cols;
454*52da9a59SGnoCiYeH                             let mut offset = start;
455*52da9a59SGnoCiYeH                             let mut attr = 1;
456*52da9a59SGnoCiYeH                             let mut x = 0;
457*52da9a59SGnoCiYeH                             while offset < end {
458*52da9a59SGnoCiYeH                                 let c = data[offset];
459*52da9a59SGnoCiYeH 
460*52da9a59SGnoCiYeH                                 if attr != c & 0xff00 {
461*52da9a59SGnoCiYeH                                     // 属性变化,输出完上一个的并且更新属性
462*52da9a59SGnoCiYeH                                     attr = c & 0xff00;
463*52da9a59SGnoCiYeH 
464*52da9a59SGnoCiYeH                                     let count = offset - start;
465*52da9a59SGnoCiYeH                                     let _ = self.con_putcs(
466*52da9a59SGnoCiYeH                                         vc_data,
467*52da9a59SGnoCiYeH                                         &data[start..offset],
468*52da9a59SGnoCiYeH                                         count,
469*52da9a59SGnoCiYeH                                         line as u32,
470*52da9a59SGnoCiYeH                                         x,
471*52da9a59SGnoCiYeH                                     );
472*52da9a59SGnoCiYeH                                     start = offset;
473*52da9a59SGnoCiYeH                                     x += count as u32;
474*52da9a59SGnoCiYeH                                 }
475*52da9a59SGnoCiYeH 
476*52da9a59SGnoCiYeH                                 offset += 1;
477*52da9a59SGnoCiYeH                             }
478*52da9a59SGnoCiYeH                             let _ = self.con_putcs(
479*52da9a59SGnoCiYeH                                 vc_data,
480*52da9a59SGnoCiYeH                                 &data[start..offset],
481*52da9a59SGnoCiYeH                                 offset - start,
482*52da9a59SGnoCiYeH                                 line as u32,
483*52da9a59SGnoCiYeH                                 x,
484*52da9a59SGnoCiYeH                             );
485*52da9a59SGnoCiYeH                         }
486*52da9a59SGnoCiYeH 
487*52da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, bottom - count, 0, count, vc_data.cols);
488*52da9a59SGnoCiYeH 
489*52da9a59SGnoCiYeH                         let offset = vc_data.cols * (bottom - count);
490*52da9a59SGnoCiYeH                         for i in
491*52da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
492*52da9a59SGnoCiYeH                         {
493*52da9a59SGnoCiYeH                             *i = vc_data.erase_char;
494*52da9a59SGnoCiYeH                         }
495*52da9a59SGnoCiYeH 
496*52da9a59SGnoCiYeH                         return true;
497*52da9a59SGnoCiYeH                     }
498*52da9a59SGnoCiYeH                     ScrollMode::PanRedraw => todo!(),
499*52da9a59SGnoCiYeH                 }
500*52da9a59SGnoCiYeH             }
501*52da9a59SGnoCiYeH             ScrollDir::Down => {
502*52da9a59SGnoCiYeH                 if count > vc_data.rows {
503*52da9a59SGnoCiYeH                     count = vc_data.rows;
504*52da9a59SGnoCiYeH                 }
505*52da9a59SGnoCiYeH 
506*52da9a59SGnoCiYeH                 match scroll_mode {
507*52da9a59SGnoCiYeH                     ScrollMode::Move => todo!(),
508*52da9a59SGnoCiYeH                     ScrollMode::PanMove => todo!(),
509*52da9a59SGnoCiYeH                     ScrollMode::WrapMove => todo!(),
510*52da9a59SGnoCiYeH                     ScrollMode::Redraw => {
511*52da9a59SGnoCiYeH                         // self.scroll_redraw(
512*52da9a59SGnoCiYeH                         //     vc_data,
513*52da9a59SGnoCiYeH                         //     bottom - 1,
514*52da9a59SGnoCiYeH                         //     bottom - top - count,
515*52da9a59SGnoCiYeH                         //     count * vc_data.cols,
516*52da9a59SGnoCiYeH                         //     false,
517*52da9a59SGnoCiYeH                         // );
518*52da9a59SGnoCiYeH 
519*52da9a59SGnoCiYeH                         let _ = self.con_clear(vc_data, top, 0, count, vc_data.cols);
520*52da9a59SGnoCiYeH 
521*52da9a59SGnoCiYeH                         let offset = vc_data.cols * top;
522*52da9a59SGnoCiYeH                         for i in
523*52da9a59SGnoCiYeH                             vc_data.screen_buf[offset..(offset + (vc_data.cols * count))].iter_mut()
524*52da9a59SGnoCiYeH                         {
525*52da9a59SGnoCiYeH                             *i = vc_data.erase_char;
526*52da9a59SGnoCiYeH                         }
527*52da9a59SGnoCiYeH 
528*52da9a59SGnoCiYeH                         return true;
529*52da9a59SGnoCiYeH                     }
530*52da9a59SGnoCiYeH                     ScrollMode::PanRedraw => todo!(),
531*52da9a59SGnoCiYeH                 }
532*52da9a59SGnoCiYeH             }
533*52da9a59SGnoCiYeH         }
534*52da9a59SGnoCiYeH     }
535*52da9a59SGnoCiYeH }
536*52da9a59SGnoCiYeH 
537*52da9a59SGnoCiYeH impl FrameBufferConsole for BlittingFbConsole {
538*52da9a59SGnoCiYeH     fn bmove(
539*52da9a59SGnoCiYeH         &self,
540*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
541*52da9a59SGnoCiYeH         sy: i32,
542*52da9a59SGnoCiYeH         sx: i32,
543*52da9a59SGnoCiYeH         dy: i32,
544*52da9a59SGnoCiYeH         dx: i32,
545*52da9a59SGnoCiYeH         height: u32,
546*52da9a59SGnoCiYeH         width: u32,
547*52da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
548*52da9a59SGnoCiYeH         let area = CopyAreaData::new(
549*52da9a59SGnoCiYeH             dx * vc_data.font.width as i32,
550*52da9a59SGnoCiYeH             dy * vc_data.font.height as i32,
551*52da9a59SGnoCiYeH             width * vc_data.font.width,
552*52da9a59SGnoCiYeH             height * vc_data.font.height,
553*52da9a59SGnoCiYeH             sx * vc_data.font.width as i32,
554*52da9a59SGnoCiYeH             sy * vc_data.font.height as i32,
555*52da9a59SGnoCiYeH         );
556*52da9a59SGnoCiYeH 
557*52da9a59SGnoCiYeH         self.fb().fb_copyarea(area)
558*52da9a59SGnoCiYeH     }
559*52da9a59SGnoCiYeH 
560*52da9a59SGnoCiYeH     fn clear(
561*52da9a59SGnoCiYeH         &self,
562*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
563*52da9a59SGnoCiYeH         sy: u32,
564*52da9a59SGnoCiYeH         sx: u32,
565*52da9a59SGnoCiYeH         height: u32,
566*52da9a59SGnoCiYeH         width: u32,
567*52da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
568*52da9a59SGnoCiYeH         let region = FillRectData::new(
569*52da9a59SGnoCiYeH             sx * vc_data.font.width,
570*52da9a59SGnoCiYeH             sy * vc_data.font.height,
571*52da9a59SGnoCiYeH             width * vc_data.font.width,
572*52da9a59SGnoCiYeH             height * vc_data.font.height,
573*52da9a59SGnoCiYeH             self.get_color(vc_data, vc_data.erase_char, false),
574*52da9a59SGnoCiYeH             FillRectROP::Copy,
575*52da9a59SGnoCiYeH         );
576*52da9a59SGnoCiYeH 
577*52da9a59SGnoCiYeH         self.fb().fb_fillrect(region)?;
578*52da9a59SGnoCiYeH 
579*52da9a59SGnoCiYeH         Ok(())
580*52da9a59SGnoCiYeH     }
581*52da9a59SGnoCiYeH 
582*52da9a59SGnoCiYeH     fn put_string(
583*52da9a59SGnoCiYeH         &self,
584*52da9a59SGnoCiYeH         vc_data: &VirtualConsoleData,
585*52da9a59SGnoCiYeH         data: &[u16],
586*52da9a59SGnoCiYeH         mut count: u32,
587*52da9a59SGnoCiYeH         y: u32,
588*52da9a59SGnoCiYeH         x: u32,
589*52da9a59SGnoCiYeH         fg: u32,
590*52da9a59SGnoCiYeH         bg: u32,
591*52da9a59SGnoCiYeH     ) -> Result<(), SystemError> {
592*52da9a59SGnoCiYeH         // 向上取整
593*52da9a59SGnoCiYeH         let width = (vc_data.font.width + 7) / 8;
594*52da9a59SGnoCiYeH         let cellsize = width * vc_data.font.height;
595*52da9a59SGnoCiYeH         let fb_info = self.fb();
596*52da9a59SGnoCiYeH         // 一次能输出的最大字数,避免帧缓冲区溢出
597*52da9a59SGnoCiYeH         let max_cnt = (fb_info.current_fb_var().xres * fb_info.current_fb_var().yres) / cellsize;
598*52da9a59SGnoCiYeH         let attr = FbConAttr::get_attr(data[0], fb_info.color_depth());
599*52da9a59SGnoCiYeH 
600*52da9a59SGnoCiYeH         let mut image = FbImage {
601*52da9a59SGnoCiYeH             x: x * vc_data.font.width,
602*52da9a59SGnoCiYeH             y: y * vc_data.font.height,
603*52da9a59SGnoCiYeH             width: 0,
604*52da9a59SGnoCiYeH             height: vc_data.font.height,
605*52da9a59SGnoCiYeH             fg,
606*52da9a59SGnoCiYeH             bg,
607*52da9a59SGnoCiYeH             depth: 1,
608*52da9a59SGnoCiYeH             data: Default::default(),
609*52da9a59SGnoCiYeH         };
610*52da9a59SGnoCiYeH 
611*52da9a59SGnoCiYeH         image.data.resize(cellsize as usize * count as usize, 0);
612*52da9a59SGnoCiYeH 
613*52da9a59SGnoCiYeH         while count > 0 {
614*52da9a59SGnoCiYeH             let cnt = count.min(max_cnt);
615*52da9a59SGnoCiYeH 
616*52da9a59SGnoCiYeH             image.width = vc_data.font.width * cnt;
617*52da9a59SGnoCiYeH 
618*52da9a59SGnoCiYeH             self.bit_put_string(vc_data, data, attr, cnt, cellsize, &mut image);
619*52da9a59SGnoCiYeH 
620*52da9a59SGnoCiYeH             image.x += cnt * vc_data.font.width;
621*52da9a59SGnoCiYeH             count -= cnt;
622*52da9a59SGnoCiYeH         }
623*52da9a59SGnoCiYeH 
624*52da9a59SGnoCiYeH         Ok(())
625*52da9a59SGnoCiYeH     }
626*52da9a59SGnoCiYeH 
627*52da9a59SGnoCiYeH     fn fbcon_data(&self) -> SpinLockGuard<super::FrameBufferConsoleData> {
628*52da9a59SGnoCiYeH         self.fbcon_data.lock()
629*52da9a59SGnoCiYeH     }
630*52da9a59SGnoCiYeH 
631*52da9a59SGnoCiYeH     fn cursor(&self, vc_data: &VirtualConsoleData, op: CursorOperation, fg: u32, bg: u32) {
632*52da9a59SGnoCiYeH         let mut fbcon_data = self.fbcon_data();
633*52da9a59SGnoCiYeH         let fb_info = self.fb();
634*52da9a59SGnoCiYeH         let mut cursor = FbCursor::default();
635*52da9a59SGnoCiYeH         let charmask = if vc_data.hi_font_mask != 0 {
636*52da9a59SGnoCiYeH             0x1ff
637*52da9a59SGnoCiYeH         } else {
638*52da9a59SGnoCiYeH             0xff
639*52da9a59SGnoCiYeH         };
640*52da9a59SGnoCiYeH 
641*52da9a59SGnoCiYeH         // 向上取整
642*52da9a59SGnoCiYeH         let w = (vc_data.font.width + 7) / 8;
643*52da9a59SGnoCiYeH         let y = fbcon_data.display.real_y(vc_data.state.y as u32);
644*52da9a59SGnoCiYeH 
645*52da9a59SGnoCiYeH         let c = vc_data.screen_buf[vc_data.pos];
646*52da9a59SGnoCiYeH         let attr = FbConAttr::get_attr(c, fb_info.color_depth());
647*52da9a59SGnoCiYeH         let char_offset = (c as usize & charmask) * ((w * vc_data.font.height) as usize);
648*52da9a59SGnoCiYeH 
649*52da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.data != &vc_data.font.data[char_offset..]
650*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
651*52da9a59SGnoCiYeH         {
652*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.data = vc_data.font.data[char_offset..].to_vec();
653*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETIMAGE);
654*52da9a59SGnoCiYeH         }
655*52da9a59SGnoCiYeH 
656*52da9a59SGnoCiYeH         if !attr.is_empty() {
657*52da9a59SGnoCiYeH             fbcon_data
658*52da9a59SGnoCiYeH                 .cursor_data
659*52da9a59SGnoCiYeH                 .resize(w as usize * vc_data.font.height as usize, 0);
660*52da9a59SGnoCiYeH 
661*52da9a59SGnoCiYeH             attr.update_attr(
662*52da9a59SGnoCiYeH                 &mut fbcon_data.cursor_data,
663*52da9a59SGnoCiYeH                 &vc_data.font.data[char_offset..],
664*52da9a59SGnoCiYeH                 vc_data,
665*52da9a59SGnoCiYeH             );
666*52da9a59SGnoCiYeH         }
667*52da9a59SGnoCiYeH 
668*52da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.fg != fg
669*52da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.bg != bg
670*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
671*52da9a59SGnoCiYeH         {
672*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.fg = fg;
673*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.bg = bg;
674*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETCMAP);
675*52da9a59SGnoCiYeH         }
676*52da9a59SGnoCiYeH 
677*52da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.x != (vc_data.font.width * vc_data.state.x as u32)
678*52da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.y != (vc_data.font.height * y)
679*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
680*52da9a59SGnoCiYeH         {
681*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.x = vc_data.font.width * vc_data.state.x as u32;
682*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.y = vc_data.font.height * y;
683*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETPOS);
684*52da9a59SGnoCiYeH         }
685*52da9a59SGnoCiYeH 
686*52da9a59SGnoCiYeH         if fbcon_data.cursor_state.image.height != vc_data.font.height
687*52da9a59SGnoCiYeH             || fbcon_data.cursor_state.image.width != vc_data.font.width
688*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
689*52da9a59SGnoCiYeH         {
690*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.height = vc_data.font.height;
691*52da9a59SGnoCiYeH             fbcon_data.cursor_state.image.width = vc_data.font.width;
692*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSIZE);
693*52da9a59SGnoCiYeH         }
694*52da9a59SGnoCiYeH 
695*52da9a59SGnoCiYeH         if fbcon_data.cursor_state.hot_x > 0
696*52da9a59SGnoCiYeH             || fbcon_data.cursor_state.hot_y > 0
697*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
698*52da9a59SGnoCiYeH         {
699*52da9a59SGnoCiYeH             fbcon_data.cursor_state.hot_x = 0;
700*52da9a59SGnoCiYeH             cursor.hot_y = 0;
701*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETHOT);
702*52da9a59SGnoCiYeH         }
703*52da9a59SGnoCiYeH 
704*52da9a59SGnoCiYeH         if cursor.set_mode.contains(FbCursorSetMode::FB_CUR_SETSIZE)
705*52da9a59SGnoCiYeH             || vc_data.cursor_type != fbcon_data.display.cursor_shape
706*52da9a59SGnoCiYeH             || fbcon_data.cursor_state.mask.is_empty()
707*52da9a59SGnoCiYeH             || fbcon_data.cursor_reset
708*52da9a59SGnoCiYeH         {
709*52da9a59SGnoCiYeH             fbcon_data.display.cursor_shape = vc_data.cursor_type;
710*52da9a59SGnoCiYeH             cursor.set_mode.insert(FbCursorSetMode::FB_CUR_SETSHAPE);
711*52da9a59SGnoCiYeH 
712*52da9a59SGnoCiYeH             let cur_height;
713*52da9a59SGnoCiYeH             match fbcon_data.display.cursor_shape.cursor_size() {
714*52da9a59SGnoCiYeH                 VcCursor::CUR_NONE => {
715*52da9a59SGnoCiYeH                     cur_height = 0;
716*52da9a59SGnoCiYeH                 }
717*52da9a59SGnoCiYeH                 VcCursor::CUR_UNDERLINE => {
718*52da9a59SGnoCiYeH                     if vc_data.font.height < 10 {
719*52da9a59SGnoCiYeH                         cur_height = 1;
720*52da9a59SGnoCiYeH                     } else {
721*52da9a59SGnoCiYeH                         cur_height = 2;
722*52da9a59SGnoCiYeH                     }
723*52da9a59SGnoCiYeH                 }
724*52da9a59SGnoCiYeH                 VcCursor::CUR_LOWER_THIRD => {
725*52da9a59SGnoCiYeH                     cur_height = vc_data.font.height / 3;
726*52da9a59SGnoCiYeH                 }
727*52da9a59SGnoCiYeH                 VcCursor::CUR_LOWER_HALF => {
728*52da9a59SGnoCiYeH                     cur_height = vc_data.font.height >> 1;
729*52da9a59SGnoCiYeH                 }
730*52da9a59SGnoCiYeH                 VcCursor::CUR_TWO_THIRDS => {
731*52da9a59SGnoCiYeH                     cur_height = (vc_data.font.height << 1) / 3;
732*52da9a59SGnoCiYeH                 }
733*52da9a59SGnoCiYeH                 _ => {
734*52da9a59SGnoCiYeH                     cur_height = vc_data.font.height;
735*52da9a59SGnoCiYeH                 }
736*52da9a59SGnoCiYeH             }
737*52da9a59SGnoCiYeH 
738*52da9a59SGnoCiYeH             // 表示空白部分
739*52da9a59SGnoCiYeH             let mut size = (vc_data.font.height - cur_height) * w;
740*52da9a59SGnoCiYeH             while size > 0 {
741*52da9a59SGnoCiYeH                 size -= 1;
742*52da9a59SGnoCiYeH                 fbcon_data.cursor_state.mask.push(0x00);
743*52da9a59SGnoCiYeH             }
744*52da9a59SGnoCiYeH             size = cur_height * w;
745*52da9a59SGnoCiYeH             // 表示光标显示部分
746*52da9a59SGnoCiYeH             while size > 0 {
747*52da9a59SGnoCiYeH                 size -= 1;
748*52da9a59SGnoCiYeH                 fbcon_data.cursor_state.mask.push(0xff);
749*52da9a59SGnoCiYeH             }
750*52da9a59SGnoCiYeH         }
751*52da9a59SGnoCiYeH 
752*52da9a59SGnoCiYeH         match op {
753*52da9a59SGnoCiYeH             CursorOperation::Erase => {
754*52da9a59SGnoCiYeH                 fbcon_data.cursor_state.enable = false;
755*52da9a59SGnoCiYeH             }
756*52da9a59SGnoCiYeH             _ => {
757*52da9a59SGnoCiYeH                 fbcon_data.cursor_state.enable = !vc_data.cursor_type.contains(VcCursor::CUR_SW);
758*52da9a59SGnoCiYeH             }
759*52da9a59SGnoCiYeH         }
760*52da9a59SGnoCiYeH 
761*52da9a59SGnoCiYeH         if !attr.is_empty() {
762*52da9a59SGnoCiYeH             cursor.image.data = fbcon_data.cursor_data.clone();
763*52da9a59SGnoCiYeH         } else {
764*52da9a59SGnoCiYeH             cursor.image.data = vc_data.font.data
765*52da9a59SGnoCiYeH                 [char_offset..char_offset + (w as usize * vc_data.font.height as usize)]
766*52da9a59SGnoCiYeH                 .to_vec();
767*52da9a59SGnoCiYeH         }
768*52da9a59SGnoCiYeH         cursor.image.fg = fbcon_data.cursor_state.image.fg;
769*52da9a59SGnoCiYeH         cursor.image.bg = fbcon_data.cursor_state.image.bg;
770*52da9a59SGnoCiYeH         cursor.image.x = fbcon_data.cursor_state.image.x;
771*52da9a59SGnoCiYeH         cursor.image.y = fbcon_data.cursor_state.image.y;
772*52da9a59SGnoCiYeH         cursor.image.height = fbcon_data.cursor_state.image.height;
773*52da9a59SGnoCiYeH         cursor.image.width = fbcon_data.cursor_state.image.width;
774*52da9a59SGnoCiYeH         cursor.hot_x = fbcon_data.cursor_state.hot_x;
775*52da9a59SGnoCiYeH         cursor.hot_y = fbcon_data.cursor_state.hot_y;
776*52da9a59SGnoCiYeH         cursor.mask = fbcon_data.cursor_state.mask.clone();
777*52da9a59SGnoCiYeH         cursor.enable = fbcon_data.cursor_state.enable;
778*52da9a59SGnoCiYeH         cursor.image.depth = 1;
779*52da9a59SGnoCiYeH         cursor.rop = true;
780*52da9a59SGnoCiYeH 
781*52da9a59SGnoCiYeH         if fb_info.fb_cursor(&cursor).is_err() {
782*52da9a59SGnoCiYeH             let _ = fb_info.soft_cursor(cursor);
783*52da9a59SGnoCiYeH         }
784*52da9a59SGnoCiYeH 
785*52da9a59SGnoCiYeH         fbcon_data.cursor_reset = false;
786*52da9a59SGnoCiYeH     }
787*52da9a59SGnoCiYeH }
788