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