framebuffer_console.rs 26 KB

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