1use alloc::boxed::Box;
2
3use core::{ffi::c_void, ptr::null_mut, slice};
4
5use file_system::Device;
6
7use crate::{Area, Point, RenderingColor, Result, ScreenWriteData, draw_buffer::Buffer};
8
9use super::lvgl;
10
11struct UserData {
12 device: Device,
13}
14
15pub struct Display {
16 display: *mut lvgl::lv_display_t,
17 _buffer_1: Buffer,
18 _buffer_2: Option<Buffer>,
19}
20
21unsafe impl Send for Display {}
22
23unsafe impl Sync for Display {}
24
25unsafe extern "C" fn binding_callback_function(
26 display: *mut lvgl::lv_disp_t,
27 area: *const lvgl::lv_area_t,
28 data: *mut u8,
29) {
30 let area: Area = unsafe { *area }.into();
31
32 let buffer_size: usize = (area.get_width()) as usize * (area.get_height()) as usize;
33
34 let buffer = unsafe { slice::from_raw_parts_mut(data as *mut RenderingColor, buffer_size) };
35
36 let screen_write_data = ScreenWriteData::new(area, buffer);
37
38 let user_data = unsafe { &*(lvgl::lv_display_get_user_data(display) as *mut UserData) };
39
40 let device = &user_data.device;
41
42 device
43 .write(screen_write_data.as_ref())
44 .expect("Error writing to display");
45
46 unsafe { lvgl::lv_display_flush_ready(display) };
47}
48
49impl Drop for Display {
50 fn drop(&mut self) {
51 unsafe {
52 lvgl::lv_display_delete(self.display);
53 }
54 }
55}
56
57impl Display {
58 pub fn new(
59 file: Device,
60 resolution: Point,
61 buffer_size: usize,
62 double_buffered: bool,
63 ) -> Result<Self> {
64 let lvgl_display: *mut lvgl_rust_sys::_lv_display_t = unsafe {
66 lvgl::lv_display_create(resolution.get_x() as i32, resolution.get_y() as i32)
67 };
68
69 let buffer_1 = Buffer::new(buffer_size);
71
72 let buffer_2 = if double_buffered {
73 Some(Buffer::new(buffer_size))
74 } else {
75 None
76 };
77
78 unsafe {
79 lvgl::lv_display_set_buffers(
80 lvgl_display,
81 buffer_1.as_ref().as_ptr() as *mut c_void,
82 buffer_2
83 .as_ref()
84 .map_or(null_mut(), |buffer| buffer.as_ref().as_ptr() as *mut c_void),
85 buffer_size as u32,
86 lvgl::lv_display_render_mode_t_LV_DISPLAY_RENDER_MODE_PARTIAL,
87 )
88 }
89
90 let user_data = Box::new(UserData { device: file });
92
93 unsafe {
94 lvgl::lv_display_set_user_data(lvgl_display, Box::into_raw(user_data) as *mut c_void)
95 };
96
97 unsafe { lvgl::lv_display_set_flush_cb(lvgl_display, Some(binding_callback_function)) }
99
100 Ok(Self {
101 display: lvgl_display,
102 _buffer_1: buffer_1,
103 _buffer_2: buffer_2,
104 })
105 }
106
107 pub fn get_object(&self) -> *mut lvgl::lv_obj_t {
108 unsafe { lvgl::lv_display_get_screen_active(self.display) }
109 }
110}