1use 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
22pub 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum PixelFormat {
37 RGBA8888,
39 BGRA8888,
41 RGB888,
43 RGB565,
45}
46
47impl PixelFormat {
48 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#[derive(Debug, Clone)]
60pub struct FramebufferConfig {
61 pub width: u32,
63 pub height: u32,
65 pub format: PixelFormat,
67 pub stride: u32,
69}
70
71impl FramebufferConfig {
72 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 pub fn size(&self) -> usize {
85 (self.stride * self.height) as usize
86 }
87}
88
89#[derive(Debug)]
91pub enum GraphicsRequest {
92 GetFramebufferConfig,
94 MapFramebuffer,
96 FlushFramebuffer {
98 x: u32,
99 y: u32,
100 width: u32,
101 height: u32,
102 },
103}
104
105#[derive(Debug)]
107pub struct GraphicsResult {
108 pub request: Box<GraphicsRequest>,
109 pub result: Result<GraphicsResponse, &'static str>,
110}
111
112#[derive(Debug)]
114pub enum GraphicsResponse {
115 FramebufferConfig(FramebufferConfig),
117 FramebufferAddress(usize),
119 Success,
121}
122
123pub trait GraphicsDevice: Device {
128 fn get_display_name(&self) -> &'static str;
130
131 fn get_framebuffer_config(&self) -> Result<FramebufferConfig, &'static str>;
133
134 fn get_framebuffer_address(&self) -> Result<usize, &'static str>;
136
137 fn flush_framebuffer(
139 &self,
140 x: u32,
141 y: u32,
142 width: u32,
143 height: u32,
144 ) -> Result<(), &'static str>;
145
146 fn init_graphics(&self) -> Result<(), &'static str>;
148}
149
150pub 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 pub fn set_framebuffer_config(&mut self, config: FramebufferConfig) {
170 self.config = Some(config);
171 }
172
173 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 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 }
220
221 fn on_unmapped(&self, _vaddr: usize, _length: usize) {
222 }
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 Ok(())
263 }
264
265 fn init_graphics(&self) -> Result<(), &'static str> {
266 Ok(())
268 }
269}