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