1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-19 05:58:09 +00:00

perf(core/rust): parse Toif metadata on demand

[no changelog]
This commit is contained in:
Martin Milata 2023-02-03 16:58:48 +01:00
parent 194868438a
commit 0df81b18e3
7 changed files with 67 additions and 93 deletions

View File

@ -289,7 +289,6 @@ fn generate_trezorhal_bindings() {
.allowlist_function("display_bar_radius") .allowlist_function("display_bar_radius")
.allowlist_function("display_bar_radius_buffer") .allowlist_function("display_bar_radius_buffer")
.allowlist_function("display_image") .allowlist_function("display_image")
.allowlist_function("display_toif_info")
.allowlist_function("display_loader") .allowlist_function("display_loader")
.allowlist_function("display_pixeldata") .allowlist_function("display_pixeldata")
.allowlist_function("display_pixeldata_dirty") .allowlist_function("display_pixeldata_dirty")

View File

@ -1,7 +1,6 @@
use super::ffi; use super::ffi;
use core::ptr; use core::ptr;
use cty::c_int; use cty::c_int;
use num_traits::FromPrimitive;
use crate::trezorhal::buffers::BufferText; use crate::trezorhal::buffers::BufferText;
@ -13,12 +12,6 @@ pub enum ToifFormat {
GrayScaleEH = ffi::toif_format_t_TOIF_GRAYSCALE_EH as _, GrayScaleEH = ffi::toif_format_t_TOIF_GRAYSCALE_EH as _,
} }
pub struct ToifInfo {
pub width: u16,
pub height: u16,
pub format: ToifFormat,
}
pub fn backlight(val: i32) -> i32 { pub fn backlight(val: i32) -> i32 {
unsafe { ffi::display_backlight(val) } unsafe { ffi::display_backlight(val) }
} }
@ -116,31 +109,6 @@ pub fn image(x: i16, y: i16, w: i16, h: i16, data: &[u8]) {
} }
} }
pub fn toif_info(data: &[u8]) -> Result<ToifInfo, ()> {
let mut width: cty::uint16_t = 0;
let mut height: cty::uint16_t = 0;
let mut format: ffi::toif_format_t = ffi::toif_format_t_TOIF_FULL_COLOR_BE;
if unsafe {
ffi::display_toif_info(
data.as_ptr() as _,
data.len() as _,
&mut width,
&mut height,
&mut format,
)
} {
let format = ToifFormat::from_usize(format as usize).unwrap_or(ToifFormat::FullColorBE);
Ok(ToifInfo {
width,
height,
format,
})
} else {
Err(())
}
}
pub fn loader( pub fn loader(
progress: u16, progress: u16,
indeterminate: bool, indeterminate: bool,

View File

@ -16,8 +16,8 @@ pub struct Image {
impl Image { impl Image {
pub fn new(data: &'static [u8]) -> Self { pub fn new(data: &'static [u8]) -> Self {
let toif = Toif::new(data); let toif = unwrap!(Toif::new(data));
assert!(toif.format == ToifFormat::FullColorLE); assert!(toif.format() == ToifFormat::FullColorLE);
Self { Self {
toif, toif,
area: Rect::zero(), area: Rect::zero(),
@ -27,8 +27,8 @@ impl Image {
/// Display the icon with baseline Point, aligned according to the /// Display the icon with baseline Point, aligned according to the
/// `alignment` argument. /// `alignment` argument.
pub fn draw(&self, baseline: Point, alignment: Alignment2D) { pub fn draw(&self, baseline: Point, alignment: Alignment2D) {
let r = Rect::snap(baseline, self.toif.size, alignment); let r = Rect::snap(baseline, self.toif.size(), alignment);
image(r.x0, r.y0, r.width(), r.height(), self.toif.data); image(r.x0, r.y0, r.width(), r.height(), self.toif.zdata());
} }
} }
@ -51,7 +51,7 @@ impl Component for Image {
fn bounds(&self, sink: &mut dyn FnMut(Rect)) { fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(Rect::from_center_and_size( sink(Rect::from_center_and_size(
self.area.center(), self.area.center(),
self.toif.size, self.toif.size(),
)); ));
} }
} }
@ -101,12 +101,12 @@ impl Component for BlendedImage {
type Msg = Never; type Msg = Never;
fn place(&mut self, bounds: Rect) -> Rect { fn place(&mut self, bounds: Rect) -> Rect {
self.bg_top_left = self.bg.toif.size.snap(bounds.center(), CENTER); self.bg_top_left = self.bg.toif.size().snap(bounds.center(), CENTER);
let ft_top_left = self.fg.toif.size.snap(bounds.center(), CENTER); let ft_top_left = self.fg.toif.size().snap(bounds.center(), CENTER);
self.fg_offset = ft_top_left - self.bg_top_left; self.fg_offset = ft_top_left - self.bg_top_left;
Rect::from_top_left_and_size(self.bg_top_left, self.bg.toif.size) Rect::from_top_left_and_size(self.bg_top_left, self.bg.toif.size())
} }
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> { fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
@ -120,7 +120,7 @@ impl Component for BlendedImage {
fn bounds(&self, sink: &mut dyn FnMut(Rect)) { fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
sink(Rect::from_top_left_and_size( sink(Rect::from_top_left_and_size(
self.bg_top_left, self.bg_top_left,
self.bg.toif.size, self.bg.toif.size(),
)); ));
} }
} }

View File

@ -43,10 +43,11 @@ pub fn loader_uncompress(
const ICON_MAX_SIZE: i16 = constant::LOADER_ICON_MAX_SIZE; const ICON_MAX_SIZE: i16 = constant::LOADER_ICON_MAX_SIZE;
if let Some((icon, color)) = icon { if let Some((icon, color)) = icon {
if icon.toif.width() <= ICON_MAX_SIZE && icon.toif.height() <= ICON_MAX_SIZE { let toif_size = icon.toif.size();
if toif_size.x <= ICON_MAX_SIZE && toif_size.y <= ICON_MAX_SIZE {
let mut icon_data = [0_u8; ((ICON_MAX_SIZE * ICON_MAX_SIZE) / 2) as usize]; let mut icon_data = [0_u8; ((ICON_MAX_SIZE * ICON_MAX_SIZE) / 2) as usize];
icon.toif.uncompress(&mut icon_data); icon.toif.uncompress(&mut icon_data);
let i = Some((icon, color, icon.toif.size)); let i = Some((icon, color, toif_size));
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, i); loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, i);
} else { } else {
loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, None); loader_rust(y_offset, fg_color, bg_color, progress, indeterminate, None);
@ -237,7 +238,7 @@ pub fn loader_rust(
let x_i = x_c - icon_area.x0; let x_i = x_c - icon_area.x0;
let y_i = y_c - icon_area.y0; let y_i = y_c - icon_area.y0;
let data = unwrap!(icon_data).data() let data = unwrap!(icon_data).zdata()
[(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize]; [(((x_i & 0xFE) + (y_i * icon_width)) / 2) as usize];
if (x_i & 0x01) == 0 { if (x_i & 0x01) == 0 {
underlying_color = icon_colortable[(data & 0xF) as usize]; underlying_color = icon_colortable[(data & 0xF) as usize];
@ -337,7 +338,7 @@ pub fn loader_rust(
icon_buffer_used.buffer[icon_offset as usize..(icon_offset + icon_width / 2) as usize] icon_buffer_used.buffer[icon_offset as usize..(icon_offset + icon_width / 2) as usize]
.copy_from_slice( .copy_from_slice(
&unwrap!(icon_data).toif.data[(y_i * (icon_width / 2)) as usize &unwrap!(icon_data).toif.zdata()[(y_i * (icon_width / 2)) as usize
..((y_i + 1) * (icon_width / 2)) as usize], ..((y_i + 1) * (icon_width / 2)) as usize],
); );
icon_buffer = icon_buffer_used; icon_buffer = icon_buffer_used;

View File

@ -24,11 +24,10 @@ use crate::{
error::Error, error::Error,
time::Duration, time::Duration,
trezorhal::{display, qr, time, uzlib::UzlibContext}, trezorhal::{display, qr, time, uzlib::UzlibContext},
ui::lerp::Lerp, ui::{component::image::Image, lerp::Lerp},
}; };
use core::slice; use core::slice;
use crate::ui::component::image::Image;
pub use crate::ui::display::toif::Icon; pub use crate::ui::display::toif::Icon;
#[cfg(any(feature = "model_tt", feature = "model_tr"))] #[cfg(any(feature = "model_tt", feature = "model_tr"))]
pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN}; pub use loader::{loader, loader_indeterminate, LOADER_MAX, LOADER_MIN};
@ -228,8 +227,9 @@ pub fn rect_rounded2_partial(
let mut icon_width = 0; let mut icon_width = 0;
if let Some((icon, icon_color)) = icon { if let Some((icon, icon_color)) = icon {
if icon.toif.width() <= MAX_ICON_SIZE && icon.toif.height() <= MAX_ICON_SIZE { let icon_size = icon.toif.size();
icon_area = Rect::from_center_and_size(center, icon.toif.size); if icon_size.x <= MAX_ICON_SIZE && icon_size.y <= MAX_ICON_SIZE {
icon_area = Rect::from_center_and_size(center, icon_size);
icon_area_clamped = icon_area.clamp(constant::screen()); icon_area_clamped = icon_area.clamp(constant::screen());
icon.toif.uncompress(&mut icon_data); icon.toif.uncompress(&mut icon_data);
icon_colortable = get_color_table(icon_color, bg_color); icon_colortable = get_color_table(icon_color, bg_color);
@ -461,10 +461,10 @@ pub fn text_over_image(
empty_img.buffer.copy_from_slice(&img1.buffer); empty_img.buffer.copy_from_slice(&img1.buffer);
area = a; area = a;
r_img = Rect::from_top_left_and_size(a.top_left() + offset_img, image.toif.size); r_img = Rect::from_top_left_and_size(a.top_left() + offset_img, image.toif.size());
offset_img_final = offset_img; offset_img_final = offset_img;
} else { } else {
area = Rect::from_top_left_and_size(offset_img.into(), image.toif.size); area = Rect::from_top_left_and_size(offset_img.into(), image.toif.size());
r_img = area; r_img = area;
offset_img_final = Offset::zero(); offset_img_final = Offset::zero();
} }
@ -583,26 +583,26 @@ pub fn icon_over_icon(
let final_offset_bg; let final_offset_bg;
if let Some(a) = bg_area { if let Some(a) = bg_area {
area = a; area = a;
r_bg = Rect::from_top_left_and_size(a.top_left() + offset_bg, icon_bg.toif.size); r_bg = Rect::from_top_left_and_size(a.top_left() + offset_bg, icon_bg.toif.size());
final_offset_bg = offset_bg; final_offset_bg = offset_bg;
} else { } else {
r_bg = r_bg =
Rect::from_top_left_and_size(Point::new(offset_bg.x, offset_bg.y), icon_bg.toif.size); Rect::from_top_left_and_size(Point::new(offset_bg.x, offset_bg.y), icon_bg.toif.size());
area = r_bg; area = r_bg;
final_offset_bg = Offset::zero(); final_offset_bg = Offset::zero();
} }
let r_fg = Rect::from_top_left_and_size(area.top_left() + offset_fg, icon_fg.toif.size); let r_fg = Rect::from_top_left_and_size(area.top_left() + offset_fg, icon_fg.toif.size());
let clamped = area.clamp(constant::screen()).ensure_even_width(); let clamped = area.clamp(constant::screen()).ensure_even_width();
set_window(clamped); set_window(clamped);
let mut window_bg = [0; UZLIB_WINDOW_SIZE]; let mut window_bg = [0; UZLIB_WINDOW_SIZE];
let mut ctx_bg = UzlibContext::new(icon_bg.toif.data, Some(&mut window_bg)); let mut ctx_bg = UzlibContext::new(icon_bg.toif.zdata(), Some(&mut window_bg));
let mut window_fg = [0; UZLIB_WINDOW_SIZE]; let mut window_fg = [0; UZLIB_WINDOW_SIZE];
let mut ctx_fg = UzlibContext::new(icon_fg.toif.data, Some(&mut window_fg)); let mut ctx_fg = UzlibContext::new(icon_fg.toif.zdata(), Some(&mut window_fg));
dma2d_setup_4bpp_over_4bpp(color_icon_bg.into(), bg_color.into(), color_icon_fg.into()); dma2d_setup_4bpp_over_4bpp(color_icon_bg.into(), bg_color.into(), color_icon_fg.into());

View File

@ -1,5 +1,4 @@
use crate::{ use crate::{
trezorhal,
trezorhal::{ trezorhal::{
display::ToifFormat, display::ToifFormat,
uzlib::{UzlibContext, UZLIB_WINDOW_SIZE}, uzlib::{UzlibContext, UZLIB_WINDOW_SIZE},
@ -15,22 +14,8 @@ use super::Color;
const TOIF_HEADER_LENGTH: usize = 12; const TOIF_HEADER_LENGTH: usize = 12;
pub fn toif_info(data: &[u8]) -> Option<(Offset, ToifFormat)> {
if let Ok(info) = trezorhal::display::toif_info(data) {
Some((
Offset::new(
unwrap!(info.width.try_into()),
unwrap!(info.height.try_into()),
),
info.format,
))
} else {
None
}
}
pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) { pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) {
let r = Rect::from_center_and_size(center, icon.toif.size); let r = Rect::from_center_and_size(center, icon.toif.size());
let area = r.translate(get_offset()); let area = r.translate(get_offset());
let clamped = area.clamp(constant::screen()); let clamped = area.clamp(constant::screen());
let colortable = get_color_table(fg_color, bg_color); let colortable = get_color_table(fg_color, bg_color);
@ -65,29 +50,49 @@ pub fn icon(icon: &Icon, center: Point, fg_color: Color, bg_color: Color) {
} }
/// Holding toif data and allowing it to draw itself. /// Holding toif data and allowing it to draw itself.
/// See https://docs.trezor.io/trezor-firmware/misc/toif.html for data format.
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
pub struct Toif { pub struct Toif {
pub data: &'static [u8], data: &'static [u8],
pub size: Offset,
pub format: ToifFormat,
} }
impl Toif { impl Toif {
pub fn new(data: &'static [u8]) -> Self { pub const fn new(data: &'static [u8]) -> Option<Self> {
let info = unwrap!(toif_info(data)); if data.len() < TOIF_HEADER_LENGTH || data[0] != b'T' || data[1] != b'O' || data[2] != b'I'
Self { {
data: data[TOIF_HEADER_LENGTH..].as_ref(), return None;
size: info.0, }
format: info.1, let zdatalen = u32::from_le_bytes([data[8], data[9], data[10], data[11]]) as usize;
if zdatalen + TOIF_HEADER_LENGTH != data.len() {
return None;
}
Some(Self { data })
}
pub const fn format(&self) -> ToifFormat {
match self.data[3] {
b'f' => ToifFormat::FullColorBE,
b'g' => ToifFormat::GrayScaleOH,
b'F' => ToifFormat::FullColorLE,
b'G' => ToifFormat::GrayScaleEH,
_ => panic!(),
} }
} }
pub fn width(&self) -> i16 { pub const fn width(&self) -> i16 {
self.size.x u16::from_le_bytes([self.data[4], self.data[5]]) as i16
} }
pub fn height(&self) -> i16 { pub const fn height(&self) -> i16 {
self.size.y u16::from_le_bytes([self.data[6], self.data[7]]) as i16
}
pub const fn size(&self) -> Offset {
Offset::new(self.width(), self.height())
}
pub fn zdata(&self) -> &'static [u8] {
&self.data[TOIF_HEADER_LENGTH..]
} }
pub fn uncompress(&self, dest: &mut [u8]) { pub fn uncompress(&self, dest: &mut [u8]) {
@ -99,7 +104,7 @@ impl Toif {
&'a self, &'a self,
window: Option<&'a mut [u8; UZLIB_WINDOW_SIZE]>, window: Option<&'a mut [u8; UZLIB_WINDOW_SIZE]>,
) -> UzlibContext { ) -> UzlibContext {
UzlibContext::new(self.data, window) UzlibContext::new(self.zdata(), window)
} }
} }
@ -110,15 +115,15 @@ pub struct Icon {
impl Icon { impl Icon {
pub fn new(data: &'static [u8]) -> Self { pub fn new(data: &'static [u8]) -> Self {
let toif = Toif::new(data); let toif = unwrap!(Toif::new(data));
assert!(toif.format == ToifFormat::GrayScaleEH); assert!(toif.format() == ToifFormat::GrayScaleEH);
Self { toif } Self { toif }
} }
/// Display the icon with baseline Point, aligned according to the /// Display the icon with baseline Point, aligned according to the
/// `alignment` argument. /// `alignment` argument.
pub fn draw(&self, baseline: Point, alignment: Alignment2D, fg_color: Color, bg_color: Color) { pub fn draw(&self, baseline: Point, alignment: Alignment2D, fg_color: Color, bg_color: Color) {
let r = Rect::snap(baseline, self.toif.size, alignment); let r = Rect::snap(baseline, self.toif.size(), alignment);
icon(self, r.center(), fg_color, bg_color); icon(self, r.center(), fg_color, bg_color);
} }
} }

View File

@ -131,10 +131,11 @@ fn homescreen_position_text(
let text_width_clamped = text_width.clamp(0, screen().width()); let text_width_clamped = text_width.clamp(0, screen().width());
let icon_size = if let Some(icon) = text.icon { let icon_size = if let Some(icon) = text.icon {
assert!(icon.toif.width() <= HOMESCREEN_MAX_ICON_SIZE); let size = icon.toif.size();
assert!(icon.toif.height() <= HOMESCREEN_MAX_ICON_SIZE); assert!(size.x <= HOMESCREEN_MAX_ICON_SIZE);
assert!(size.y <= HOMESCREEN_MAX_ICON_SIZE);
icon.toif.uncompress(icon_buffer); icon.toif.uncompress(icon_buffer);
icon.toif.size size
} else { } else {
Offset::zero() Offset::zero()
}; };