xref: /DragonOS/kernel/src/libs/lib_ui/screen_manager.rs (revision 2b7818e80e00fcfe4d03533f587cc125ea5e4bec)
1abe3a6eaShanjiezhou use core::{
2abe3a6eaShanjiezhou     fmt::Debug,
3abe3a6eaShanjiezhou     intrinsics::unlikely,
4abe3a6eaShanjiezhou     sync::atomic::{AtomicBool, AtomicU32, Ordering},
5abe3a6eaShanjiezhou };
6abe3a6eaShanjiezhou 
7abe3a6eaShanjiezhou use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
891e9d4abSLoGin use system_error::SystemError;
9abe3a6eaShanjiezhou 
10abe3a6eaShanjiezhou use crate::{
1152da9a59SGnoCiYeH     driver::{serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager},
121a72a751SLoGin     libs::{lib_ui::textui::textui_is_enable_put_to_window, rwlock::RwLock, spinlock::SpinLock},
13*2b7818e8SLoGin     mm::{mmio_buddy::MMIOSpaceGuard, VirtAddr},
14abe3a6eaShanjiezhou };
15abe3a6eaShanjiezhou 
161a72a751SLoGin use super::{
171a72a751SLoGin     textui::{textui_disable_put_to_window, textui_enable_put_to_window},
181a72a751SLoGin     textui_no_alloc::textui_init_no_alloc,
191a72a751SLoGin };
20abe3a6eaShanjiezhou 
21abe3a6eaShanjiezhou /// 全局的UI框架列表
221496ba7bSLoGin pub static SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> =
23abe3a6eaShanjiezhou     SpinLock::new(LinkedList::new());
24abe3a6eaShanjiezhou 
251496ba7bSLoGin /// 当前在使用的UI框架
261496ba7bSLoGin pub static CURRENT_FRAMEWORK: RwLock<Option<Arc<dyn ScmUiFramework>>> = RwLock::new(None);
27abe3a6eaShanjiezhou 
28abe3a6eaShanjiezhou /// 是否启用双缓冲
29abe3a6eaShanjiezhou pub static SCM_DOUBLE_BUFFER_ENABLED: AtomicBool = AtomicBool::new(false);
30abe3a6eaShanjiezhou 
31abe3a6eaShanjiezhou bitflags! {
32abe3a6eaShanjiezhou   pub struct ScmBufferFlag:u8 {
33abe3a6eaShanjiezhou     // 帧缓冲区标志位
34abe3a6eaShanjiezhou        const SCM_BF_FB = 1 << 0; // 当前buffer是设备显存中的帧缓冲区
35abe3a6eaShanjiezhou        const SCM_BF_DB = 1 << 1; // 当前buffer是双缓冲
36abe3a6eaShanjiezhou        const SCM_BF_TEXT = 1 << 2; // 使用文本模式
37abe3a6eaShanjiezhou        const SCM_BF_PIXEL = 1 << 3; // 使用图像模式
38abe3a6eaShanjiezhou    }
39abe3a6eaShanjiezhou }
40abe3a6eaShanjiezhou #[derive(Clone, Debug)]
41abe3a6eaShanjiezhou #[allow(dead_code)]
42abe3a6eaShanjiezhou pub enum ScmFramworkType {
43abe3a6eaShanjiezhou     Text,
44abe3a6eaShanjiezhou     Gui,
45abe3a6eaShanjiezhou     Unused,
46abe3a6eaShanjiezhou }
471496ba7bSLoGin #[derive(Debug, Clone)]
48abe3a6eaShanjiezhou pub enum ScmBuffer {
491496ba7bSLoGin     DeviceBuffer(VirtAddr),
502755467cS曾俊     DoubleBuffer(Arc<SpinLock<Box<[u8]>>>),
51abe3a6eaShanjiezhou }
521496ba7bSLoGin 
531496ba7bSLoGin #[derive(Debug, Clone)]
54abe3a6eaShanjiezhou pub struct ScmBufferInfo {
55abe3a6eaShanjiezhou     width: u32,     // 帧缓冲区宽度(pixel或columns)
56abe3a6eaShanjiezhou     height: u32,    // 帧缓冲区高度(pixel或lines)
57abe3a6eaShanjiezhou     size: u32,      // 帧缓冲区大小(bytes)
58abe3a6eaShanjiezhou     bit_depth: u32, // 像素点位深度
59*2b7818e8SLoGin     device_buffer_mmio_guard: Option<Arc<MMIOSpaceGuard>>,
60abe3a6eaShanjiezhou     pub buf: ScmBuffer,
61abe3a6eaShanjiezhou     flags: ScmBufferFlag, // 帧缓冲区标志位
62abe3a6eaShanjiezhou }
63abe3a6eaShanjiezhou 
641496ba7bSLoGin #[allow(dead_code)]
65abe3a6eaShanjiezhou impl ScmBufferInfo {
66abe3a6eaShanjiezhou     /// 创建新的帧缓冲区信息
67abe3a6eaShanjiezhou     ///
68abe3a6eaShanjiezhou     /// ## 参数
69abe3a6eaShanjiezhou     ///
70abe3a6eaShanjiezhou     /// - `buf_type` 帧缓冲区类型
71abe3a6eaShanjiezhou     ///
72abe3a6eaShanjiezhou     /// ## 返回值
73abe3a6eaShanjiezhou     ///
74abe3a6eaShanjiezhou     /// - `Result<Self, SystemError>` 创建成功返回新的帧缓冲区结构体,创建失败返回错误码
751496ba7bSLoGin     pub fn new(mut buf_type: ScmBufferFlag) -> Result<Self, SystemError> {
76b5b571e0SLoGin         if unlikely(!SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst)) {
771496ba7bSLoGin             let mut device_buffer = video_refresh_manager().device_buffer().clone();
781496ba7bSLoGin             buf_type.remove(ScmBufferFlag::SCM_BF_DB);
791496ba7bSLoGin             buf_type.insert(ScmBufferFlag::SCM_BF_FB);
801496ba7bSLoGin             device_buffer.flags = buf_type;
811496ba7bSLoGin             return Ok(device_buffer);
82abe3a6eaShanjiezhou         } else {
831496ba7bSLoGin             let device_buffer_guard = video_refresh_manager().device_buffer();
84abe3a6eaShanjiezhou 
852755467cS曾俊             let buf_space: Arc<SpinLock<Box<[u8]>>> = Arc::new(SpinLock::new(
862755467cS曾俊                 vec![0u8; (device_buffer_guard.size / 4) as usize].into_boxed_slice(),
87abe3a6eaShanjiezhou             ));
88abe3a6eaShanjiezhou 
891496ba7bSLoGin             assert!(buf_type.contains(ScmBufferFlag::SCM_BF_DB));
90abe3a6eaShanjiezhou 
911496ba7bSLoGin             assert_eq!(
921496ba7bSLoGin                 device_buffer_guard.size as usize,
932755467cS曾俊                 buf_space.lock().len() * core::mem::size_of::<u8>()
941496ba7bSLoGin             );
95abe3a6eaShanjiezhou 
961496ba7bSLoGin             // 创建双缓冲区
971496ba7bSLoGin             let buffer = Self {
981496ba7bSLoGin                 width: device_buffer_guard.width,
991496ba7bSLoGin                 height: device_buffer_guard.height,
1001496ba7bSLoGin                 size: device_buffer_guard.size,
1011496ba7bSLoGin                 bit_depth: device_buffer_guard.bit_depth,
1021496ba7bSLoGin                 flags: buf_type,
1031496ba7bSLoGin                 buf: ScmBuffer::DoubleBuffer(buf_space),
104*2b7818e8SLoGin                 device_buffer_mmio_guard: None,
105abe3a6eaShanjiezhou             };
1061496ba7bSLoGin             drop(device_buffer_guard);
1071496ba7bSLoGin 
1081496ba7bSLoGin             return Ok(buffer);
109abe3a6eaShanjiezhou         }
110abe3a6eaShanjiezhou     }
1111496ba7bSLoGin 
112*2b7818e8SLoGin     pub unsafe fn set_device_buffer_mmio_guard(&mut self, guard: Arc<MMIOSpaceGuard>) {
113*2b7818e8SLoGin         self.device_buffer_mmio_guard = Some(guard);
114*2b7818e8SLoGin     }
115*2b7818e8SLoGin 
1161496ba7bSLoGin     pub unsafe fn new_device_buffer(
1171496ba7bSLoGin         width: u32,
1181496ba7bSLoGin         height: u32,
1191496ba7bSLoGin         size: u32,
1201496ba7bSLoGin         bit_depth: u32,
1211496ba7bSLoGin         buf_type: ScmBufferFlag,
1221496ba7bSLoGin         vaddr: VirtAddr,
123*2b7818e8SLoGin         mut device_buffer_mmio_guard: Option<MMIOSpaceGuard>,
1241496ba7bSLoGin     ) -> Result<Self, SystemError> {
125*2b7818e8SLoGin         let mmio_guard = device_buffer_mmio_guard.take().map(Arc::new);
1261496ba7bSLoGin         let buffer = Self {
1271496ba7bSLoGin             width,
1281496ba7bSLoGin             height,
1291496ba7bSLoGin             size,
1301496ba7bSLoGin             bit_depth,
1311496ba7bSLoGin             flags: buf_type,
1321496ba7bSLoGin             buf: ScmBuffer::DeviceBuffer(vaddr),
133*2b7818e8SLoGin             device_buffer_mmio_guard: mmio_guard,
1341496ba7bSLoGin         };
1351496ba7bSLoGin         return Ok(buffer);
136abe3a6eaShanjiezhou     }
1371496ba7bSLoGin 
1381496ba7bSLoGin     pub fn buf_size(&self) -> usize {
1391496ba7bSLoGin         self.size as usize
1401496ba7bSLoGin     }
1411496ba7bSLoGin 
1421496ba7bSLoGin     pub fn bit_depth(&self) -> u32 {
1431496ba7bSLoGin         self.bit_depth
1441496ba7bSLoGin     }
1451496ba7bSLoGin 
1461496ba7bSLoGin     pub fn height(&self) -> u32 {
147abe3a6eaShanjiezhou         self.height
148abe3a6eaShanjiezhou     }
1491496ba7bSLoGin 
1501496ba7bSLoGin     pub fn width(&self) -> u32 {
151abe3a6eaShanjiezhou         self.width
152abe3a6eaShanjiezhou     }
1531496ba7bSLoGin 
154abe3a6eaShanjiezhou     pub fn is_double_buffer(&self) -> bool {
155b5b571e0SLoGin         matches!(&self.buf, ScmBuffer::DoubleBuffer(_))
156abe3a6eaShanjiezhou     }
157abe3a6eaShanjiezhou     pub fn is_device_buffer(&self) -> bool {
158b5b571e0SLoGin         matches!(&self.buf, ScmBuffer::DeviceBuffer(_))
159abe3a6eaShanjiezhou     }
1601496ba7bSLoGin 
1611496ba7bSLoGin     pub fn copy_from_nonoverlapping(&mut self, src: &ScmBufferInfo) {
1621496ba7bSLoGin         assert!(self.buf_size() == src.buf_size());
1631496ba7bSLoGin         match &self.buf {
1641496ba7bSLoGin             ScmBuffer::DeviceBuffer(vaddr) => {
1651496ba7bSLoGin                 let len = self.buf_size() / core::mem::size_of::<u32>();
1661496ba7bSLoGin                 let self_buf_guard =
1672755467cS曾俊                     unsafe { core::slice::from_raw_parts_mut(vaddr.data() as *mut u8, len) };
1681496ba7bSLoGin                 match &src.buf {
1691496ba7bSLoGin                     ScmBuffer::DeviceBuffer(vaddr) => {
1701496ba7bSLoGin                         let src_buf_guard =
1712755467cS曾俊                             unsafe { core::slice::from_raw_parts(vaddr.data() as *const u8, len) };
1721496ba7bSLoGin                         self_buf_guard.copy_from_slice(src_buf_guard);
1731496ba7bSLoGin                     }
1741496ba7bSLoGin                     ScmBuffer::DoubleBuffer(double_buffer) => {
1751496ba7bSLoGin                         let src_buf_guard = double_buffer.lock();
1761496ba7bSLoGin                         self_buf_guard.copy_from_slice(src_buf_guard.as_ref());
1771496ba7bSLoGin                     }
1781496ba7bSLoGin                 };
179abe3a6eaShanjiezhou             }
180abe3a6eaShanjiezhou 
1811496ba7bSLoGin             ScmBuffer::DoubleBuffer(double_buffer) => {
1821496ba7bSLoGin                 let mut double_buffer_guard = double_buffer.lock();
1831496ba7bSLoGin                 match &src.buf {
1841496ba7bSLoGin                     ScmBuffer::DeviceBuffer(vaddr) => {
1852755467cS曾俊                         let len = src.buf_size() / core::mem::size_of::<u8>();
1861496ba7bSLoGin                         double_buffer_guard.as_mut().copy_from_slice(unsafe {
1872755467cS曾俊                             core::slice::from_raw_parts(vaddr.data() as *const u8, len)
1881496ba7bSLoGin                         });
1891496ba7bSLoGin                     }
1901496ba7bSLoGin                     ScmBuffer::DoubleBuffer(double_buffer) => {
1911496ba7bSLoGin                         let x = double_buffer.lock();
1921496ba7bSLoGin                         double_buffer_guard.as_mut().copy_from_slice(x.as_ref());
1931496ba7bSLoGin                     }
1941496ba7bSLoGin                 };
195abe3a6eaShanjiezhou             }
196abe3a6eaShanjiezhou         }
197abe3a6eaShanjiezhou     }
198abe3a6eaShanjiezhou }
1991496ba7bSLoGin 
200abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
201abe3a6eaShanjiezhou pub struct ScmUiFrameworkId(u32);
202abe3a6eaShanjiezhou 
203abe3a6eaShanjiezhou impl ScmUiFrameworkId {
204abe3a6eaShanjiezhou     /// 分配一个新的框架id
205abe3a6eaShanjiezhou     pub fn new() -> Self {
206abe3a6eaShanjiezhou         static MAX_ID: AtomicU32 = AtomicU32::new(0);
207abe3a6eaShanjiezhou         return ScmUiFrameworkId(MAX_ID.fetch_add(1, Ordering::SeqCst));
208abe3a6eaShanjiezhou     }
209abe3a6eaShanjiezhou }
210abe3a6eaShanjiezhou #[allow(dead_code)]
211abe3a6eaShanjiezhou #[derive(Debug, Clone)]
212abe3a6eaShanjiezhou pub struct ScmUiFrameworkMetadata {
213abe3a6eaShanjiezhou     id: ScmUiFrameworkId,
214abe3a6eaShanjiezhou     name: String,
215abe3a6eaShanjiezhou     framework_type: ScmFramworkType,
216abe3a6eaShanjiezhou     pub buf_info: ScmBufferInfo,
217abe3a6eaShanjiezhou }
218abe3a6eaShanjiezhou 
219abe3a6eaShanjiezhou impl ScmUiFrameworkMetadata {
220abe3a6eaShanjiezhou     pub fn new(name: String, framework_type: ScmFramworkType) -> Self {
221abe3a6eaShanjiezhou         match framework_type {
222abe3a6eaShanjiezhou             ScmFramworkType::Text => {
223abe3a6eaShanjiezhou                 let result = ScmUiFrameworkMetadata {
224abe3a6eaShanjiezhou                     id: ScmUiFrameworkId::new(),
225abe3a6eaShanjiezhou                     name,
226abe3a6eaShanjiezhou                     framework_type: ScmFramworkType::Text,
2271496ba7bSLoGin                     buf_info: ScmBufferInfo::new(
2281496ba7bSLoGin                         ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_DB,
2291496ba7bSLoGin                     )
2301496ba7bSLoGin                     .unwrap(),
231abe3a6eaShanjiezhou                 };
232abe3a6eaShanjiezhou 
233abe3a6eaShanjiezhou                 return result;
234abe3a6eaShanjiezhou             }
235abe3a6eaShanjiezhou             ScmFramworkType::Gui => todo!(),
236abe3a6eaShanjiezhou             ScmFramworkType::Unused => todo!(),
237abe3a6eaShanjiezhou         }
238abe3a6eaShanjiezhou     }
239abe3a6eaShanjiezhou     pub fn buf_info(&self) -> ScmBufferInfo {
240abe3a6eaShanjiezhou         return self.buf_info.clone();
241abe3a6eaShanjiezhou     }
242abe3a6eaShanjiezhou     pub fn set_buf_info(&mut self, buf_info: ScmBufferInfo) {
243abe3a6eaShanjiezhou         self.buf_info = buf_info;
244abe3a6eaShanjiezhou     }
245abe3a6eaShanjiezhou }
246abe3a6eaShanjiezhou pub trait ScmUiFramework: Sync + Send + Debug {
247abe3a6eaShanjiezhou     // 安装ui框架的回调函数
248abe3a6eaShanjiezhou     fn install(&self) -> Result<i32, SystemError> {
2491074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
250abe3a6eaShanjiezhou     }
251abe3a6eaShanjiezhou     // 卸载ui框架的回调函数
252bd70d2d1SLoGin     #[allow(dead_code)]
253abe3a6eaShanjiezhou     fn uninstall(&self) -> Result<i32, SystemError> {
2541074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
255abe3a6eaShanjiezhou     }
256abe3a6eaShanjiezhou     // 启用ui框架的回调函数
257abe3a6eaShanjiezhou     fn enable(&self) -> Result<i32, SystemError> {
2581074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
259abe3a6eaShanjiezhou     }
260abe3a6eaShanjiezhou     // 禁用ui框架的回调函数
261abe3a6eaShanjiezhou     fn disable(&self) -> Result<i32, SystemError> {
2621074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
263abe3a6eaShanjiezhou     }
264abe3a6eaShanjiezhou     // 改变ui框架的帧缓冲区的回调函数
265abe3a6eaShanjiezhou     fn change(&self, _buf: ScmBufferInfo) -> Result<i32, SystemError> {
2661074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
267abe3a6eaShanjiezhou     }
268abe3a6eaShanjiezhou     /// @brief 获取ScmUiFramework的元数据
269abe3a6eaShanjiezhou     /// @return 成功:Ok(ScmUiFramework的元数据)
270abe3a6eaShanjiezhou     ///         失败:Err(错误码)
271abe3a6eaShanjiezhou     fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> {
272abe3a6eaShanjiezhou         // 若文件系统没有实现此方法,则返回“不支持”
2731074eb34SSamuel Dai         return Err(SystemError::ENOSYS);
274abe3a6eaShanjiezhou     }
275abe3a6eaShanjiezhou }
276abe3a6eaShanjiezhou 
277abe3a6eaShanjiezhou /// 初始化屏幕控制模块
278abe3a6eaShanjiezhou ///
279abe3a6eaShanjiezhou /// ## 调用时机
280abe3a6eaShanjiezhou ///
281abe3a6eaShanjiezhou /// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
2821a72a751SLoGin pub fn scm_init(enable_put_to_window: bool) {
283abe3a6eaShanjiezhou     SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
2841a72a751SLoGin     if enable_put_to_window {
2851a72a751SLoGin         textui_enable_put_to_window();
2861a72a751SLoGin     } else {
2871a72a751SLoGin         textui_disable_put_to_window();
2881a72a751SLoGin     }
2891a72a751SLoGin     textui_init_no_alloc(enable_put_to_window);
290abe3a6eaShanjiezhou 
291a03c4f9dSLoGin     send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes());
292abe3a6eaShanjiezhou }
293abe3a6eaShanjiezhou 
294abe3a6eaShanjiezhou /// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上
295abe3a6eaShanjiezhou /// ## 参数
296abe3a6eaShanjiezhou ///
297abe3a6eaShanjiezhou /// - framework 要启动的ui框架
298abe3a6eaShanjiezhou 
299abe3a6eaShanjiezhou pub fn scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
300abe3a6eaShanjiezhou     // 获取信息
301abe3a6eaShanjiezhou     let metadata = framework.metadata()?;
302abe3a6eaShanjiezhou 
303abe3a6eaShanjiezhou     // if metadata.buf_info.buf.is_null() {
304abe3a6eaShanjiezhou     //     return Err(SystemError::EINVAL);
305abe3a6eaShanjiezhou     // }
306abe3a6eaShanjiezhou     let mut current_framework = CURRENT_FRAMEWORK.write();
307abe3a6eaShanjiezhou 
308b5b571e0SLoGin     if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
3091496ba7bSLoGin         video_refresh_manager().set_refresh_target(&metadata.buf_info)?;
310abe3a6eaShanjiezhou     }
311abe3a6eaShanjiezhou 
3121496ba7bSLoGin     framework.enable()?;
313abe3a6eaShanjiezhou     current_framework.replace(framework);
314abe3a6eaShanjiezhou 
315abe3a6eaShanjiezhou     return Ok(0);
316abe3a6eaShanjiezhou }
317abe3a6eaShanjiezhou /// 向屏幕管理器注册UI框架
318abe3a6eaShanjiezhou ///
319abe3a6eaShanjiezhou /// ## 参数
320abe3a6eaShanjiezhou /// - framework 框架结构体
321abe3a6eaShanjiezhou 
322abe3a6eaShanjiezhou pub fn scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
323abe3a6eaShanjiezhou     // 把ui框架加入链表
324abe3a6eaShanjiezhou 
325abe3a6eaShanjiezhou     SCM_FRAMEWORK_LIST.lock().push_back(framework.clone());
326abe3a6eaShanjiezhou     // 调用ui框架的回调函数以安装ui框架,并将其激活
327abe3a6eaShanjiezhou     framework.install()?;
328abe3a6eaShanjiezhou 
329abe3a6eaShanjiezhou     // 如果当前还没有框架获得了屏幕的控制权,就让其拿去
330abe3a6eaShanjiezhou     if CURRENT_FRAMEWORK.read().is_none() {
331abe3a6eaShanjiezhou         return scm_framework_enable(framework);
332abe3a6eaShanjiezhou     }
333abe3a6eaShanjiezhou     return Ok(0);
334abe3a6eaShanjiezhou }
335abe3a6eaShanjiezhou 
3361496ba7bSLoGin /// 屏幕管理器启用双缓冲区
3371496ba7bSLoGin #[allow(dead_code)]
3381496ba7bSLoGin pub fn scm_enable_double_buffer() -> Result<i32, SystemError> {
339abe3a6eaShanjiezhou     if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
340abe3a6eaShanjiezhou         // 已经开启了双缓冲区了, 直接退出
341abe3a6eaShanjiezhou         return Ok(0);
342abe3a6eaShanjiezhou     }
343abe3a6eaShanjiezhou     let scm_list = SCM_FRAMEWORK_LIST.lock();
344abe3a6eaShanjiezhou     if scm_list.is_empty() {
345abe3a6eaShanjiezhou         // scm 框架链表为空
346abe3a6eaShanjiezhou         return Ok(0);
347abe3a6eaShanjiezhou     }
348abe3a6eaShanjiezhou     drop(scm_list);
349abe3a6eaShanjiezhou     SCM_DOUBLE_BUFFER_ENABLED.store(true, Ordering::SeqCst);
350abe3a6eaShanjiezhou     // 创建双缓冲区
3511496ba7bSLoGin     let buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
3521496ba7bSLoGin 
3531496ba7bSLoGin     // 设置定时刷新的对象
3541496ba7bSLoGin     video_refresh_manager()
3551496ba7bSLoGin         .set_refresh_target(&buf_info)
3561496ba7bSLoGin         .expect("set refresh target failed");
3571496ba7bSLoGin 
3581496ba7bSLoGin     // 设置当前框架的帧缓冲区
359abe3a6eaShanjiezhou     CURRENT_FRAMEWORK
360abe3a6eaShanjiezhou         .write()
361abe3a6eaShanjiezhou         .as_ref()
362abe3a6eaShanjiezhou         .unwrap()
363abe3a6eaShanjiezhou         .change(buf_info)?;
364abe3a6eaShanjiezhou     // 遍历当前所有使用帧缓冲区的框架,更新为双缓冲区
365abe3a6eaShanjiezhou     for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
366abe3a6eaShanjiezhou         if !(*framework).metadata()?.buf_info.is_double_buffer() {
367abe3a6eaShanjiezhou             let new_buf_info =
368abe3a6eaShanjiezhou                 ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
369abe3a6eaShanjiezhou             (*framework).change(new_buf_info)?;
370abe3a6eaShanjiezhou         }
371abe3a6eaShanjiezhou     }
372abe3a6eaShanjiezhou     // 通知显示驱动,启动双缓冲
3731496ba7bSLoGin     video_refresh_manager().video_reinitialize(true)?;
374abe3a6eaShanjiezhou 
375abe3a6eaShanjiezhou     return Ok(0);
376abe3a6eaShanjiezhou }
3771496ba7bSLoGin 
378abe3a6eaShanjiezhou /// 允许往窗口打印信息
379abe3a6eaShanjiezhou pub fn scm_enable_put_to_window() {
3801496ba7bSLoGin     // mm之前要继续往窗口打印信息时,因为没有动态内存分配(textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
381abe3a6eaShanjiezhou     if CURRENT_FRAMEWORK.read().is_none() {
3821a72a751SLoGin         textui_enable_put_to_window();
383abe3a6eaShanjiezhou     } else {
384abe3a6eaShanjiezhou         let r = CURRENT_FRAMEWORK
385abe3a6eaShanjiezhou             .write()
386abe3a6eaShanjiezhou             .as_ref()
387abe3a6eaShanjiezhou             .unwrap()
388abe3a6eaShanjiezhou             .enable()
389abe3a6eaShanjiezhou             .unwrap_or_else(|e| e.to_posix_errno());
390abe3a6eaShanjiezhou         if r.is_negative() {
391a03c4f9dSLoGin             send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
392abe3a6eaShanjiezhou         }
393abe3a6eaShanjiezhou     }
394abe3a6eaShanjiezhou }
395abe3a6eaShanjiezhou /// 禁止往窗口打印信息
396abe3a6eaShanjiezhou pub fn scm_disable_put_to_window() {
397abe3a6eaShanjiezhou     // mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
398abe3a6eaShanjiezhou     if CURRENT_FRAMEWORK.read().is_none() {
3991a72a751SLoGin         textui_disable_put_to_window();
400b5b571e0SLoGin         assert!(!textui_is_enable_put_to_window());
401abe3a6eaShanjiezhou     } else {
402abe3a6eaShanjiezhou         let r = CURRENT_FRAMEWORK
403abe3a6eaShanjiezhou             .write()
404abe3a6eaShanjiezhou             .as_ref()
405abe3a6eaShanjiezhou             .unwrap()
406abe3a6eaShanjiezhou             .disable()
407abe3a6eaShanjiezhou             .unwrap_or_else(|e| e.to_posix_errno());
408abe3a6eaShanjiezhou         if r.is_negative() {
409a03c4f9dSLoGin             send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
410abe3a6eaShanjiezhou         }
411abe3a6eaShanjiezhou     }
412abe3a6eaShanjiezhou }
413abe3a6eaShanjiezhou /// 当内存管理单元被初始化之后,重新处理帧缓冲区问题
4145b59005fSLoGin #[inline(never)]
4155b59005fSLoGin pub fn scm_reinit() -> Result<(), SystemError> {
416338f6903SLoGin     #[cfg(target_arch = "x86_64")]
417338f6903SLoGin     {
4185b59005fSLoGin         let r = true_scm_reinit();
4195b59005fSLoGin         if r.is_err() {
420a03c4f9dSLoGin             send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes());
421abe3a6eaShanjiezhou         }
422abe3a6eaShanjiezhou         return r;
423abe3a6eaShanjiezhou     }
424338f6903SLoGin 
425338f6903SLoGin     #[cfg(not(target_arch = "x86_64"))]
426338f6903SLoGin     {
427338f6903SLoGin         return Ok(());
428338f6903SLoGin     }
429338f6903SLoGin }
430338f6903SLoGin 
431338f6903SLoGin #[allow(dead_code)]
4325b59005fSLoGin fn true_scm_reinit() -> Result<(), SystemError> {
4331496ba7bSLoGin     video_refresh_manager()
4341496ba7bSLoGin         .video_reinitialize(false)
4351496ba7bSLoGin         .expect("video reinitialize failed");
436abe3a6eaShanjiezhou 
437abe3a6eaShanjiezhou     // 遍历当前所有使用帧缓冲区的框架,更新地址
4381496ba7bSLoGin     let device_buffer = video_refresh_manager().device_buffer().clone();
439abe3a6eaShanjiezhou     for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
440abe3a6eaShanjiezhou         if framework.metadata()?.buf_info().is_device_buffer() {
4411496ba7bSLoGin             framework.change(device_buffer.clone())?;
442abe3a6eaShanjiezhou         }
443abe3a6eaShanjiezhou     }
444abe3a6eaShanjiezhou 
445abe3a6eaShanjiezhou     scm_enable_put_to_window();
446abe3a6eaShanjiezhou 
4475b59005fSLoGin     return Ok(());
448abe3a6eaShanjiezhou }
449