1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-02-10 14:42:44 +00:00

feat(core): add simple downscaling for bitmap copy ops

[no changelog]
This commit is contained in:
cepetr 2025-02-08 13:20:46 +01:00
parent 599b1ea9ea
commit f3208bb950
6 changed files with 41 additions and 10 deletions

View File

@ -125,10 +125,10 @@ void gfx_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb) {
while (height-- > 0) {
for (int x = 0; x < bb->width; x++) {
dst_ptr[x] = src_ptr[x];
dst_ptr[x] = src_ptr[x << bb->src_downscale];
}
dst_ptr += bb->dst_stride / sizeof(*dst_ptr);
src_ptr += bb->src_stride / sizeof(*src_ptr);
src_ptr += (bb->src_stride / sizeof(*src_ptr)) << bb->src_downscale;
}
}
}

View File

@ -771,6 +771,10 @@ bool dma2d_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb) {
return false;
}
if (bb->src_downscale > 0) {
return false;
}
drv->handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
drv->handle.Init.Mode = DMA2D_M2M_PFC;
drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint32_t) - bb->width;

View File

@ -72,6 +72,9 @@ typedef struct {
gfx_color_t src_bg;
// Alpha value for fill operation (255 => normal fill, 0 => noop)
uint8_t src_alpha;
// Downscaling for the source bitmap
// (0 => no downscaling, 1 => 1/2, 2 => 1/4, 3 => 1/8)
uint8_t src_downscale;
} gfx_bitblt_t;

View File

@ -31,6 +31,7 @@ impl Default for ffi::gfx_bitblt_t {
src_x: 0,
src_y: 0,
src_alpha: 255,
src_downscale: 0,
}
}
}
@ -128,6 +129,15 @@ impl ffi::gfx_bitblt_t {
..self
}
}
/// Sets the downscaling for the source bitmap.
/// (0 = no downscale, 1 = 1/2, 2 = 1/4, 3 = 1/8)
fn with_downscale(self, downscale: u8) -> Self {
Self {
src_downscale: downscale,
..self
}
}
}
/// Rectangle filling operation.
@ -250,16 +260,18 @@ impl<'a> BitBltCopy<'a> {
// Clip with the bitmap top-left
if r.x0 > r_dst.x0 {
offset.x += r.x0 - r_dst.x0;
offset.x += (r.x0 - r_dst.x0) << src.downscale;
}
if r.y0 > r_dst.y0 {
offset.y += r.y0 - r_dst.y0;
offset.y += (r.y0 - r_dst.y0) << src.downscale;
}
// Clip with the bitmap size
r.x1 = r.x1.min(r.x0 + src.size().x - offset.x);
r.y1 = r.y1.min(r.y0 + src.size().y - offset.y);
r.x1 =
r.x1.min(r.x0 + ((src.size().x - offset.x) >> src.downscale));
r.y1 =
r.y1.min(r.y0 + ((src.size().y - offset.y) >> src.downscale));
if !r.is_empty() {
Some(Self {
@ -280,6 +292,7 @@ impl<'a> BitBltCopy<'a> {
.with_bg(src.bg_color)
.with_fg(src.fg_color)
.with_alpha(src.alpha)
.with_downscale(src.downscale)
},
src,
})

View File

@ -300,6 +300,7 @@ pub struct BitmapView<'a> {
pub fg_color: Color,
pub bg_color: Color,
pub alpha: u8,
pub downscale: u8,
}
impl<'a> BitmapView<'a> {
@ -311,6 +312,7 @@ impl<'a> BitmapView<'a> {
fg_color: Color::black(),
bg_color: Color::black(),
alpha: 255,
downscale: 0,
}
}
@ -337,6 +339,12 @@ impl<'a> BitmapView<'a> {
Self { alpha, ..self }
}
/// Builds a new structure with downscale set to the specified value
/// (0 means no downscale, 1 means 1/2, 2 means 1/4, etc.)
pub fn with_downscale(self, downscale: u8) -> Self {
Self { downscale, ..self }
}
/// Returns the bitmap width and height in pixels
pub fn size(&self) -> Offset {
self.bitmap.size

View File

@ -108,8 +108,6 @@ impl<'a> Shape<'a> for JpegImage<'a> {
let bounds = self.bounds();
let clip = canvas.viewport().relative_clip(bounds).clip;
let vp = canvas.set_clip(clip);
// Translate clip to JPEG relative coordinates
let clip = clip.translate(-canvas.viewport().origin);
let clip = clip.translate((-bounds.top_left()).into());
@ -119,6 +117,13 @@ impl<'a> Shape<'a> for JpegImage<'a> {
let mut jpegdec = unwrap!(JpegDecoder::new(self.jpeg));
let _ = jpegdec.decode(&mut buff[..], &mut |slice_r, slice| {
let slice = slice.with_downscale(self.scale);
let slice_r = Rect {
x0: slice_r.x0 >> self.scale,
y0: slice_r.y0 >> self.scale,
x1: slice_r.x1 >> self.scale,
y1: slice_r.y1 >> self.scale,
};
// Draw single slice
canvas.draw_bitmap(slice_r.translate(bounds.top_left().into()), slice);
// Return true if we are not done yet
@ -136,8 +141,6 @@ impl<'a> Shape<'a> for JpegImage<'a> {
// Blur the image
canvas.blur_rect(clip, self.blur_radius, cache);
}
canvas.set_viewport(vp);
}
// This is a little bit slower implementation suitable for ProgressiveRenderer