diff --git a/core/embed/lib/gfx_bitblt.h b/core/embed/lib/gfx_bitblt.h index bb0af66abe..f897d933b5 100644 --- a/core/embed/lib/gfx_bitblt.h +++ b/core/embed/lib/gfx_bitblt.h @@ -89,6 +89,9 @@ void gfx_rgb565_copy_rgb565(const gfx_bitblt_t* bb); // Blends a mono bitmap (with 4-bit alpha channel) // with the destination bitmap void gfx_rgb565_blend_mono4(const gfx_bitblt_t* bb); +// Blends a mono bitmap (with 8-bit alpha channel) +// with the destination bitmap +void gfx_rgb565_blend_mono8(const gfx_bitblt_t* bb); // Functions for RGBA8888 bitmap/framebuffer void gfx_rgba8888_fill(const gfx_bitblt_t* bb); @@ -103,6 +106,9 @@ void gfx_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb); // Blends a mono bitmap (with 4-bit alpha channel) // with the destination bitmap void gfx_rgba8888_blend_mono4(const gfx_bitblt_t* bb); +// Blends a mono bitmap (with 8-bit alpha channel) +// with the destination bitmap +void gfx_rgba8888_blend_mono8(const gfx_bitblt_t* bb); // Functions for Mono8 bitmap/framebuffer void gfx_mono8_fill(const gfx_bitblt_t* bb); diff --git a/core/embed/lib/gfx_bitblt_rgb565.c b/core/embed/lib/gfx_bitblt_rgb565.c index 5ee3059d3e..8648f5267a 100644 --- a/core/embed/lib/gfx_bitblt_rgb565.c +++ b/core/embed/lib/gfx_bitblt_rgb565.c @@ -135,3 +135,24 @@ void gfx_rgb565_blend_mono4(const gfx_bitblt_t* bb) { } } } + +void gfx_rgb565_blend_mono8(const gfx_bitblt_t* bb) { +#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR) + if (!dma2d_rgb565_blend_mono8(bb)) +#endif + { + uint16_t* dst_ptr = (uint16_t*)bb->dst_row + bb->dst_x; + uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x; + uint16_t height = bb->height; + + while (height-- > 0) { + for (int x = 0; x < bb->width; x++) { + uint8_t fg_alpha = src_ptr[x]; + dst_ptr[x] = gfx_color16_blend_a8( + bb->src_fg, gfx_color16_to_color(dst_ptr[x]), fg_alpha); + } + dst_ptr += bb->dst_stride / sizeof(*dst_ptr); + src_ptr += bb->src_stride / sizeof(*src_ptr); + } + } +} diff --git a/core/embed/lib/gfx_bitblt_rgba8888.c b/core/embed/lib/gfx_bitblt_rgba8888.c index a7c50ddcc0..1eab15525c 100644 --- a/core/embed/lib/gfx_bitblt_rgba8888.c +++ b/core/embed/lib/gfx_bitblt_rgba8888.c @@ -155,3 +155,24 @@ void gfx_rgba8888_blend_mono4(const gfx_bitblt_t* bb) { } } } + +void gfx_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { +#if defined(USE_DMA2D) && !defined(TREZOR_EMULATOR) + if (!dma2d_rgba8888_blend_mono8(bb)) +#endif + { + uint32_t* dst_ptr = (uint32_t*)bb->dst_row + bb->dst_x; + uint8_t* src_ptr = (uint8_t*)bb->src_row + bb->src_x; + uint16_t height = bb->height; + + while (height-- > 0) { + for (int x = 0; x < bb->width; x++) { + uint8_t fg_alpha = src_ptr[x]; + dst_ptr[x] = gfx_color32_blend_a8( + bb->src_fg, gfx_color32_to_color(dst_ptr[x]), fg_alpha); + } + dst_ptr += bb->dst_stride / sizeof(*dst_ptr); + src_ptr += bb->src_stride / sizeof(*src_ptr); + } + } +} diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 7277d94e43..e95c9678c6 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -352,11 +352,13 @@ fn generate_trezorhal_bindings() { .allowlist_function("gfx_rgb565_copy_mono4") .allowlist_function("gfx_rgb565_copy_rgb565") .allowlist_function("gfx_rgb565_blend_mono4") + .allowlist_function("gfx_rgb565_blend_mono8") .allowlist_function("gfx_rgba8888_fill") .allowlist_function("gfx_rgba8888_copy_mono4") .allowlist_function("gfx_rgba8888_copy_rgb565") .allowlist_function("gfx_rgba8888_copy_rgba8888") .allowlist_function("gfx_rgba8888_blend_mono4") + .allowlist_function("gfx_rgba8888_blend_mono8") .allowlist_function("gfx_mono8_fill") .allowlist_function("gfx_mono8_copy_mono1p") .allowlist_function("gfx_mono8_copy_mono4") diff --git a/core/embed/rust/src/trezorhal/bitblt.rs b/core/embed/rust/src/trezorhal/bitblt.rs index e00cb114cc..dea82a0ea6 100644 --- a/core/embed/rust/src/trezorhal/bitblt.rs +++ b/core/embed/rust/src/trezorhal/bitblt.rs @@ -325,6 +325,7 @@ impl<'a> BitBltCopy<'a> { let bitblt = self.bitblt.with_dst(dst); match self.src.format() { BitmapFormat::MONO4 => ffi::gfx_rgb565_blend_mono4(&bitblt), + BitmapFormat::MONO8 => ffi::gfx_rgb565_blend_mono8(&bitblt), _ => unimplemented!(), } } @@ -369,6 +370,7 @@ impl<'a> BitBltCopy<'a> { let bitblt = self.bitblt.with_dst(dst); match self.src.format() { BitmapFormat::MONO4 => ffi::gfx_rgba8888_blend_mono4(&bitblt), + BitmapFormat::MONO8 => ffi::gfx_rgba8888_blend_mono8(&bitblt), _ => unimplemented!(), } } diff --git a/core/embed/trezorhal/dma2d_bitblt.h b/core/embed/trezorhal/dma2d_bitblt.h index a000a7008f..0f3aa26bb1 100644 --- a/core/embed/trezorhal/dma2d_bitblt.h +++ b/core/embed/trezorhal/dma2d_bitblt.h @@ -35,11 +35,13 @@ bool dma2d_rgb565_fill(const gfx_bitblt_t* bb); bool dma2d_rgb565_copy_mono4(const gfx_bitblt_t* bb); bool dma2d_rgb565_copy_rgb565(const gfx_bitblt_t* bb); bool dma2d_rgb565_blend_mono4(const gfx_bitblt_t* bb); +bool dma2d_rgb565_blend_mono8(const gfx_bitblt_t* bb); bool dma2d_rgba8888_fill(const gfx_bitblt_t* bb); bool dma2d_rgba8888_copy_mono4(const gfx_bitblt_t* bb); bool dma2d_rgba8888_copy_rgb565(const gfx_bitblt_t* bb); bool dma2d_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb); bool dma2d_rgba8888_blend_mono4(const gfx_bitblt_t* bb); +bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t* bb); #endif // TREZORHAL_DMA2D_BITBLT_H diff --git a/core/embed/trezorhal/stm32f4/dma2d_bitblt.c b/core/embed/trezorhal/stm32f4/dma2d_bitblt.c index 36ec4762cb..65ab14f7bd 100644 --- a/core/embed/trezorhal/stm32f4/dma2d_bitblt.c +++ b/core/embed/trezorhal/stm32f4/dma2d_bitblt.c @@ -337,6 +337,40 @@ bool dma2d_rgb565_blend_mono4(const gfx_bitblt_t* params) { return true; } +bool dma2d_rgb565_blend_mono8(const gfx_bitblt_t* bb) { + dma2d_wait(); + + if (!dma2d_accessible(bb->dst_row) || !dma2d_accessible(bb->src_row)) { + return false; + } + + dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + dma2d_handle.Init.Mode = DMA2D_M2M_BLEND; + dma2d_handle.Init.OutputOffset = + bb->dst_stride / sizeof(uint16_t) - bb->width; + HAL_DMA2D_Init(&dma2d_handle); + + dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8; + dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride - bb->width; + dma2d_handle.LayerCfg[1].AlphaMode = 0; + dma2d_handle.LayerCfg[1].InputAlpha = gfx_color_to_color32(bb->src_fg); + HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + + dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; + dma2d_handle.LayerCfg[0].InputOffset = + bb->dst_stride / sizeof(uint16_t) - bb->width; + dma2d_handle.LayerCfg[0].AlphaMode = 0; + dma2d_handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&dma2d_handle, 0); + + HAL_DMA2D_BlendingStart(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x, + (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), + (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), + bb->width, bb->height); + + return true; +} + bool dma2d_rgba8888_fill(const gfx_bitblt_t* bb) { dma2d_wait(); @@ -590,6 +624,40 @@ bool dma2d_rgba8888_blend_mono4(const gfx_bitblt_t* params) { return true; } +bool dma2d_rgb8888_blend_mono8(const gfx_bitblt_t* bb) { + dma2d_wait(); + + if (!dma2d_accessible(bb->dst_row) || !dma2d_accessible(bb->src_row)) { + return false; + } + + dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; + dma2d_handle.Init.Mode = DMA2D_M2M_BLEND; + dma2d_handle.Init.OutputOffset = + bb->dst_stride / sizeof(uint32_t) - bb->width; + HAL_DMA2D_Init(&dma2d_handle); + + dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8; + dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride - bb->width; + dma2d_handle.LayerCfg[1].AlphaMode = 0; + dma2d_handle.LayerCfg[1].InputAlpha = gfx_color_to_color32(bb->src_fg); + HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + + dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; + dma2d_handle.LayerCfg[0].InputOffset = + bb->dst_stride / sizeof(uint32_t) - bb->width; + dma2d_handle.LayerCfg[0].AlphaMode = 0; + dma2d_handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&dma2d_handle, 0); + + HAL_DMA2D_BlendingStart(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x, + (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), + (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), + bb->width, bb->height); + + return true; +} + bool dma2d_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb) { dma2d_wait();