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