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