use core::{cell::RefCell, time::Duration}; use alloc::rc::Rc; use esp_hal::{time::Instant}; use log::info; use slint::{PhysicalSize, WindowSize, platform::{Key, software_renderer::{RenderingRotation, RepaintBufferType, Rgb565Pixel, SoftwareRenderer}}}; use super::window_adapter::SoftwareWindowAdapter; pub struct FramebufferPtr(pub *mut [Rgb565Pixel]); unsafe impl Send for FramebufferPtr {} pub struct SlintBackend { pub window_size: [u32; 2], pub window: RefCell>>, pub framebuffer: FramebufferPtr, // pub peripherals: RefCell>, } impl slint::platform::Platform for SlintBackend { fn create_window_adapter(&self) -> Result, slint::PlatformError> { // TODO: Custom window adapter impl needs to be implemented, so we can change `rotation` on // `SoftwareRenderer`. let renderer = SoftwareRenderer::new_with_repaint_buffer_type(RepaintBufferType::ReusedBuffer /* TODO: Implement a swapchain */); renderer.set_rendering_rotation(RenderingRotation::Rotate270); let window = SoftwareWindowAdapter::new(renderer); // window.set_scale_factor(4.0); window.set_size(WindowSize::Physical(PhysicalSize::new(self.window_size[0], self.window_size[1]))); self.window.replace(Some(window.clone())); Ok(window) } fn duration_since_start(&self) -> Duration { Duration::from_millis(Instant::now().duration_since_epoch().as_millis()) } fn run_event_loop(&self) -> Result<(), slint::PlatformError> { // Instead of `loop`ing here, we execute a single iteration and handle `loop`ing // in `crate::run_renderer_task`, where we can make use of `await`. /* loop */ { if let Some(window) = self.window.borrow().clone() { // TODO: Event dispatch. Here or in `run_renderer_task`? // window.try_dispatch_event(todo!())?; window.draw_if_needed(|renderer| { // TODO: Proper synchronization. let framebuffer = unsafe { &mut *self.framebuffer.0 }; renderer.render(framebuffer, self.window_size[1] as usize); info!("UI rendered."); }); } } Ok(()) } }