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