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::uart::uart::{c_uart_send_str, UartPort}, 11 include::bindings::bindings::{ 12 scm_buffer_info_t, video_frame_buffer_info, video_reinitialize, video_set_refresh_target, 13 }, 14 libs::{rwlock::RwLock, spinlock::SpinLock}, 15 mm::VirtAddr, 16 syscall::SystemError, 17 }; 18 19 use lazy_static::lazy_static; 20 21 use super::textui_no_alloc::textui_init_no_alloc; 22 23 lazy_static! { 24 /// 全局的UI框架列表 25 pub static ref SCM_FRAMEWORK_LIST: SpinLock<LinkedList<Arc<dyn ScmUiFramework>>> = 26 SpinLock::new(LinkedList::new()); 27 /// 当前在使用的UI框架 28 pub static ref CURRENT_FRAMEWORK: RwLock<Option<Arc<dyn ScmUiFramework>>> = RwLock::new(None); 29 30 } 31 32 /// 是否启用双缓冲 33 pub static SCM_DOUBLE_BUFFER_ENABLED: AtomicBool = AtomicBool::new(false); 34 35 bitflags! { 36 pub struct ScmBufferFlag:u8 { 37 // 帧缓冲区标志位 38 const SCM_BF_FB = 1 << 0; // 当前buffer是设备显存中的帧缓冲区 39 const SCM_BF_DB = 1 << 1; // 当前buffer是双缓冲 40 const SCM_BF_TEXT = 1 << 2; // 使用文本模式 41 const SCM_BF_PIXEL = 1 << 3; // 使用图像模式 42 } 43 } 44 #[derive(Clone, Debug)] 45 #[allow(dead_code)] 46 pub enum ScmFramworkType { 47 Text, 48 Gui, 49 Unused, 50 } 51 #[derive(Debug)] 52 pub enum ScmBuffer { 53 DeviceBuffer(Option<VirtAddr>), 54 DoubleBuffer(Option<Box<[u32]>>), 55 } 56 #[derive(Debug)] 57 pub struct ScmBufferInfo { 58 width: u32, // 帧缓冲区宽度(pixel或columns) 59 height: u32, // 帧缓冲区高度(pixel或lines) 60 size: u32, // 帧缓冲区大小(bytes) 61 bit_depth: u32, // 像素点位深度 62 pub buf: ScmBuffer, 63 flags: ScmBufferFlag, // 帧缓冲区标志位 64 } 65 impl Clone for ScmBufferInfo { 66 fn clone(&self) -> Self { 67 match self.buf { 68 ScmBuffer::DeviceBuffer(_) => ScmBufferInfo { 69 width: self.width, 70 height: self.height, 71 size: self.size, 72 bit_depth: self.bit_depth, 73 flags: self.flags, 74 buf: ScmBuffer::DeviceBuffer(Option::None), 75 }, 76 ScmBuffer::DoubleBuffer(_) => ScmBufferInfo { 77 width: self.width, 78 height: self.height, 79 size: self.size, 80 bit_depth: self.bit_depth, 81 flags: self.flags, 82 buf: ScmBuffer::DoubleBuffer(Option::None), 83 }, 84 } 85 } 86 } 87 88 impl ScmBufferInfo { 89 /// 创建新的帧缓冲区信息 90 /// 91 /// ## 参数 92 /// 93 /// - `buf_type` 帧缓冲区类型 94 /// 95 /// ## 返回值 96 /// 97 /// - `Result<Self, SystemError>` 创建成功返回新的帧缓冲区结构体,创建失败返回错误码 98 pub fn new(buf_type: ScmBufferFlag) -> Result<Self, SystemError> { 99 if unlikely(SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) == false) { 100 let buf_info = ScmBufferInfo::from(unsafe { &video_frame_buffer_info }); 101 102 return Ok(buf_info); 103 } else { 104 // 创建双缓冲区 105 let mut frame_buffer_info: ScmBufferInfo = 106 ScmBufferInfo::from(unsafe { &video_frame_buffer_info }); 107 108 frame_buffer_info.flags = buf_type; 109 // 这里还是改成使用box来存储数组,如果直接用vec存储,在multiboot2_iter那里会报错,不知为何 110 frame_buffer_info.buf = ScmBuffer::DoubleBuffer(Some( 111 Box::new(vec![ 112 0; 113 unsafe { (video_frame_buffer_info.size / 4) as usize } 114 ]) 115 .into_boxed_slice(), 116 )); 117 118 return Ok(frame_buffer_info); 119 } 120 } 121 122 // 重构了video后可以删除 123 fn vaddr(&mut self) -> VirtAddr { 124 match &self.buf { 125 ScmBuffer::DeviceBuffer(vaddr) => { 126 if !vaddr.is_none() { 127 vaddr.unwrap() 128 } else { 129 return VirtAddr::new(0); 130 } 131 } 132 ScmBuffer::DoubleBuffer(buf) => { 133 if !buf.is_none() { 134 let address = self.buf().as_ptr(); 135 VirtAddr::new(address as usize) 136 } else { 137 return VirtAddr::new(0); 138 } 139 } 140 } 141 } 142 143 fn buf(&mut self) -> &mut [u32] { 144 let len = self.buf_size() / 4; 145 match &mut self.buf { 146 ScmBuffer::DoubleBuffer(buf) => match buf.as_mut() { 147 Some(buf) => buf, 148 None => panic!("Buffer is none"), 149 }, 150 ScmBuffer::DeviceBuffer(vaddr) => match vaddr.as_mut() { 151 Some(vaddr) => { 152 let buf: &mut [u32] = unsafe { 153 core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len as usize) 154 }; 155 return buf; 156 } 157 None => panic!("Buffer is none"), 158 }, 159 } 160 } 161 pub fn buf_size(&self) -> u32 { 162 self.size 163 } 164 pub fn buf_height(&self) -> u32 { 165 self.height 166 } 167 pub fn buf_width(&self) -> u32 { 168 self.width 169 } 170 pub fn is_double_buffer(&self) -> bool { 171 match &self.buf { 172 ScmBuffer::DoubleBuffer(_) => true, 173 _ => false, 174 } 175 } 176 pub fn is_device_buffer(&self) -> bool { 177 match &self.buf { 178 ScmBuffer::DeviceBuffer(_) => true, 179 _ => false, 180 } 181 } 182 } 183 184 // 重构了video后可以删除 185 impl From<&scm_buffer_info_t> for ScmBufferInfo { 186 fn from(value: &scm_buffer_info_t) -> Self { 187 Self { 188 width: value.width, 189 height: value.height, 190 size: value.size, 191 bit_depth: value.bit_depth, 192 buf: ScmBuffer::DeviceBuffer(Some(VirtAddr::new(value.vaddr as usize))), 193 flags: ScmBufferFlag::from_bits_truncate(value.flags as u8), 194 } 195 } 196 } 197 impl Into<scm_buffer_info_t> for ScmBufferInfo { 198 fn into(mut self) -> scm_buffer_info_t { 199 let vaddr = self.vaddr(); 200 scm_buffer_info_t { 201 width: self.width, 202 height: self.height, 203 size: self.size, 204 bit_depth: self.bit_depth, 205 vaddr: vaddr.data() as u64, 206 flags: self.flags.bits as u64, 207 } 208 } 209 } 210 #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 211 pub struct ScmUiFrameworkId(u32); 212 213 impl ScmUiFrameworkId { 214 /// 分配一个新的框架id 215 pub fn new() -> Self { 216 static MAX_ID: AtomicU32 = AtomicU32::new(0); 217 return ScmUiFrameworkId(MAX_ID.fetch_add(1, Ordering::SeqCst)); 218 } 219 } 220 #[allow(dead_code)] 221 #[derive(Debug, Clone)] 222 pub struct ScmUiFrameworkMetadata { 223 id: ScmUiFrameworkId, 224 name: String, 225 framework_type: ScmFramworkType, 226 pub buf_info: ScmBufferInfo, 227 } 228 229 impl ScmUiFrameworkMetadata { 230 pub fn new(name: String, framework_type: ScmFramworkType) -> Self { 231 match framework_type { 232 ScmFramworkType::Text => { 233 let result = ScmUiFrameworkMetadata { 234 id: ScmUiFrameworkId::new(), 235 name, 236 framework_type: ScmFramworkType::Text, 237 buf_info: ScmBufferInfo::new(ScmBufferFlag::SCM_BF_TEXT).unwrap(), 238 }; 239 240 return result; 241 } 242 ScmFramworkType::Gui => todo!(), 243 ScmFramworkType::Unused => todo!(), 244 } 245 } 246 pub fn buf_info(&self) -> ScmBufferInfo { 247 return self.buf_info.clone(); 248 } 249 pub fn set_buf_info(&mut self, buf_info: ScmBufferInfo) { 250 self.buf_info = buf_info; 251 } 252 pub fn buf_is_none(&self) -> bool { 253 match &self.buf_info.buf { 254 ScmBuffer::DeviceBuffer(vaddr) => { 255 return vaddr.is_none(); 256 } 257 ScmBuffer::DoubleBuffer(buf) => { 258 return buf.is_none(); 259 } 260 } 261 } 262 pub fn buf(&mut self) -> &mut [u32] { 263 if self.buf_is_none() { 264 panic!("buf is none"); 265 } 266 self.buf_info.buf() 267 } 268 } 269 pub trait ScmUiFramework: Sync + Send + Debug { 270 // 安装ui框架的回调函数 271 fn install(&self) -> Result<i32, SystemError> { 272 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 273 } 274 // 卸载ui框架的回调函数 275 fn uninstall(&self) -> Result<i32, SystemError> { 276 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 277 } 278 // 启用ui框架的回调函数 279 fn enable(&self) -> Result<i32, SystemError> { 280 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 281 } 282 // 禁用ui框架的回调函数 283 fn disable(&self) -> Result<i32, SystemError> { 284 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 285 } 286 // 改变ui框架的帧缓冲区的回调函数 287 fn change(&self, _buf: ScmBufferInfo) -> Result<i32, SystemError> { 288 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 289 } 290 /// @brief 获取ScmUiFramework的元数据 291 /// @return 成功:Ok(ScmUiFramework的元数据) 292 /// 失败:Err(错误码) 293 fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> { 294 // 若文件系统没有实现此方法,则返回“不支持” 295 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 296 } 297 } 298 299 /// 初始化屏幕控制模块 300 /// 301 /// ## 调用时机 302 /// 303 /// 该函数在内核启动的早期进行调用。调用时,内存管理模块尚未初始化。 304 #[no_mangle] 305 pub extern "C" fn scm_init() { 306 SCM_DOUBLE_BUFFER_ENABLED.store(false, Ordering::SeqCst); // 禁用双缓冲 307 308 textui_init_no_alloc(); 309 310 c_uart_send_str(UartPort::COM1.to_u16(), "\nfinish_scm_init\n\0".as_ptr()); 311 } 312 313 /// 启用某个ui框架,将它的帧缓冲区渲染到屏幕上 314 /// ## 参数 315 /// 316 /// - framework 要启动的ui框架 317 318 pub fn scm_framework_enable(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> { 319 // 获取信息 320 let metadata = framework.metadata()?; 321 322 // if metadata.buf_info.buf.is_null() { 323 // return Err(SystemError::EINVAL); 324 // } 325 let mut current_framework = CURRENT_FRAMEWORK.write(); 326 327 if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) == true { 328 let buf: scm_buffer_info_t = metadata.buf_info.into(); 329 let retval = unsafe { video_set_refresh_target(buf) }; 330 if retval == 0 { 331 framework.enable()?; 332 } 333 } else { 334 framework.enable()?; 335 } 336 337 current_framework.replace(framework); 338 339 return Ok(0); 340 } 341 /// 向屏幕管理器注册UI框架 342 /// 343 /// ## 参数 344 /// - framework 框架结构体 345 346 pub fn scm_register(framework: Arc<dyn ScmUiFramework>) -> Result<i32, SystemError> { 347 // 把ui框架加入链表 348 349 SCM_FRAMEWORK_LIST.lock().push_back(framework.clone()); 350 // 调用ui框架的回调函数以安装ui框架,并将其激活 351 framework.install()?; 352 353 // 如果当前还没有框架获得了屏幕的控制权,就让其拿去 354 if CURRENT_FRAMEWORK.read().is_none() { 355 return scm_framework_enable(framework); 356 } 357 return Ok(0); 358 } 359 360 /// 允许双缓冲区 361 #[no_mangle] 362 pub extern "C" fn scm_enable_double_buffer() -> i32 { 363 let r = true_scm_enable_double_buffer().unwrap_or_else(|e| e.to_posix_errno()); 364 if r.is_negative() { 365 c_uart_send_str( 366 UartPort::COM1.to_u16(), 367 "scm enable double buffer fail.\n\0".as_ptr(), 368 ); 369 } 370 371 return r; 372 } 373 fn true_scm_enable_double_buffer() -> Result<i32, SystemError> { 374 if SCM_DOUBLE_BUFFER_ENABLED.load(Ordering::SeqCst) { 375 // 已经开启了双缓冲区了, 直接退出 376 return Ok(0); 377 } 378 let scm_list = SCM_FRAMEWORK_LIST.lock(); 379 if scm_list.is_empty() { 380 // scm 框架链表为空 381 return Ok(0); 382 } 383 drop(scm_list); 384 SCM_DOUBLE_BUFFER_ENABLED.store(true, Ordering::SeqCst); 385 // 创建双缓冲区 386 let mut buf_info = ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?; 387 let mut refresh_target_buf: scm_buffer_info_t = buf_info.clone().into(); 388 // 重构video后进行修改 389 refresh_target_buf.vaddr = buf_info.vaddr().data() as u64; 390 CURRENT_FRAMEWORK 391 .write() 392 .as_ref() 393 .unwrap() 394 .change(buf_info)?; 395 // 设置定时刷新的对象 396 unsafe { video_set_refresh_target(refresh_target_buf) }; 397 // 遍历当前所有使用帧缓冲区的框架,更新为双缓冲区 398 for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() { 399 if !(*framework).metadata()?.buf_info.is_double_buffer() { 400 let new_buf_info = 401 ScmBufferInfo::new(ScmBufferFlag::SCM_BF_DB | ScmBufferFlag::SCM_BF_PIXEL)?; 402 (*framework).change(new_buf_info)?; 403 } 404 } 405 // 通知显示驱动,启动双缓冲 406 unsafe { video_reinitialize(true) }; 407 408 return Ok(0); 409 } 410 /// 允许往窗口打印信息 411 #[no_mangle] 412 pub fn scm_enable_put_to_window() { 413 // mm之前要继续往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值 414 if CURRENT_FRAMEWORK.read().is_none() { 415 super::textui::ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst); 416 } else { 417 let r = CURRENT_FRAMEWORK 418 .write() 419 .as_ref() 420 .unwrap() 421 .enable() 422 .unwrap_or_else(|e| e.to_posix_errno()); 423 if r.is_negative() { 424 c_uart_send_str( 425 UartPort::COM1.to_u16(), 426 "scm_enable_put_to_window() failed.\n\0".as_ptr(), 427 ); 428 } 429 } 430 } 431 /// 禁止往窗口打印信息 432 #[no_mangle] 433 pub fn scm_disable_put_to_window() { 434 // mm之前要停止往窗口打印信息时,因为没有动态内存分配(rwlock与otion依然能用,但是textui并没有往scm注册),且使用的是textui,要直接修改textui里面的值 435 if CURRENT_FRAMEWORK.read().is_none() { 436 super::textui::ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst); 437 assert!(super::textui::ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst) == false); 438 } else { 439 let r = CURRENT_FRAMEWORK 440 .write() 441 .as_ref() 442 .unwrap() 443 .disable() 444 .unwrap_or_else(|e| e.to_posix_errno()); 445 if r.is_negative() { 446 c_uart_send_str( 447 UartPort::COM1.to_u16(), 448 "scm_disable_put_to_window() failed.\n\0".as_ptr(), 449 ); 450 } 451 } 452 } 453 /// 当内存管理单元被初始化之后,重新处理帧缓冲区问题 454 #[no_mangle] 455 pub extern "C" fn scm_reinit() -> i32 { 456 let r = true_scm_reinit().unwrap_or_else(|e| e.to_posix_errno()); 457 if r.is_negative() { 458 c_uart_send_str(UartPort::COM1.to_u16(), "scm reinit failed.\n\0".as_ptr()); 459 } 460 return r; 461 } 462 fn true_scm_reinit() -> Result<i32, SystemError> { 463 unsafe { video_reinitialize(false) }; 464 465 // 遍历当前所有使用帧缓冲区的框架,更新地址 466 for framework in SCM_FRAMEWORK_LIST.lock().iter_mut() { 467 if framework.metadata()?.buf_info().is_device_buffer() { 468 framework.change(unsafe { ScmBufferInfo::from(&video_frame_buffer_info) })?; 469 } 470 } 471 472 scm_enable_put_to_window(); 473 474 return Ok(0); 475 } 476