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>` 创建成功返回新的帧缓冲区结构体,创建失败返回错误码 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 112 pub unsafe fn set_device_buffer_mmio_guard(&mut self, guard: Arc<MMIOSpaceGuard>) { 113 self.device_buffer_mmio_guard = Some(guard); 114 } 115 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 138 pub fn buf_size(&self) -> usize { 139 self.size as usize 140 } 141 142 pub fn bit_depth(&self) -> u32 { 143 self.bit_depth 144 } 145 146 pub fn height(&self) -> u32 { 147 self.height 148 } 149 150 pub fn width(&self) -> u32 { 151 self.width 152 } 153 154 pub fn is_double_buffer(&self) -> bool { 155 matches!(&self.buf, ScmBuffer::DoubleBuffer(_)) 156 } 157 pub fn is_device_buffer(&self) -> bool { 158 matches!(&self.buf, ScmBuffer::DeviceBuffer(_)) 159 } 160 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 205 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 { 220 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 } 239 pub fn buf_info(&self) -> ScmBufferInfo { 240 return self.buf_info.clone(); 241 } 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框架的回调函数 248 fn install(&self) -> Result<i32, SystemError> { 249 return Err(SystemError::ENOSYS); 250 } 251 // 卸载ui框架的回调函数 252 #[allow(dead_code)] 253 fn uninstall(&self) -> Result<i32, SystemError> { 254 return Err(SystemError::ENOSYS); 255 } 256 // 启用ui框架的回调函数 257 fn enable(&self) -> Result<i32, SystemError> { 258 return Err(SystemError::ENOSYS); 259 } 260 // 禁用ui框架的回调函数 261 fn disable(&self) -> Result<i32, SystemError> { 262 return Err(SystemError::ENOSYS); 263 } 264 // 改变ui框架的帧缓冲区的回调函数 265 fn change(&self, _buf: ScmBufferInfo) -> Result<i32, SystemError> { 266 return Err(SystemError::ENOSYS); 267 } 268 /// @brief 获取ScmUiFramework的元数据 269 /// @return 成功:Ok(ScmUiFramework的元数据) 270 /// 失败:Err(错误码) 271 fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> { 272 // 若文件系统没有实现此方法,则返回“不支持” 273 return Err(SystemError::ENOSYS); 274 } 275 } 276 277 /// 初始化屏幕控制模块 278 /// 279 /// ## 调用时机 280 /// 281 /// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。 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 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 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)] 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 /// 允许往窗口打印信息 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 /// 禁止往窗口打印信息 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)] 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)] 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