1extern crate alloc;
21
22use alloc::{
23 format,
24 string::{String, ToString},
25 sync::Arc,
26 vec::Vec,
27};
28use hashbrown::HashMap;
29use spin::{Mutex, RwLock};
30
31use crate::device::{
32 DeviceType,
33 graphics::{FramebufferConfig, GraphicsDevice},
34 manager::{DeviceManager, SharedDevice},
35};
36
37#[derive(Debug)]
39pub struct FramebufferResource {
40 pub source_device_id: usize,
42 pub logical_name: String,
44 pub config: FramebufferConfig,
46 pub physical_addr: usize,
48 pub size: usize,
54 pub created_char_device_id: RwLock<Option<usize>>,
56}
57
58impl FramebufferResource {
59 pub fn new(
61 source_device_id: usize,
62 logical_name: String,
63 config: FramebufferConfig,
64 physical_addr: usize,
65 size: usize,
66 ) -> Self {
67 Self {
68 source_device_id,
69 logical_name,
70 config,
71 physical_addr,
72 size,
73 created_char_device_id: RwLock::new(None),
74 }
75 }
76}
77
78#[derive(Debug, Clone)]
80pub struct DisplayConfiguration {
81 pub display_id: String,
83 pub framebuffer_name: String,
85 pub position: (u32, u32),
87 pub resolution: (u32, u32),
89 pub is_primary: bool,
91}
92
93#[derive(Debug, Clone)]
95pub struct MmapRegion {
96 pub virtual_addr: usize,
98 pub physical_addr: usize,
100 pub size: usize,
102 pub framebuffer_name: String,
104}
105
106pub struct GraphicsManager {
108 framebuffers: Mutex<Option<HashMap<String, Arc<FramebufferResource>>>>,
110 display_configs: Mutex<Vec<DisplayConfiguration>>,
112 active_mappings: Mutex<Vec<MmapRegion>>,
114}
115
116static MANAGER: GraphicsManager = GraphicsManager::new();
117
118impl GraphicsManager {
119 pub const fn new() -> Self {
121 Self {
122 framebuffers: Mutex::new(None),
123 display_configs: Mutex::new(Vec::new()),
124 active_mappings: Mutex::new(Vec::new()),
125 }
126 }
127
128 pub fn get_manager() -> &'static GraphicsManager {
130 &MANAGER
131 }
132
133 pub fn discover_graphics_devices(&self) {
138 let device_manager = DeviceManager::get_manager();
139 let device_count = device_manager.get_devices_count();
140
141 for device_id in 0..device_count {
142 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
143
144 let device = match device_manager.get_device(device_id) {
145 Some(device) => device,
146 None => {
147 crate::early_println!("[GraphicsManager] Device not found: {}", device_id);
148 continue;
149 }
150 };
151
152 if device.device_type() == DeviceType::Graphics {
153 if let Err(e) = self.register_framebuffer_from_device(device_id, device) {
154 crate::early_println!(
155 "[GraphicsManager] Failed to register framebuffer from device {}: {}",
156 device_id,
157 e
158 );
159 } else {
160 crate::early_println!(
161 "[GraphicsManager] Successfully registered framebuffer from device {}",
162 device_id
163 );
164 }
165 }
166 }
167 }
168
169 pub fn register_framebuffer_from_device(
180 &self,
181 device_id: usize,
182 device: SharedDevice,
183 ) -> Result<(), &'static str> {
184 let graphics_device = device
186 .as_graphics_device()
187 .ok_or("Device is not a graphics device")?;
188
189 graphics_device.init_graphics()?;
191
192 let config = graphics_device.get_framebuffer_config()?;
194
195 let physical_addr = graphics_device.get_framebuffer_address()?;
197
198 let logical_size = config.size();
201 let physical_size = (logical_size + crate::environment::PAGE_SIZE - 1)
203 & !(crate::environment::PAGE_SIZE - 1);
204
205 let mut framebuffers = self.framebuffers.lock();
207 if framebuffers.is_none() {
208 *framebuffers = Some(HashMap::new());
209 }
210 let map = framebuffers.as_ref().unwrap();
211 let logical_name = format!("fb{}", map.len());
212 drop(framebuffers);
213
214 let resource = Arc::new(FramebufferResource::new(
216 device_id,
217 logical_name.clone(),
218 config,
219 physical_addr,
220 physical_size,
221 ));
222
223 let mut framebuffers = self.framebuffers.lock();
225 if framebuffers.is_none() {
226 *framebuffers = Some(HashMap::new());
227 }
228 framebuffers
229 .as_mut()
230 .unwrap()
231 .insert(logical_name.clone(), resource);
232 drop(framebuffers);
233
234 crate::early_println!(
235 "[GraphicsManager] Registered framebuffer resource: {} -> {}",
236 device_id,
237 logical_name
238 );
239
240 if let Err(e) = self.create_framebuffer_char_device(&logical_name) {
242 crate::early_println!(
243 "[GraphicsManager] Warning: Failed to create character device for {}: {}",
244 logical_name,
245 e
246 );
247 }
248
249 Ok(())
250 }
251
252 pub fn get_framebuffer(&self, fb_name: &str) -> Option<Arc<FramebufferResource>> {
262 let framebuffers = self.framebuffers.lock();
263 framebuffers.as_ref()?.get(fb_name).cloned()
264 }
265
266 pub fn get_framebuffer_names(&self) -> Vec<String> {
272 let framebuffers = self.framebuffers.lock();
273 if let Some(map) = framebuffers.as_ref() {
274 map.keys().cloned().collect()
275 } else {
276 Vec::new()
277 }
278 }
279
280 pub fn get_framebuffer_count(&self) -> usize {
286 let framebuffers = self.framebuffers.lock();
287 if let Some(map) = framebuffers.as_ref() {
288 map.len()
289 } else {
290 0
291 }
292 }
293
294 pub fn create_framebuffer_char_device(&self, fb_name: &str) -> Result<(), &'static str> {
304 use crate::device::{
305 graphics::framebuffer_device::FramebufferCharDevice, manager::DeviceManager,
306 };
307 use alloc::sync::Arc;
308
309 let fb_resource = {
311 let framebuffers = self.framebuffers.lock();
312 framebuffers
313 .as_ref()
314 .and_then(|map| map.get(fb_name))
315 .cloned()
316 .ok_or("Framebuffer not found")?
317 };
318
319 let fb_char_device = FramebufferCharDevice::new(fb_resource);
321
322 let device_manager = DeviceManager::get_manager();
324 let device_id =
325 device_manager.register_device_with_name(fb_name.to_string(), Arc::new(fb_char_device));
326
327 self.set_char_device_id(fb_name, device_id)?;
329
330 crate::early_println!(
331 "[GraphicsManager] Created framebuffer character device: /dev/{}",
332 fb_name
333 );
334 Ok(())
335 }
336
337 pub fn set_char_device_id(
348 &self,
349 fb_name: &str,
350 char_device_id: usize,
351 ) -> Result<(), &'static str> {
352 let mut framebuffers = self.framebuffers.lock();
353 if let Some(map) = framebuffers.as_mut() {
354 if let Some(resource) = map.get_mut(fb_name) {
355 *resource.created_char_device_id.write() = Some(char_device_id);
356 Ok(())
357 } else {
358 Err("Framebuffer not found")
359 }
360 } else {
361 Err("Framebuffer not found")
362 }
363 }
364
365 pub fn read_byte_from_framebuffer(&self, fb_name: &str, position: usize) -> Option<u8> {
376 let fb_resource = self.get_framebuffer(fb_name)?;
377
378 if position >= fb_resource.size {
379 return None;
380 }
381
382 unsafe {
384 let fb_ptr = fb_resource.physical_addr as *const u8;
385 Some(*fb_ptr.add(position))
386 }
387 }
388
389 pub fn write_byte_to_framebuffer(
401 &self,
402 fb_name: &str,
403 position: usize,
404 byte: u8,
405 ) -> Result<(), &'static str> {
406 let fb_resource = self
407 .get_framebuffer(fb_name)
408 .ok_or("Framebuffer not found")?;
409
410 if position >= fb_resource.size {
411 return Err("Position beyond framebuffer size");
412 }
413
414 unsafe {
416 let fb_ptr = fb_resource.physical_addr as *mut u8;
417 *fb_ptr.add(position) = byte;
418 }
419
420 Ok(())
421 }
422
423 pub fn read_framebuffer(&self, fb_name: &str, position: usize, buffer: &mut [u8]) -> usize {
435 let fb_resource = match self.get_framebuffer(fb_name) {
436 Some(resource) => resource,
437 None => return 0,
438 };
439
440 let available_bytes = fb_resource.size.saturating_sub(position);
441 let bytes_to_read = buffer.len().min(available_bytes);
442
443 if bytes_to_read == 0 {
444 return 0;
445 }
446
447 unsafe {
452 let fb_ptr = fb_resource.physical_addr as *const u8;
453 let src = fb_ptr.add(position);
454 for i in 0..bytes_to_read {
455 buffer[i] = core::ptr::read_volatile(src.add(i));
456 }
457 }
458
459 bytes_to_read
460 }
461
462 pub fn write_framebuffer(
474 &self,
475 fb_name: &str,
476 position: usize,
477 buffer: &[u8],
478 ) -> Result<usize, &'static str> {
479 let fb_resource = self
480 .get_framebuffer(fb_name)
481 .ok_or("Framebuffer not found")?;
482
483 let available_space = fb_resource.size.saturating_sub(position);
484 let bytes_to_write = buffer.len().min(available_space);
485
486 if bytes_to_write == 0 {
487 return Err("No space available in framebuffer");
488 }
489
490 unsafe {
493 let fb_ptr = fb_resource.physical_addr as *mut u8;
494 let dst = fb_ptr.add(position);
495 for i in 0..bytes_to_write {
496 core::ptr::write_volatile(dst.add(i), buffer[i]);
497 }
498 }
499
500 Ok(bytes_to_write)
501 }
502
503 #[cfg(test)]
506 pub fn clear_for_test(&self) {
507 use crate::device::manager::DeviceManager;
508
509 let mut framebuffers = self.framebuffers.lock();
511 *framebuffers = None;
512
513 let mut display_configs = self.display_configs.lock();
514 display_configs.clear();
515
516 let mut active_mappings = self.active_mappings.lock();
517 active_mappings.clear();
518
519 DeviceManager::get_manager().clear_for_test();
521 }
522}
523
524#[cfg(test)]
525mod test_utils {
526 use super::*;
527
528 pub fn create_test_graphics_manager() -> GraphicsManager {
531 GraphicsManager::new()
532 }
533
534 pub fn setup_clean_global_graphics_manager() -> &'static GraphicsManager {
538 let manager = GraphicsManager::get_manager();
539 manager.clear_for_test();
540 manager
541 }
542}
543
544#[cfg(test)]
545mod tests {
546 use super::*;
547 use crate::device::{
548 Device,
549 graphics::{
550 FramebufferConfig, GenericGraphicsDevice, PixelFormat, manager::GraphicsManager,
551 },
552 };
553 use alloc::{string::ToString, sync::Arc};
554
555 #[test_case]
556 fn test_framebuffer_resource_creation() {
557 let config = FramebufferConfig::new(1024, 768, PixelFormat::RGBA8888);
558 let resource = FramebufferResource::new(
559 0,
560 "fb0".to_string(),
561 config.clone(),
562 0x80000000,
563 config.size(),
564 );
565
566 assert_eq!(resource.source_device_id, 0);
567 assert_eq!(resource.logical_name, "fb0");
568 assert_eq!(resource.config.width, 1024);
569 assert_eq!(resource.config.height, 768);
570 assert_eq!(resource.physical_addr, 0x80000000);
571 assert_eq!(resource.size, 1024 * 768 * 4);
572 assert_eq!(*resource.created_char_device_id.read(), None);
573 }
574
575 #[test_case]
576 fn test_graphics_manager_initialization() {
577 let manager = GraphicsManager::new();
578 assert_eq!(manager.get_framebuffer_count(), 0);
579 assert_eq!(manager.get_framebuffer_names().len(), 0);
580 }
581
582 #[test_case]
583 fn test_graphics_manager_singleton() {
584 let manager1 = GraphicsManager::get_manager();
585 let manager2 = GraphicsManager::get_manager();
586
587 assert_eq!(manager1 as *const _, manager2 as *const _);
589 }
590
591 #[test_case]
592 fn test_framebuffer_registration() {
593 let mut manager = test_utils::create_test_graphics_manager();
594
595 let mut device = GenericGraphicsDevice::new("test-gpu");
597 let config = FramebufferConfig::new(800, 600, PixelFormat::BGRA8888);
598 device.set_framebuffer_config(config.clone());
599 device.set_framebuffer_address(0x90000000);
600
601 let shared_device: SharedDevice = Arc::new(device);
602
603 let result = manager.register_framebuffer_from_device(0, shared_device);
605 assert!(result.is_ok());
606
607 assert_eq!(manager.get_framebuffer_count(), 1);
609 let names = manager.get_framebuffer_names();
610 assert_eq!(names.len(), 1);
611 assert_eq!(names[0], "fb0");
612
613 let fb = manager.get_framebuffer("fb0").unwrap();
615 assert_eq!(fb.source_device_id, 0);
616 assert_eq!(fb.logical_name, "fb0");
617 assert_eq!(fb.config.width, 800);
618 assert_eq!(fb.config.height, 600);
619 assert_eq!(fb.physical_addr, 0x90000000);
620 let page_aligned_size = (800 * 600 * 4 + crate::environment::PAGE_SIZE - 1)
621 & !(crate::environment::PAGE_SIZE - 1);
622 assert_eq!(fb.size, page_aligned_size);
623 }
624
625 #[test_case]
626 fn test_multiple_framebuffer_registration() {
627 let mut manager = test_utils::create_test_graphics_manager();
628
629 let mut device1 = GenericGraphicsDevice::new("test-gpu1");
631 let config1 = FramebufferConfig::new(1920, 1080, PixelFormat::RGBA8888);
632 device1.set_framebuffer_config(config1.clone());
633 device1.set_framebuffer_address(0x80000000);
634 let shared_device1: SharedDevice = Arc::new(device1);
635
636 let mut device2 = GenericGraphicsDevice::new("test-gpu2");
638 let config2 = FramebufferConfig::new(1024, 768, PixelFormat::BGRA8888);
639 device2.set_framebuffer_config(config2.clone());
640 device2.set_framebuffer_address(0x90000000);
641 let shared_device2: SharedDevice = Arc::new(device2);
642
643 assert!(
645 manager
646 .register_framebuffer_from_device(1, shared_device1)
647 .is_ok()
648 );
649 assert!(
650 manager
651 .register_framebuffer_from_device(2, shared_device2)
652 .is_ok()
653 );
654
655 assert_eq!(manager.get_framebuffer_count(), 2);
657 let names = manager.get_framebuffer_names();
658 assert_eq!(names.len(), 2);
659 assert!(names.contains(&"fb0".to_string()));
660 assert!(names.contains(&"fb1".to_string()));
661
662 let fb0 = manager.get_framebuffer("fb0").unwrap();
664 let fb1 = manager.get_framebuffer("fb1").unwrap();
665
666 assert_eq!(fb0.source_device_id, 1);
667 assert_eq!(fb1.source_device_id, 2);
668 assert_ne!(fb0.physical_addr, fb1.physical_addr);
669 }
670
671 #[test_case]
672 fn test_char_device_id_assignment() {
673 let mut manager = test_utils::create_test_graphics_manager();
674
675 let mut device = GenericGraphicsDevice::new("test-gpu");
677 let config = FramebufferConfig::new(640, 480, PixelFormat::RGB888);
678 device.set_framebuffer_config(config);
679 device.set_framebuffer_address(0x80000000);
680 let shared_device: SharedDevice = Arc::new(device);
681
682 manager
683 .register_framebuffer_from_device(0, shared_device)
684 .unwrap();
685
686 assert!(manager.set_char_device_id("fb0", 42).is_ok());
688
689 let fb = manager.get_framebuffer("fb0").unwrap();
691 assert_eq!(*fb.created_char_device_id.read(), Some(42));
692
693 assert!(manager.set_char_device_id("fb999", 123).is_err());
695 }
696
697 #[test_case]
698 fn test_framebuffer_not_found() {
699 let manager = GraphicsManager::new();
700
701 assert!(manager.get_framebuffer("non_existent").is_none());
703
704 assert_eq!(manager.get_framebuffer_count(), 0);
706 assert_eq!(manager.get_framebuffer_names().len(), 0);
707 }
708}