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