Improve refresh performance

This commit is contained in:
Rafael Caricio 2020-05-31 00:06:28 +02:00
parent 9f1be5b1f4
commit e6140c55c8
2 changed files with 35 additions and 29 deletions

View file

@ -34,6 +34,7 @@ fn main() -> Result<(), String> {
let mut screen_style = lvgl::Style::new(); let mut screen_style = lvgl::Style::new();
screen_style.set_body_main_color(lvgl::Color::from_rgb((0, 0, 0))); screen_style.set_body_main_color(lvgl::Color::from_rgb((0, 0, 0)));
screen_style.set_body_grad_color(lvgl::Color::from_rgb((0, 0, 0))); screen_style.set_body_grad_color(lvgl::Color::from_rgb((0, 0, 0)));
screen_style.set_body_radius(0);
screen.set_style(screen_style); screen.set_style(screen_style);
let mut time = lvgl::Label::new(&mut screen); let mut time = lvgl::Label::new(&mut screen);
@ -72,7 +73,7 @@ fn main() -> Result<(), String> {
let (stop_ch, read_ch) = mpsc::channel(); let (stop_ch, read_ch) = mpsc::channel();
let closure_ui = threaded_ui.clone(); let closure_ui = threaded_ui.clone();
let tick_thr = std::thread::spawn(move || loop { let tick_thr = std::thread::spawn(move || loop {
let period = Duration::from_millis(5); let period = Duration::from_millis(250);
closure_ui.lock().unwrap().tick_inc(period); closure_ui.lock().unwrap().tick_inc(period);
sleep(period); sleep(period);

View file

@ -1,6 +1,5 @@
use crate::Color; use crate::Color;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::vec::Vec;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use embedded_graphics; use embedded_graphics;
use embedded_graphics::prelude::*; use embedded_graphics::prelude::*;
@ -23,22 +22,28 @@ impl DisplayDriver {
Box::new(MaybeUninit::<lvgl_sys::lv_disp_buf_t>::uninit().assume_init()); Box::new(MaybeUninit::<lvgl_sys::lv_disp_buf_t>::uninit().assume_init());
// Declare a buffer for the refresh rate // Declare a buffer for the refresh rate
let refresh_buffer = const REFRESH_BUFFER_LEN: usize = 2;
Box::new( let refresh_buffer1 = Box::new(
MaybeUninit::< MaybeUninit::<
[MaybeUninit<lvgl_sys::lv_color_t>; lvgl_sys::LV_HOR_RES_MAX as usize], [MaybeUninit<lvgl_sys::lv_color_t>;
lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN],
>::uninit()
.assume_init(),
);
let refresh_buffer2 = Box::new(
MaybeUninit::<
[MaybeUninit<lvgl_sys::lv_color_t>;
lvgl_sys::LV_HOR_RES_MAX as usize * REFRESH_BUFFER_LEN],
>::uninit() >::uninit()
.assume_init(), .assume_init(),
); );
let refresh_buffer_len = refresh_buffer.len();
// Initialize the display buffer // Initialize the display buffer
lvgl_sys::lv_disp_buf_init( lvgl_sys::lv_disp_buf_init(
display_buffer.as_mut(), display_buffer.as_mut(),
Box::into_raw(refresh_buffer) as *mut cty::c_void, Box::into_raw(refresh_buffer1) as *mut cty::c_void,
core::ptr::null_mut(), Box::into_raw(refresh_buffer2) as *mut cty::c_void,
refresh_buffer_len as u32, lvgl_sys::LV_HOR_RES_MAX * REFRESH_BUFFER_LEN as u32,
); );
// Descriptor of a display driver // Descriptor of a display driver
@ -92,26 +97,26 @@ unsafe extern "C" fn display_callback_wrapper<T, C>(
{ {
// We need to make sure panics can't escape across the FFI boundary. // We need to make sure panics can't escape across the FFI boundary.
//let _ = std::panic::catch_unwind(|| { //let _ = std::panic::catch_unwind(|| {
let mut i = 0;
let display_driver = *disp_drv; let display_driver = *disp_drv;
// Rust code closure reference // Rust code closure reference
let device = &mut *(display_driver.user_data as *mut T); let device = &mut *(display_driver.user_data as *mut T);
// TODO: create a fixed image buffer iterator somehow, maybe a fixed size array let ys = (*area).y1..=(*area).y2;
let mut image_buffer = Vec::new(); let xs = ((*area).x1..=(*area).x2).enumerate();
for y in (*area).y1..=(*area).y2 { let x_len = ((*area).x2 - (*area).x1 + 1) as usize;
for x in (*area).x1..=(*area).x2 { let pixels = ys
let raw_color = Color::from_raw(*color_p.add(i)); .enumerate()
i = i + 1; .map(|(iy, y)| {
image_buffer.push(drawable::Pixel( xs.clone().map(move |(ix, x)| {
Point::new(x as i32, y as i32), let color_len = x_len * iy + ix;
raw_color.into(), let raw_color = Color::from_raw(*color_p.add(color_len));
)); drawable::Pixel(Point::new(x as i32, y as i32), raw_color.into())
} })
} })
.flatten();
let _ = device.draw_iter(image_buffer.into_iter()); // TODO: Maybe find a way to use `draw_image` method on the device instance.
let _ = device.draw_iter(pixels.into_iter());
// Indicate to LittlevGL that you are ready with the flushing // Indicate to LittlevGL that you are ready with the flushing
lvgl_sys::lv_disp_flush_ready(disp_drv); lvgl_sys::lv_disp_flush_ready(disp_drv);