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框架
301
scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError>302 pub fn scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
303 // 获取信息
304 let metadata = framework.metadata()?;
305
306 // if metadata.buf_info.buf.is_null() {
307 // return Err(SystemError::EINVAL);
308 // }
309 let mut current_framework = CURRENT_FRAMEWORK.write();
310
311 if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
312 video_refresh_manager().set_refresh_target(&metadata.buf_info)?;
313 }
314
315 framework.enable()?;
316 current_framework.replace(framework);
317
318 return Ok(0);
319 }
320 /// 向屏幕管理器注册UI框架
321 ///
322 /// ## 参数
323 /// - framework 框架结构体
324
scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError>325 pub fn scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> {
326 // 把ui框架加入链表
327
328 SCM_FRAMEWORK_LIST.lock().push_back(framework.clone());
329 // 调用ui框架的回调函数以安装ui框架,并将其激活
330 framework.install()?;
331
332 // 如果当前还没有框架获得了屏幕的控制权,就让其拿去
333 if CURRENT_FRAMEWORK.read().is_none() {
334 return scm_framework_enable(framework);
335 }
336 return Ok(0);
337 }
338
339 /// 屏幕管理器启用双缓冲区
340 #[allow(dead_code)]
scm_enable_double_buffer() -> Result<i32, SystemError>341 pub fn scm_enable_double_buffer() -> Result<i32, SystemError> {
342 if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) {
343 // 已经开启了双缓冲区了, 直接退出
344 return Ok(0);
345 }
346 let scm_list = SCM_FRAMEWORK_LIST.lock();
347 if scm_list.is_empty() {
348 // scm 框架链表为空
349 return Ok(0);
350 }
351 drop(scm_list);
352 SCM_DOUBLE_BUFFER_ENABLED.store(true, Ordering::SeqCst);
353 // 创建双缓冲区
354 let buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
355
356 // 设置定时刷新的对象
357 video_refresh_manager()
358 .set_refresh_target(&buf_info)
359 .expect("set refresh target failed");
360
361 // 设置当前框架的帧缓冲区
362 CURRENT_FRAMEWORK
363 .write()
364 .as_ref()
365 .unwrap()
366 .change(buf_info)?;
367 // 遍历当前所有使用帧缓冲区的框架,更新为双缓冲区
368 for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
369 if !(*framework).metadata()?.buf_info.is_double_buffer() {
370 let new_buf_info =
371 ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?;
372 (*framework).change(new_buf_info)?;
373 }
374 }
375 // 通知显示驱动,启动双缓冲
376 video_refresh_manager().video_reinitialize(true)?;
377
378 return Ok(0);
379 }
380
381 /// 允许往窗口打印信息
scm_enable_put_to_window()382 pub fn scm_enable_put_to_window() {
383 // mm之前要继续往窗口打印信息时,因为没有动态内存分配(textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
384 if CURRENT_FRAMEWORK.read().is_none() {
385 textui_enable_put_to_window();
386 } else {
387 let r = CURRENT_FRAMEWORK
388 .write()
389 .as_ref()
390 .unwrap()
391 .enable()
392 .unwrap_or_else(|e| e.to_posix_errno());
393 if r.is_negative() {
394 send_to_default_serial8250_port("scm_enable_put_to_window() failed.\n\0".as_bytes());
395 }
396 }
397 }
398 /// 禁止往窗口打印信息
scm_disable_put_to_window()399 pub fn scm_disable_put_to_window() {
400 // mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值
401 if CURRENT_FRAMEWORK.read().is_none() {
402 textui_disable_put_to_window();
403 assert!(!textui_is_enable_put_to_window());
404 } else {
405 let r = CURRENT_FRAMEWORK
406 .write()
407 .as_ref()
408 .unwrap()
409 .disable()
410 .unwrap_or_else(|e| e.to_posix_errno());
411 if r.is_negative() {
412 send_to_default_serial8250_port("scm_disable_put_to_window() failed.\n\0".as_bytes());
413 }
414 }
415 }
416 /// 当内存管理单元被初始化之后,重新处理帧缓冲区问题
417 #[inline(never)]
scm_reinit() -> Result<(), SystemError>418 pub fn scm_reinit() -> Result<(), SystemError> {
419 #[cfg(target_arch = "x86_64")]
420 {
421 let r = true_scm_reinit();
422 if r.is_err() {
423 send_to_default_serial8250_port("scm reinit failed.\n\0".as_bytes());
424 }
425 return r;
426 }
427
428 #[cfg(not(target_arch = "x86_64"))]
429 {
430 return Ok(());
431 }
432 }
433
434 #[allow(dead_code)]
true_scm_reinit() -> Result<(), SystemError>435 fn true_scm_reinit() -> Result<(), SystemError> {
436 if !has_video_refresh_manager() {
437 return Err(SystemError::ENODEV);
438 }
439 video_refresh_manager().video_reinitialize(false)?;
440
441 // 遍历当前所有使用帧缓冲区的框架,更新地址
442 let device_buffer = video_refresh_manager().device_buffer().clone();
443 for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() {
444 if framework.metadata()?.buf_info().is_device_buffer() {
445 framework.change(device_buffer.clone())?;
446 }
447 }
448
449 scm_enable_put_to_window();
450
451 return Ok(());
452 }
453