rlvgl_platform/display.rs
1//! Traits and helpers for display drivers.
2use alloc::vec;
3use alloc::vec::Vec;
4use rlvgl_core::widget::{Color, Rect};
5
6use crate::screen::Screen;
7
8/// Trait implemented by display drivers.
9pub trait DisplayDriver {
10 /// Return the screen geometry (logical size + scan rotation).
11 ///
12 /// Applications use [`Screen::logical_size`] to size widgets;
13 /// renderers and compositors consult [`Screen::rotation`] to map
14 /// logical coordinates onto the physical framebuffer.
15 fn screen(&self) -> Screen;
16
17 /// Flush a rectangular region of pixels to the display.
18 ///
19 /// `area` and `colors` are in **logical** coordinates. The driver
20 /// is responsible for rotating them into the physical framebuffer
21 /// according to its [`Screen::rotation`].
22 fn flush(&mut self, area: Rect, colors: &[Color]);
23
24 /// Optional vertical sync hook.
25 fn vsync(&mut self) {}
26}
27
28/// Dummy headless driver used for tests.
29pub struct DummyDisplay;
30
31impl DisplayDriver for DummyDisplay {
32 fn screen(&self) -> Screen {
33 Screen::landscape(0, 0)
34 }
35 fn flush(&mut self, _area: Rect, _colors: &[Color]) {}
36}
37
38/// In-memory framebuffer driver for tests and headless rendering.
39pub struct BufferDisplay {
40 /// Width of the framebuffer in pixels.
41 pub width: usize,
42 /// Height of the framebuffer in pixels.
43 pub height: usize,
44 /// Pixel buffer stored in row-major order.
45 pub buffer: Vec<Color>,
46}
47
48impl BufferDisplay {
49 /// Create a framebuffer with the specified dimensions.
50 pub fn new(width: usize, height: usize) -> Self {
51 Self {
52 width,
53 height,
54 buffer: vec![Color(0, 0, 0, 255); width * height],
55 }
56 }
57}
58
59impl DisplayDriver for BufferDisplay {
60 fn screen(&self) -> Screen {
61 Screen::landscape(self.width as u32, self.height as u32)
62 }
63 fn flush(&mut self, area: Rect, colors: &[Color]) {
64 for y in 0..area.height as usize {
65 for x in 0..area.width as usize {
66 let idx = (area.y as usize + y) * self.width + (area.x as usize + x);
67 self.buffer[idx] = colors[y * area.width as usize + x];
68 }
69 }
70 }
71}