diff --git a/core/embed/gfx/bitblt/gfx_bitblt_rgba8888.c b/core/embed/gfx/bitblt/gfx_bitblt_rgba8888.c index 015b0c9d68..6329946381 100644 --- a/core/embed/gfx/bitblt/gfx_bitblt_rgba8888.c +++ b/core/embed/gfx/bitblt/gfx_bitblt_rgba8888.c @@ -165,14 +165,26 @@ void gfx_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { 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); + if (bb->src_alpha == 255) { + 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); + } + } else { + while (height-- > 0) { + for (int x = 0; x < bb->width; x++) { + uint8_t fg_alpha = (src_ptr[x] * bb->src_alpha) / 255; + 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); } - dst_ptr += bb->dst_stride / sizeof(*dst_ptr); - src_ptr += bb->src_stride / sizeof(*src_ptr); } } } diff --git a/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c b/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c index d2ff25fb34..7379ca0fa7 100644 --- a/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c +++ b/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c @@ -786,6 +786,9 @@ bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { return false; } + uint32_t src_fg = + gfx_color32_replace_a(gfx_color_to_color32(bb->src_fg), bb->src_alpha); + drv->handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; drv->handle.Init.Mode = DMA2D_M2M_BLEND; drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint32_t) - bb->width; @@ -793,8 +796,8 @@ bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8; drv->handle.LayerCfg[1].InputOffset = bb->src_stride - bb->width; - drv->handle.LayerCfg[1].AlphaMode = 0; - drv->handle.LayerCfg[1].InputAlpha = gfx_color_to_color32(bb->src_fg); + drv->handle.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; + drv->handle.LayerCfg[1].InputAlpha = src_fg; HAL_DMA2D_ConfigLayer(&drv->handle, 1); drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; diff --git a/core/embed/gfx/inc/gfx/gfx_color.h b/core/embed/gfx/inc/gfx/gfx_color.h index 4b0a10f7b3..235eeceebf 100644 --- a/core/embed/gfx/inc/gfx/gfx_color.h +++ b/core/embed/gfx/inc/gfx/gfx_color.h @@ -86,6 +86,8 @@ typedef uint32_t gfx_color32_t; #define gfx_color32_to_b(c) (((c) & 0x000000FF) >> 0) // Extracts alpha component from gfx_color32_t #define gfx_color32_to_a(c) (((c) & 0xFF000000) >> 24) +// Sets alpha component of gfx_color32_t +#define gfx_color32_replace_a(c, a) (((c) & 0x00FFFFFF) | ((a) << 24)) // 4-bit linear interpolation between `fg` and `bg` #define a4_lerp(fg, bg, alpha) (((fg) * (alpha) + ((bg) * (15 - (alpha)))) / 15)