kernel/device/graphics/
mod.rs

1//! Graphics device interface
2//!
3//! This module defines the interface for graphics devices in the kernel.
4//! It provides abstractions for framebuffer operations and graphics device management.
5
6use alloc::{boxed::Box, vec::Vec};
7use core::any::Any;
8use spin::Mutex;
9
10use alloc::sync::Arc;
11
12use super::{Device, DeviceType, manager::DeviceManager};
13use crate::object::capability::selectable::Selectable;
14use crate::object::capability::{ControlOps, MemoryMappingOps};
15
16pub mod framebuffer_device;
17pub mod manager;
18
19#[cfg(test)]
20mod tests;
21
22/// Get the first available graphics device
23///
24/// This is a convenience function to get the first graphics device registered in the system.
25/// Returns None if no graphics devices are available.
26pub fn get_graphics_device() -> Option<Arc<dyn Device>> {
27    let manager = DeviceManager::get_manager();
28    if let Some(device_id) = manager.get_first_device_by_type(DeviceType::Graphics) {
29        return manager.get_device(device_id);
30    }
31    None
32}
33
34/// Pixel format for framebuffer
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum PixelFormat {
37    /// 32-bit RGBA (8 bits per channel)
38    RGBA8888,
39    /// 32-bit BGRA (8 bits per channel)  
40    BGRA8888,
41    /// 24-bit RGB (8 bits per channel)
42    RGB888,
43    /// 16-bit RGB (5-6-5 bits)
44    RGB565,
45}
46
47impl PixelFormat {
48    /// Get bytes per pixel for this format
49    pub fn bytes_per_pixel(&self) -> usize {
50        match self {
51            PixelFormat::RGBA8888 | PixelFormat::BGRA8888 => 4,
52            PixelFormat::RGB888 => 3,
53            PixelFormat::RGB565 => 2,
54        }
55    }
56}
57
58/// Framebuffer configuration
59#[derive(Debug, Clone)]
60pub struct FramebufferConfig {
61    /// Width in pixels
62    pub width: u32,
63    /// Height in pixels
64    pub height: u32,
65    /// Pixel format
66    pub format: PixelFormat,
67    /// Stride (bytes per row)
68    pub stride: u32,
69}
70
71impl FramebufferConfig {
72    /// Create a new framebuffer configuration
73    pub fn new(width: u32, height: u32, format: PixelFormat) -> Self {
74        let stride = width * format.bytes_per_pixel() as u32;
75        Self {
76            width,
77            height,
78            format,
79            stride,
80        }
81    }
82
83    /// Get the total size of the framebuffer in bytes
84    pub fn size(&self) -> usize {
85        (self.stride * self.height) as usize
86    }
87}
88
89/// Graphics operation requests
90#[derive(Debug)]
91pub enum GraphicsRequest {
92    /// Get framebuffer configuration
93    GetFramebufferConfig,
94    /// Map framebuffer memory
95    MapFramebuffer,
96    /// Flush framebuffer changes to display
97    FlushFramebuffer {
98        x: u32,
99        y: u32,
100        width: u32,
101        height: u32,
102    },
103}
104
105/// Result of graphics operations
106#[derive(Debug)]
107pub struct GraphicsResult {
108    pub request: Box<GraphicsRequest>,
109    pub result: Result<GraphicsResponse, &'static str>,
110}
111
112/// Response from graphics operations
113#[derive(Debug)]
114pub enum GraphicsResponse {
115    /// Framebuffer configuration
116    FramebufferConfig(FramebufferConfig),
117    /// Framebuffer memory address
118    FramebufferAddress(usize),
119    /// Operation completed successfully
120    Success,
121}
122
123/// Graphics device interface
124///
125/// This trait defines the interface for graphics devices.
126/// It provides methods for framebuffer management and display operations.
127pub trait GraphicsDevice: Device {
128    /// Get the device display name
129    fn get_display_name(&self) -> &'static str;
130
131    /// Get framebuffer configuration
132    fn get_framebuffer_config(&self) -> Result<FramebufferConfig, &'static str>;
133
134    /// Get framebuffer memory address
135    fn get_framebuffer_address(&self) -> Result<usize, &'static str>;
136
137    /// Flush framebuffer region to display
138    fn flush_framebuffer(
139        &self,
140        x: u32,
141        y: u32,
142        width: u32,
143        height: u32,
144    ) -> Result<(), &'static str>;
145
146    /// Initialize the graphics device (idempotent)
147    fn init_graphics(&self) -> Result<(), &'static str>;
148}
149
150/// A generic implementation of a graphics device
151pub struct GenericGraphicsDevice {
152    display_name: &'static str,
153    config: Option<FramebufferConfig>,
154    framebuffer_addr: Option<usize>,
155    request_queue: Mutex<Vec<Box<GraphicsRequest>>>,
156}
157
158impl GenericGraphicsDevice {
159    pub fn new(display_name: &'static str) -> Self {
160        Self {
161            display_name,
162            config: None,
163            framebuffer_addr: None,
164            request_queue: Mutex::new(Vec::new()),
165        }
166    }
167
168    /// Set framebuffer configuration
169    pub fn set_framebuffer_config(&mut self, config: FramebufferConfig) {
170        self.config = Some(config);
171    }
172
173    /// Set framebuffer address
174    pub fn set_framebuffer_address(&mut self, addr: usize) {
175        self.framebuffer_addr = Some(addr);
176    }
177}
178
179impl Device for GenericGraphicsDevice {
180    fn device_type(&self) -> super::DeviceType {
181        super::DeviceType::Graphics
182    }
183
184    fn name(&self) -> &'static str {
185        self.display_name
186    }
187
188    fn as_any(&self) -> &dyn Any {
189        self
190    }
191
192    fn as_any_mut(&mut self) -> &mut dyn Any {
193        self
194    }
195
196    fn as_graphics_device(&self) -> Option<&dyn GraphicsDevice> {
197        Some(self)
198    }
199}
200
201impl ControlOps for GenericGraphicsDevice {
202    // Generic graphics devices don't support control operations by default
203    fn control(&self, _command: u32, _arg: usize) -> Result<i32, &'static str> {
204        Err("Control operations not supported")
205    }
206}
207
208impl MemoryMappingOps for GenericGraphicsDevice {
209    fn get_mapping_info(
210        &self,
211        _offset: usize,
212        _length: usize,
213    ) -> Result<(usize, usize, bool), &'static str> {
214        Err("Memory mapping not supported by this graphics device")
215    }
216
217    fn on_mapped(&self, _vaddr: usize, _paddr: usize, _length: usize, _offset: usize) {
218        // Generic graphics devices don't support memory mapping
219    }
220
221    fn on_unmapped(&self, _vaddr: usize, _length: usize) {
222        // Generic graphics devices don't support memory mapping
223    }
224
225    fn supports_mmap(&self) -> bool {
226        false
227    }
228}
229
230impl Selectable for GenericGraphicsDevice {
231    fn wait_until_ready(
232        &self,
233        _interest: crate::object::capability::selectable::ReadyInterest,
234        _trapframe: &mut crate::arch::Trapframe,
235        _timeout_ticks: Option<u64>,
236    ) -> crate::object::capability::selectable::SelectWaitOutcome {
237        crate::object::capability::selectable::SelectWaitOutcome::Ready
238    }
239}
240
241impl GraphicsDevice for GenericGraphicsDevice {
242    fn get_display_name(&self) -> &'static str {
243        self.display_name
244    }
245
246    fn get_framebuffer_config(&self) -> Result<FramebufferConfig, &'static str> {
247        self.config.clone().ok_or("Framebuffer not configured")
248    }
249
250    fn get_framebuffer_address(&self) -> Result<usize, &'static str> {
251        self.framebuffer_addr.ok_or("Framebuffer address not set")
252    }
253
254    fn flush_framebuffer(
255        &self,
256        _x: u32,
257        _y: u32,
258        _width: u32,
259        _height: u32,
260    ) -> Result<(), &'static str> {
261        // Generic implementation - no-op
262        Ok(())
263    }
264
265    fn init_graphics(&self) -> Result<(), &'static str> {
266        // Generic implementation - no-op
267        Ok(())
268    }
269}