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