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