xref: /DragonOS/kernel/src/libs/lib_ui/screen_manager.rs (revision c635d8a9cfe25bc11779f323ef0c7d7a0f597d4a)
1 use core::{
2     fmt::Debug,
3     intrinsics::unlikely,
4     sync::atomic::{AtomicBool, AtomicU32, Ordering},
5 };
6 
7 use alloc::{boxed::Box, collections::LinkedList, string::String, sync::Arc};
8 use system_error::SystemError;
9 
10 use crate::{
11     driver::{serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager},
12     libs::{lib_ui::textui::textui_is_enable_put_to_window, rwlock::RwLock, spinlock::SpinLock},
13     mm::{mmio_buddy::MMIOSpaceGuard, VirtAddr},
14 };
15 
16 use super::{
17     textui::{textui_disable_put_to_window, textui_enable_put_to_window},
18     textui_no_alloc::textui_init_no_alloc,
19 };
20 
21 /// 全局的UI框架列表
22 pub static SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> =
23     SpinLock::new(LinkedList::new());
24 
25 /// 当前在使用的UI框架
26 pub static CURRENT_FRAMEWORK: RwLock<Option<Arc<dyn ScmUiFramework>>> = RwLock::new(None);
27 
28 /// 是否启用双缓冲
29 pub static SCM_DOUBLE_BUFFER_ENABLED: AtomicBool = AtomicBool::new(false);
30 
31 bitflags! {
32   pub struct ScmBufferFlag:u8 {
33     // 帧缓冲区标志位
34        const SCM_BF_FB = 1 << 0; // 当前buffer是设备显存中的帧缓冲区
35        const SCM_BF_DB = 1 << 1; // 当前buffer是双缓冲
36        const SCM_BF_TEXT = 1 << 2; // 使用文本模式
37        const SCM_BF_PIXEL = 1 << 3; // 使用图像模式
38    }
39 }
40 #[derive(Clone, Debug)]
41 #[allow(dead_code)]
42 pub enum ScmFramworkType {
43     Text,
44     Gui,
45     Unused,
46 }
47 #[derive(Debug, Clone)]
48 pub enum ScmBuffer {
49     DeviceBuffer(VirtAddr),
50     DoubleBuffer(Arc<SpinLock<Box<[u8]>>>),
51 }
52 
53 #[derive(Debug, Clone)]
54 pub struct ScmBufferInfo {
55     width: u32,     // 帧缓冲区宽度(pixel或columns)
56     height: u32,    // 帧缓冲区高度(pixel或lines)
57     size: u32,      // 帧缓冲区大小(bytes)
58     bit_depth: u32, // 像素点位深度
59     device_buffer_mmio_guard: Option<Arc<MMIOSpaceGuard>>,
60     pub buf: ScmBuffer,
61     flags: ScmBufferFlag, // 帧缓冲区标志位
62 }
63 
64 #[allow(dead_code)]
65 impl ScmBufferInfo {
66     /// 创建新的帧缓冲区信息
67     ///
68     /// ## 参数
69     ///
70     /// - `buf_type` 帧缓冲区类型
71     ///
72     /// ## 返回值
73     ///
74     /// - `Result<Self, SystemError>` 创建成功返回新的帧缓冲区结构体,创建失败返回错误码
75     pub fn new(mut buf_type: ScmBufferFlag) -> Result<Self, SystemError> {
76         if unlikely(!SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst)) {
77             let mut device_buffer = video_refresh_manager().device_buffer().clone();
78             buf_type.remove(ScmBufferFlag::SCM_BF_DB);
79             buf_type.insert(ScmBufferFlag::SCM_BF_FB);
80             device_buffer.flags = buf_type;
81             return Ok(device_buffer);
82         } else {
83             let device_buffer_guard = video_refresh_manager().device_buffer();
84 
85             let buf_space: Arc<SpinLock<Box<[u8]>>> = Arc::new(SpinLock::new(
86                 vec![0u8; (device_buffer_guard.size / 4) as usize].into_boxed_slice(),
87             ));
88 
89             assert!(buf_type.contains(ScmBufferFlag::SCM_BF_DB));
90 
91             assert_eq!(
92                 device_buffer_guard.size as usize,
93                 buf_space.lock().len() * core::mem::size_of::<u8>()
94             );
95 
96             // 创建双缓冲区
97             let buffer = Self {
98                 width: device_buffer_guard.width,
99                 height: device_buffer_guard.height,
100                 size: device_buffer_guard.size,
101                 bit_depth: device_buffer_guard.bit_depth,
102                 flags: buf_type,
103                 buf: ScmBuffer::DoubleBuffer(buf_space),
104                 device_buffer_mmio_guard: None,
105             };
106             drop(device_buffer_guard);
107 
108             return Ok(buffer);
109         }
110     }
111 
112     pub unsafe fn set_device_buffer_mmio_guard(&mut self, guard: Arc<MMIOSpaceGuard>) {
113         self.device_buffer_mmio_guard = Some(guard);
114     }
115 
116     pub unsafe fn new_device_buffer(
117         width: u32,
118         height: u32,
119         size: u32,
120         bit_depth: u32,
121         buf_type: ScmBufferFlag,
122         vaddr: VirtAddr,
123         mut device_buffer_mmio_guard: Option<MMIOSpaceGuard>,
124     ) -> Result<Self, SystemError> {
125         let mmio_guard = device_buffer_mmio_guard.take().map(Arc::new);
126         let buffer = Self {
127             width,
128             height,
129             size,
130             bit_depth,
131             flags: buf_type,
132             buf: ScmBuffer::DeviceBuffer(vaddr),
133             device_buffer_mmio_guard: mmio_guard,
134         };
135         return Ok(buffer);
136     }
137 
138     pub fn buf_size(&self) -> usize {
139         self.size as usize
140     }
141 
142     pub fn bit_depth(&self) -> u32 {
143         self.bit_depth
144     }
145 
146     pub fn height(&self) -> u32 {
147         self.height
148     }
149 
150     pub fn width(&self) -> u32 {
151         self.width
152     }
153 
154     pub fn is_double_buffer(&self) -> bool {
155         matches!(&self.buf, ScmBuffer::DoubleBuffer(_))
156     }
157     pub fn is_device_buffer(&self) -> bool {
158         matches!(&self.buf, ScmBuffer::DeviceBuffer(_))
159     }
160 
161     pub fn copy_from_nonoverlapping(&mut self, src: &ScmBufferInfo) {
162         assert!(self.buf_size() == src.buf_size());
163         match &self.buf {
164             ScmBuffer::DeviceBuffer(vaddr) => {
165                 let len = self.buf_size() / core::mem::size_of::<u32>();
166                 let self_buf_guard =
167                     unsafe { core::slice::from_raw_parts_mut(vaddr.data() as *mut u8, len) };
168                 match &src.buf {
169                     ScmBuffer::DeviceBuffer(vaddr) => {
170                         let src_buf_guard =
171                             unsafe { core::slice::from_raw_parts(vaddr.data() as *const u8, len) };
172                         self_buf_guard.copy_from_slice(src_buf_guard);
173                     }
174                     ScmBuffer::DoubleBuffer(double_buffer) => {
175                         let src_buf_guard = double_buffer.lock();
176                         self_buf_guard.copy_from_slice(src_buf_guard.as_ref());
177                     }
178                 };
179             }
180 
181             ScmBuffer::DoubleBuffer(double_buffer) => {
182                 let mut double_buffer_guard = double_buffer.lock();
183                 match &src.buf {
184                     ScmBuffer::DeviceBuffer(vaddr) => {
185                         let len = src.buf_size() / core::mem::size_of::<u8>();
186                         double_buffer_guard.as_mut().copy_from_slice(unsafe {
187                             core::slice::from_raw_parts(vaddr.data() as *const u8, len)
188                         });
189                     }
190                     ScmBuffer::DoubleBuffer(double_buffer) => {
191                         let x = double_buffer.lock();
192                         double_buffer_guard.as_mut().copy_from_slice(x.as_ref());
193                     }
194                 };
195             }
196         }
197     }
198 }
199 
200 #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
201 pub struct ScmUiFrameworkId(u32);
202 
203 impl ScmUiFrameworkId {
204     /// 分配一个新的框架id
205     pub fn new() -> Self {
206         static MAX_ID: AtomicU32 = AtomicU32::new(0);
207         return ScmUiFrameworkId(MAX_ID.fetch_add(1, Ordering::SeqCst));
208     }
209 }
210 #[allow(dead_code)]
211 #[derive(Debug, Clone)]
212 pub struct ScmUiFrameworkMetadata {
213     id: ScmUiFrameworkId,
214     name: String,
215     framework_type: ScmFramworkType,
216     pub buf_info: ScmBufferInfo,
217 }
218 
219 impl ScmUiFrameworkMetadata {
220     pub fn new(name: String, framework_type: ScmFramworkType) -> Self {
221         match framework_type {
222             ScmFramworkType::Text => {
223                 let result = ScmUiFrameworkMetadata {
224                     id: ScmUiFrameworkId::new(),
225                     name,
226                     framework_type: ScmFramworkType::Text,
227                     buf_info: ScmBufferInfo::new(
228                         ScmBufferFlag::SCM_BF_TEXT | ScmBufferFlag::SCM_BF_DB,
229                     )
230                     .unwrap(),
231                 };
232 
233                 return result;
234             }
235             ScmFramworkType::Gui => todo!(),
236             ScmFramworkType::Unused => todo!(),
237         }
238     }
239     pub fn buf_info(&self) -> ScmBufferInfo {
240         return self.buf_info.clone();
241     }
242     pub fn set_buf_info(&mut self, buf_info: ScmBufferInfo) {
243         self.buf_info = buf_info;
244     }
245 }
246 pub trait ScmUiFramework: Sync + Send + Debug {
247     // 安装ui框架的回调函数
248     fn install(&self) -> Result<i32, SystemError> {
249         return Err(SystemError::ENOSYS);
250     }
251     // 卸载ui框架的回调函数
252     #[allow(dead_code)]
253     fn uninstall(&self) -> Result<i32, SystemError> {
254         return Err(SystemError::ENOSYS);
255     }
256     // 启用ui框架的回调函数
257     fn enable(&self) -> Result<i32, SystemError> {
258         return Err(SystemError::ENOSYS);
259     }
260     // 禁用ui框架的回调函数
261     fn disable(&self) -> Result<i32, SystemError> {
262         return Err(SystemError::ENOSYS);
263     }
264     // 改变ui框架的帧缓冲区的回调函数
265     fn change(&self, _buf: ScmBufferInfo) -> Result<i32, SystemError> {
266         return Err(SystemError::ENOSYS);
267     }
268     /// @brief 获取ScmUiFramework的元数据
269     /// @return 成功:Ok(ScmUiFramework的元数据)
270     ///         失败:Err(错误码)
271     fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> {
272         // 若文件系统没有实现此方法,则返回“不支持”
273         return Err(SystemError::ENOSYS);
274     }
275 }
276 
277 /// 初始化屏幕控制模块
278 ///
279 /// ## 调用时机
280 ///
281 /// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。
282 pub fn scm_init(enable_put_to_window: bool) {
283     SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲
284     if enable_put_to_window {
285         textui_enable_put_to_window();
286     } else {
287         textui_disable_put_to_window();
288     }
289     textui_init_no_alloc(enable_put_to_window);
290 
291     send_to_default_serial8250_port("\nfinish_scm_init\n\0".as_bytes());
292 }
293 
294 /// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上
295 /// ## 参数
296 ///
297 /// - framework 要启动的ui框架
298 
299 pub fn scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
300     // 获取信息
301     let metadata = framework.metadata()?;
302 
303     // if metadata.buf_info.buf.is_null() {
304     //     return Err(SystemError::EINVAL);
305     // }
306     let mut current_framework = CURRENT_FRAMEWORK.write();
307 
308     if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
309         video_refresh_manager().set_refresh_target(&metadata.buf_info)?;
310     }
311 
312     framework.enable()?;
313     current_framework.replace(framework);
314 
315     return Ok(0);
316 }
317 /// 向屏幕管理器注册UI框架
318 ///
319 /// ## 参数
320 /// - framework 框架结构体
321 
322 pub fn scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
323     // 把ui框架加入链表
324 
325     SCM_FRAMEWORK_LIST.lock().push_back(framework.clone());
326     // 调用ui框架的回调函数以安装ui框架,并将其激活
327     framework.install()?;
328 
329     // 如果当前还没有框架获得了屏幕的控制权,就让其拿去
330     if CURRENT_FRAMEWORK.read().is_none() {
331         return scm_framework_enable(framework);
332     }
333     return Ok(0);
334 }
335 
336 /// 屏幕管理器启用双缓冲区
337 #[allow(dead_code)]
338 pub fn scm_enable_double_buffer() -> Result<i32, SystemError> {
339     if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
340         // 已经开启了双缓冲区了, 直接退出
341         return Ok(0);
342     }
343     let scm_list = SCM_FRAMEWORK_LIST.lock();
344     if scm_list.is_empty() {
345         // scm 框架链表为空
346         return Ok(0);
347     }
348     drop(scm_list);
349     SCM_DOUBLE_BUFFER_ENABLED.store(true, Ordering::SeqCst);
350     // 创建双缓冲区
351     let buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
352 
353     // 设置定时刷新的对象
354     video_refresh_manager()
355         .set_refresh_target(&buf_info)
356         .expect("set refresh target failed");
357 
358     // 设置当前框架的帧缓冲区
359     CURRENT_FRAMEWORK
360         .write()
361         .as_ref()
362         .unwrap()
363         .change(buf_info)?;
364     // 遍历当前所有使用帧缓冲区的框架,更新为双缓冲区
365     for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
366         if !(*framework).metadata()?.buf_info.is_double_buffer() {
367             let new_buf_info =
368                 ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
369             (*framework).change(new_buf_info)?;
370         }
371     }
372     // 通知显示驱动,启动双缓冲
373     video_refresh_manager().video_reinitialize(true)?;
374 
375     return Ok(0);
376 }
377 
378 /// 允许往窗口打印信息
379 pub fn scm_enable_put_to_window() {
380     // mm之前要继续往窗口打印信息时,因为没有动态内存分配(textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
381     if CURRENT_FRAMEWORK.read().is_none() {
382         textui_enable_put_to_window();
383     } else {
384         let r = CURRENT_FRAMEWORK
385             .write()
386             .as_ref()
387             .unwrap()
388             .enable()
389             .unwrap_or_else(|e| e.to_posix_errno());
390         if r.is_negative() {
391             send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
392         }
393     }
394 }
395 /// 禁止往窗口打印信息
396 pub fn scm_disable_put_to_window() {
397     // mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
398     if CURRENT_FRAMEWORK.read().is_none() {
399         textui_disable_put_to_window();
400         assert!(!textui_is_enable_put_to_window());
401     } else {
402         let r = CURRENT_FRAMEWORK
403             .write()
404             .as_ref()
405             .unwrap()
406             .disable()
407             .unwrap_or_else(|e| e.to_posix_errno());
408         if r.is_negative() {
409             send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
410         }
411     }
412 }
413 /// 当内存管理单元被初始化之后,重新处理帧缓冲区问题
414 #[inline(never)]
415 pub fn scm_reinit() -> Result<(), SystemError> {
416     #[cfg(target_arch = "x86_64")]
417     {
418         let r = true_scm_reinit();
419         if r.is_err() {
420             send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes());
421         }
422         return r;
423     }
424 
425     #[cfg(not(target_arch = "x86_64"))]
426     {
427         return Ok(());
428     }
429 }
430 
431 #[allow(dead_code)]
432 fn true_scm_reinit() -> Result<(), SystemError> {
433     video_refresh_manager()
434         .video_reinitialize(false)
435         .expect("video reinitialize failed");
436 
437     // 遍历当前所有使用帧缓冲区的框架,更新地址
438     let device_buffer = video_refresh_manager().device_buffer().clone();
439     for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
440         if framework.metadata()?.buf_info().is_device_buffer() {
441             framework.change(device_buffer.clone())?;
442         }
443     }
444 
445     scm_enable_put_to_window();
446 
447     return Ok(());
448 }
449