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