Completely unsafe example using SDL2
This commit is contained in:
parent
35dbaaf3e8
commit
df0ff1f8eb
6 changed files with 20601 additions and 8 deletions
|
@ -1,3 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["lvgl-sys", "lvgl"]
|
members = [
|
||||||
|
"lvgl-sys",
|
||||||
|
"lvgl",
|
||||||
|
"examples/demo",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
11
examples/demo/Cargo.toml
Normal file
11
examples/demo/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "demo"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Rafael Caricio <crates@caric.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
lvgl-sys = { path = "../../lvgl-sys" }
|
||||||
|
sdl2 = "0.33.0"
|
103
examples/demo/src/main.rs
Normal file
103
examples/demo/src/main.rs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::os::raw::c_void;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use sdl2::event::Event;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::pixels::{Color, PixelFormat, PixelFormatEnum};
|
||||||
|
|
||||||
|
use lvgl_sys;
|
||||||
|
use lvgl_sys::{lv_btn_create, lv_color_t, lv_disp_buf_init, lv_disp_buf_t, lv_disp_drv_init, lv_disp_drv_register, lv_disp_drv_t, lv_disp_get_hor_res, lv_disp_get_scr_act, lv_disp_get_ver_res, lv_label_create, lv_label_set_text, lv_obj_set_pos, lv_obj_set_size, lv_obj_set_x, lv_obj_set_y, lv_obj_t, lv_task_handler, lv_area_t, lv_disp_flush_ready, LV_HOR_RES_MAX, lv_style_t, lv_style_copy, lv_style_btn_rel, LV_BTN_STYLE_PR, LV_BTN_STYLE_REL, lv_slider_set_style};
|
||||||
|
|
||||||
|
fn main() -> Result<(), String> {
|
||||||
|
unsafe {
|
||||||
|
lvgl_sys::lv_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
let sdl_context = sdl2::init()?;
|
||||||
|
let video_subsystem = sdl_context.video()?;
|
||||||
|
|
||||||
|
let hr: u32 = unsafe { lv_disp_get_hor_res(std::ptr::null_mut()) as u32 };
|
||||||
|
let vr: u32 = unsafe { lv_disp_get_ver_res(std::ptr::null_mut()) as u32 };
|
||||||
|
|
||||||
|
let window = video_subsystem.window("TFT Display: Demo", hr, vr)
|
||||||
|
.position_centered()
|
||||||
|
.opengl()
|
||||||
|
.build()
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
canvas.set_draw_color(Color::RGB(255, 0, 0));
|
||||||
|
canvas.clear();
|
||||||
|
canvas.present();
|
||||||
|
let mut event_pump = sdl_context.event_pump()?;
|
||||||
|
|
||||||
|
// Create a display buffer for LittlevGL
|
||||||
|
let mut disp_buf = MaybeUninit::<lv_disp_buf_t>::uninit();
|
||||||
|
let mut buf: [MaybeUninit<lv_color_t>; LV_HOR_RES_MAX as usize * 10] = unsafe { MaybeUninit::uninit().assume_init() }; /*Declare a buffer for 10 lines*/
|
||||||
|
unsafe {
|
||||||
|
lv_disp_buf_init(disp_buf.as_mut_ptr(), buf.as_mut_ptr() as *mut c_void, std::ptr::null_mut(), (hr * 10) as u32); /*Initialize the display buffer*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement and register a function which can copy a pixel array to an area of your display:
|
||||||
|
unsafe {
|
||||||
|
unsafe extern "C" fn my_disp_flush(disp_drv: *mut lv_disp_drv_t, area: *const lv_area_t, color_p: *mut lv_color_t) {
|
||||||
|
let mut i = 1;
|
||||||
|
for y in (*area).y1..(*area).y2 {
|
||||||
|
for x in (*area).x1..(*area).x2 {
|
||||||
|
// Put a pixel to the display.
|
||||||
|
let raw_color = *color_p.add(i);
|
||||||
|
let color = Color::from((raw_color.ch.red, raw_color.ch.green, raw_color.ch.blue, raw_color.ch.alpha));
|
||||||
|
if raw_color.ch.blue != 255 {
|
||||||
|
println!("{}x{} - {:?}", x, y, color.rgb());
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_disp_flush_ready(disp_drv); /* Indicate you are ready with the flushing*/
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut disp_drv = MaybeUninit::<lv_disp_drv_t>::uninit().assume_init(); /*Descriptor of a display driver*/
|
||||||
|
lv_disp_drv_init(&mut disp_drv); /*Basic initialization*/
|
||||||
|
disp_drv.flush_cb = Some(my_disp_flush); /*Set your driver function*/
|
||||||
|
disp_drv.buffer = disp_buf.as_mut_ptr(); /*Assign the buffer to the display*/
|
||||||
|
lv_disp_drv_register(&mut disp_drv); /*Finally register the driver*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create screen and widgets
|
||||||
|
let mut screen = unsafe { lv_disp_get_scr_act(std::ptr::null_mut()) };
|
||||||
|
let mut btn = unsafe { lv_btn_create(screen, std::ptr::null_mut()) };
|
||||||
|
unsafe {
|
||||||
|
lv_obj_set_pos(btn, 10, 10);
|
||||||
|
lv_obj_set_size(btn, 200, 50)
|
||||||
|
}
|
||||||
|
let mut label = unsafe { lv_label_create(btn, std::ptr::null_mut()) };
|
||||||
|
unsafe {
|
||||||
|
lv_label_set_text(label, CString::new("Click me!").unwrap().as_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
'running: loop {
|
||||||
|
for event in event_pump.poll_iter() {
|
||||||
|
match event {
|
||||||
|
Event::Quit { .. } | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
|
||||||
|
break 'running;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.clear();
|
||||||
|
canvas.present();
|
||||||
|
::std::thread::sleep(Duration::from_millis(300));
|
||||||
|
// The rest of the game loop goes here...
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
lv_task_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let root_dir = project_dir.parent().unwrap();
|
let root_dir = project_dir.parent().unwrap();
|
||||||
let vendor = root_dir.join("vendor");
|
let vendor = root_dir.join("vendor");
|
||||||
|
let lvgl_sys_src = root_dir.join("lvgl-sys").join("src");
|
||||||
let src = vendor.join("lvgl").join("src");
|
let src = vendor.join("lvgl").join("src");
|
||||||
|
|
||||||
// TODO: Make it configurable! Needs to be linked to final proj defs, define as an env var.
|
// TODO: Make it configurable! Needs to be linked to final proj defs, define as an env var.
|
||||||
|
@ -29,14 +30,13 @@ fn main() {
|
||||||
.include(&lvgl_config_path)
|
.include(&lvgl_config_path)
|
||||||
.compile("lvgl");
|
.compile("lvgl");
|
||||||
|
|
||||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
||||||
let cc_args = ["-DLV_CONF_INCLUDE_SIMPLE=1", "-I", lvgl_config_path.to_str().unwrap()];
|
let cc_args = ["-DLV_CONF_INCLUDE_SIMPLE=1", "-I", lvgl_config_path.to_str().unwrap()];
|
||||||
bindgen::Builder::default()
|
bindgen::Builder::default()
|
||||||
.header(src.parent().unwrap().join("lvgl.h").to_str().unwrap())
|
.header(src.parent().unwrap().join("lvgl.h").to_str().unwrap())
|
||||||
.clang_args(&cc_args)
|
.clang_args(&cc_args)
|
||||||
.generate()
|
.generate()
|
||||||
.expect("Unable to generate bindings")
|
.expect("Unable to generate bindings")
|
||||||
.write_to_file(out_path.join("bindings.rs"))
|
.write_to_file(lvgl_sys_src.join("bindings.rs"))
|
||||||
.expect("Can't write bindings!");
|
.expect("Can't write bindings!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20474
lvgl-sys/src/bindings.rs
Normal file
20474
lvgl-sys/src/bindings.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,8 @@
|
||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
#![allow(non_upper_case_globals)]
|
#![allow(non_upper_case_globals)]
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
pub mod bindings;
|
||||||
|
pub use bindings::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -13,11 +14,11 @@ mod tests {
|
||||||
unsafe {
|
unsafe {
|
||||||
lv_init();
|
lv_init();
|
||||||
|
|
||||||
let hres = lv_disp_get_hor_res(std::ptr::null_mut());
|
let horizontal_resolution = lv_disp_get_hor_res(std::ptr::null_mut());
|
||||||
assert_eq!(hres, 480);
|
assert_eq!(horizontal_resolution, 480);
|
||||||
|
|
||||||
let vres = lv_disp_get_ver_res(std::ptr::null_mut());
|
let vertical_resolution = lv_disp_get_ver_res(std::ptr::null_mut());
|
||||||
assert_eq!(vres, 320);
|
assert_eq!(vertical_resolution, 320);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue