feat(core/rust): introduce render_on_canvas functionality

[no changelog]
cepetr/drawlib-anim
cepetr 2 weeks ago
parent d10d4cc65d
commit 257495aff7

@ -0,0 +1,69 @@
use crate::ui::shape::DrawingCache;
use static_alloc::Bump;
/// Memory reserved for `ProgressiveRenderer`s shape storage.
/// ProgressiveRenderer is used if framebuffer is not available.
#[cfg(not(feature = "xframebuffer"))]
pub const SHAPE_MEM_SIZE: usize = 5 * 1024;
#[cfg(feature = "xframebuffer")]
pub const SHAPE_MEM_SIZE: usize = 0;
/// Maximum number of shapes on a single screen
/// (if you change it, you will probably need to change
/// the memory size above)
#[cfg(not(feature = "xframebuffer"))]
pub const SHAPE_MAX_COUNT: usize = 45;
#[cfg(feature = "xframebuffer")]
pub const SHAPE_MAX_COUNT: usize = 0;
/// Size of `bump_a` memory that might not be accessible by DMA
pub const BUMP_A_SIZE: usize = DrawingCache::get_bump_a_size() + SHAPE_MEM_SIZE;
/// Size of `bump_b` memory that must be accessible by DMA
pub const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
/// Runs a user-defined function with two bump allocators.
///
/// The function is passed two bump allocators, `bump_a` and `bump_b`, which
/// can be used to allocate memory for temporary objects.
///
/// The function calls cannot be nested. The function panics if that happens.
pub fn run_with_bumps<'a, F>(func: F)
where
F: FnOnce(&'a mut Bump<[u8; BUMP_A_SIZE]>, &'a mut Bump<[u8; BUMP_B_SIZE]>),
{
static mut LOCKED: bool = false;
// SAFETY:
// The application is single-threaded, so we can safely use a
// static variable as a lock against nested calls.
if unsafe { LOCKED } {
panic!("nested run_with_bumps!");
}
unsafe {
LOCKED = true;
};
#[cfg_attr(not(target_os = "macos"), link_section = ".no_dma_buffers")]
static mut BUMP_A: Bump<[u8; BUMP_A_SIZE]> = Bump::uninit();
#[cfg_attr(not(target_os = "macos"), link_section = ".buf")]
static mut BUMP_B: Bump<[u8; BUMP_B_SIZE]> = Bump::uninit();
// SAFETY:
// The function cannot be nested, so we can safely
// use the static bump allocators.
let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) };
let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) };
bump_a.reset();
bump_b.reset();
func(bump_a, bump_b);
unsafe {
LOCKED = false;
};
}

@ -0,0 +1,24 @@
use crate::ui::{
display::Color,
shape::{Canvas, DirectRenderer, DrawingCache},
};
use super::bumps::run_with_bumps;
/// Creates the `Renderer` object for drawing on a the specified and invokes a
/// user-defined function that takes a single argument `target`. The user's
/// function can utilize the `target` for drawing on the canvas.
///
/// `bg_color` specifies a background color with which the canvas is filled
/// before the drawing starts. If the background color is None, the background
/// is undefined, and the user has to fill it themselves.
pub fn render_on_canvas<'a, C: Canvas, F>(canvas: &mut C, bg_color: Option<Color>, func: F)
where
F: FnOnce(&mut DirectRenderer<'_, 'a, C>),
{
run_with_bumps(|bump_a, bump_b| {
let cache = DrawingCache::new(bump_a, bump_b);
let mut target = DirectRenderer::new(canvas, bg_color, &cache);
func(&mut target);
});
}

@ -1,12 +1,12 @@
use crate::ui::{
display::Color,
geometry::Offset,
shape::{BasicCanvas, DirectRenderer, DrawingCache, Rgb565Canvas, Viewport},
shape::{BasicCanvas, Canvas, DirectRenderer, DrawingCache, Rgb565Canvas, Viewport},
};
use crate::trezorhal::display;
use super::bumps;
use static_alloc::Bump;
use crate::trezorhal::display;
/// Creates the `Renderer` object for drawing on a display and invokes a
/// user-defined function that takes a single argument `target`. The user's
@ -22,24 +22,10 @@ pub fn render_on_display<'a, F>(viewport: Option<Viewport>, bg_color: Option<Col
where
F: FnOnce(&mut DirectRenderer<'_, 'a, Rgb565Canvas<'a>>),
{
const BUMP_A_SIZE: usize = DrawingCache::get_bump_a_size();
const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
#[cfg_attr(not(target_os = "macos"), link_section = ".no_dma_buffers")]
static mut BUMP_A: Bump<[u8; BUMP_A_SIZE]> = Bump::uninit();
#[cfg_attr(not(target_os = "macos"), link_section = ".buf")]
static mut BUMP_B: Bump<[u8; BUMP_B_SIZE]> = Bump::uninit();
let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) };
let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) };
{
bumps::run_with_bumps(|bump_a, bump_b| {
let width = display::DISPLAY_RESX as i16;
let height = display::DISPLAY_RESY as i16;
bump_a.reset();
bump_b.reset();
let cache = DrawingCache::new(bump_a, bump_b);
let (fb, fb_stride) = display::get_frame_buffer();
@ -58,5 +44,5 @@ where
let mut target = DirectRenderer::new(&mut canvas, bg_color, &cache);
func(&mut target);
}
});
}

@ -4,7 +4,7 @@ use crate::ui::{
shape::{BasicCanvas, DirectRenderer, DrawingCache, Rgba8888Canvas, Viewport},
};
use static_alloc::Bump;
use super::bumps;
use crate::trezorhal::display;
@ -22,24 +22,10 @@ pub fn render_on_display<'a, F>(viewport: Option<Viewport>, bg_color: Option<Col
where
F: FnOnce(&mut DirectRenderer<'_, 'a, Rgba8888Canvas<'a>>),
{
const BUMP_A_SIZE: usize = DrawingCache::get_bump_a_size();
const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
#[cfg_attr(not(target_os = "macos"), link_section = ".no_dma_buffers")]
static mut BUMP_A: Bump<[u8; BUMP_A_SIZE]> = Bump::uninit();
#[cfg_attr(not(target_os = "macos"), link_section = ".buf")]
static mut BUMP_B: Bump<[u8; BUMP_B_SIZE]> = Bump::uninit();
let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) };
let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) };
{
bumps::run_with_bumps(|bump_a, bump_b| {
let width = display::DISPLAY_RESX as i16;
let height = display::DISPLAY_RESY as i16;
bump_a.reset();
bump_b.reset();
let cache = DrawingCache::new(bump_a, bump_b);
let (fb, fb_stride) = display::get_frame_buffer();
@ -58,5 +44,5 @@ where
let mut target = DirectRenderer::new(&mut canvas, bg_color, &cache);
func(&mut target);
}
});
}

@ -1,3 +1,8 @@
mod bumps;
mod direct_canvas;
pub use direct_canvas::render_on_canvas;
#[cfg(all(feature = "xframebuffer", feature = "display_mono"))]
pub mod fb_mono8;
#[cfg(all(feature = "xframebuffer", feature = "display_mono"))]

@ -10,16 +10,9 @@ use crate::ui::{
use super::super::{BasicCanvas, BitmapView, DrawingCache, ProgressiveRenderer, Viewport};
use static_alloc::Bump;
use super::bumps;
// Maximum number of shapes on a single screen
const SHAPE_MAX_COUNT: usize = 45;
// Memory reserved for ProgressiveRenderes shape storage
const SHAPE_MEM_SIZE: usize = 5 * 1024;
// Memory not accessible by DMA
const BUMP_A_SIZE: usize = DrawingCache::get_bump_a_size() + SHAPE_MEM_SIZE;
// Memory accessible by DMA
const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
use static_alloc::Bump;
/// Creates the `Renderer` object for drawing on a display and invokes a
/// user-defined function that takes a single argument `target`. The user's
@ -33,20 +26,9 @@ const BUMP_B_SIZE: usize = DrawingCache::get_bump_b_size();
/// is undefined, and the user has to fill it themselves.
pub fn render_on_display<'a, F>(viewport: Option<Viewport>, bg_color: Option<Color>, func: F)
where
F: FnOnce(&mut ProgressiveRenderer<'_, 'a, Bump<[u8; BUMP_A_SIZE]>, DisplayCanvas>),
F: FnOnce(&mut ProgressiveRenderer<'_, 'a, Bump<[u8; bumps::BUMP_A_SIZE]>, DisplayCanvas>),
{
#[cfg_attr(not(target_os = "macos"), link_section = ".no_dma_buffers")]
static mut BUMP_A: Bump<[u8; BUMP_A_SIZE]> = Bump::uninit();
#[cfg_attr(not(target_os = "macos"), link_section = ".buf")]
static mut BUMP_B: Bump<[u8; BUMP_B_SIZE]> = Bump::uninit();
let bump_a = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_A) };
let bump_b = unsafe { &mut *core::ptr::addr_of_mut!(BUMP_B) };
{
bump_a.reset();
bump_b.reset();
bumps::run_with_bumps(|bump_a, bump_b| {
let cache = DrawingCache::new(bump_a, bump_b);
let mut canvas = DisplayCanvas::new();
@ -54,13 +36,18 @@ where
canvas.set_viewport(viewport);
}
let mut target =
ProgressiveRenderer::new(&mut canvas, bg_color, &cache, bump_a, SHAPE_MAX_COUNT);
let mut target = ProgressiveRenderer::new(
&mut canvas,
bg_color,
&cache,
bump_a,
bumps::SHAPE_MAX_COUNT,
);
func(&mut target);
target.render(16);
}
});
}
/// A simple display canvas allowing just two bitblt operations:

@ -26,7 +26,7 @@ pub use canvas::{
BasicCanvas, Canvas, CanvasBuilder, Mono8Canvas, Rgb565Canvas, Rgba8888Canvas, Viewport,
};
pub use circle::Circle;
pub use display::render_on_display;
pub use display::{render_on_canvas, render_on_display};
#[cfg(feature = "ui_jpeg_decoder")]
pub use jpeg::JpegImage;
pub use qrcode::QrImage;

Loading…
Cancel
Save