diff --git a/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c b/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c index a3910845df..b7778884ac 100644 --- a/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c +++ b/core/embed/gfx/bitblt/stm32/dma2d_bitblt.c @@ -24,8 +24,27 @@ #include "../dma2d_bitblt.h" -static DMA2D_HandleTypeDef dma2d_handle = { - .Instance = (DMA2D_TypeDef*)DMA2D_BASE, +// Number of DMA2D layers - background (0) and foreground (1) +#define DMA2D_LAYER_COUNT 2 + +typedef struct { + // Set if the driver is initialized + bool initialized; + // ST DMA2D driver handle + DMA2D_HandleTypeDef handle; + // CLUT cache + struct { + gfx_color32_t c_fg; + gfx_color32_t c_bg; + } cache[DMA2D_LAYER_COUNT]; + + // CLUT is configured according to the cache + bool clut_valid; + +} dma2d_driver_t; + +static dma2d_driver_t g_dma2d_driver = { + .initialized = false, }; // Returns `true` if the specified address is accessible by DMA2D @@ -41,25 +60,45 @@ static inline bool dma2d_accessible(const void* ptr) { } void dma2d_init(void) { + dma2d_driver_t* drv = &g_dma2d_driver; + if (drv->initialized) { + return; + } + memset(drv, 0, sizeof(dma2d_driver_t)); + drv->handle.Instance = DMA2D; + __HAL_RCC_DMA2D_FORCE_RESET(); __HAL_RCC_DMA2D_RELEASE_RESET(); - __HAL_RCC_DMA2D_CLK_ENABLE(); + drv->initialized = true; } void dma2d_deinit(void) { + dma2d_driver_t* drv = &g_dma2d_driver; __HAL_RCC_DMA2D_CLK_DISABLE(); - __HAL_RCC_DMA2D_FORCE_RESET(); __HAL_RCC_DMA2D_RELEASE_RESET(); + memset(drv, 0, sizeof(dma2d_driver_t)); } void dma2d_wait(void) { - while (HAL_DMA2D_PollForTransfer(&dma2d_handle, 10) != HAL_OK) + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return; + } + + while (HAL_DMA2D_PollForTransfer(&drv->handle, 10) != HAL_OK) ; } bool dma2d_rgb565_fill(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + dma2d_wait(); if (!dma2d_accessible(bb->dst_row)) { @@ -67,38 +106,38 @@ bool dma2d_rgb565_fill(const gfx_bitblt_t* bb) { } if (bb->src_alpha == 255) { - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; - dma2d_handle.Init.Mode = DMA2D_R2M; - dma2d_handle.Init.OutputOffset = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_R2M; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - HAL_DMA2D_Start(&dma2d_handle, gfx_color_to_color32(bb->src_fg), + HAL_DMA2D_Start(&drv->handle, gfx_color_to_color32(bb->src_fg), (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), bb->width, bb->height); } else { #ifdef STM32U5 - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; - dma2d_handle.Init.Mode = DMA2D_M2M_BLEND_FG; - dma2d_handle.Init.OutputOffset = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_M2M_BLEND_FG; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; - dma2d_handle.LayerCfg[1].InputOffset = 0; - dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA; - dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; + drv->handle.LayerCfg[1].InputOffset = 0; + drv->handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA; + drv->handle.LayerCfg[1].InputAlpha = bb->src_alpha; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); - dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; - dma2d_handle.LayerCfg[0].InputOffset = + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; + drv->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); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); HAL_DMA2D_BlendingStart( - &dma2d_handle, gfx_color_to_color32(bb->src_fg), + &drv->handle, gfx_color_to_color32(bb->src_fg), (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); @@ -113,24 +152,22 @@ bool dma2d_rgb565_fill(const gfx_bitblt_t* bb) { static void dma2d_config_clut(uint32_t layer, gfx_color32_t fg, gfx_color32_t bg) { -#define LAYER_COUNT 2 + dma2d_driver_t* drv = &g_dma2d_driver; + #define GRADIENT_STEPS 16 - static struct { - gfx_color32_t c_fg; - gfx_color32_t c_bg; - } cache[LAYER_COUNT] = {0}; - - if (layer >= LAYER_COUNT) { + if (layer >= ARRAY_LENGTH(drv->cache)) { return; } volatile uint32_t* clut = - layer ? dma2d_handle.Instance->FGCLUT : dma2d_handle.Instance->BGCLUT; + layer ? drv->handle.Instance->FGCLUT : drv->handle.Instance->BGCLUT; - if (fg != cache[layer].c_fg || bg != cache[layer].c_bg) { - cache[layer].c_fg = fg; - cache[layer].c_bg = bg; + if (fg != drv->cache[layer].c_fg || bg != drv->cache[layer].c_bg || + !drv->clut_valid) { + drv->cache[layer].c_fg = fg; + drv->cache[layer].c_bg = bg; + drv->clut_valid = true; for (int step = 0; step < GRADIENT_STEPS; step++) { clut[step] = gfx_color32_rgba( @@ -145,7 +182,7 @@ static void dma2d_config_clut(uint32_t layer, gfx_color32_t fg, clut_def.Size = GRADIENT_STEPS - 1; clut_def.pCLUT = 0; // ??? - HAL_DMA2D_ConfigCLUT(&dma2d_handle, clut_def, layer); + HAL_DMA2D_ConfigCLUT(&drv->handle, clut_def, layer); } } @@ -180,6 +217,12 @@ static void dma2d_rgb565_copy_mono4_last_col(gfx_bitblt_t* bb, } bool dma2d_rgb565_copy_mono4(const gfx_bitblt_t* params) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + const gfx_color16_t* src_gradient = NULL; gfx_bitblt_t bb_copy = *params; @@ -211,48 +254,52 @@ bool dma2d_rgb565_copy_mono4(const gfx_bitblt_t* params) { bb->width -= 1; } - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; - dma2d_handle.Init.Mode = DMA2D_M2M_PFC; - dma2d_handle.Init.OutputOffset = - bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_M2M_PFC; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; - dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = 0; - dma2d_handle.LayerCfg[1].InputAlpha = 0; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; + drv->handle.LayerCfg[1].AlphaMode = 0; + drv->handle.LayerCfg[1].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); dma2d_config_clut(1, gfx_color_to_color32(bb->src_fg), gfx_color_to_color32(bb->src_bg)); - HAL_DMA2D_Start(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2, + HAL_DMA2D_Start(&drv->handle, (uint32_t)bb->src_row + bb->src_x / 2, (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), bb->width, bb->height); return true; } bool dma2d_rgb565_copy_rgb565(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + 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_PFC; - dma2d_handle.Init.OutputOffset = - bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_M2M_PFC; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; - dma2d_handle.LayerCfg[1].InputOffset = + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride / sizeof(uint16_t) - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = 0; - dma2d_handle.LayerCfg[1].InputAlpha = 0; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].AlphaMode = 0; + drv->handle.LayerCfg[1].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); - HAL_DMA2D_Start(&dma2d_handle, + HAL_DMA2D_Start(&drv->handle, (uint32_t)bb->src_row + bb->src_x * sizeof(uint16_t), (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint16_t), bb->width, bb->height); @@ -292,6 +339,12 @@ static void dma2d_rgb565_blend_mono4_last_col(const gfx_bitblt_t* bb) { } bool dma2d_rgb565_blend_mono4(const gfx_bitblt_t* params) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + dma2d_wait(); gfx_bitblt_t bb_copy = *params; @@ -318,31 +371,31 @@ bool dma2d_rgb565_blend_mono4(const gfx_bitblt_t* params) { } if (bb->width > 0) { - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; - dma2d_handle.Init.Mode = DMA2D_M2M_BLEND; - dma2d_handle.Init.OutputOffset = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_M2M_BLEND; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; - dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; - dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; + drv->handle.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; + drv->handle.LayerCfg[1].InputAlpha = bb->src_alpha; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); dma2d_config_clut( 1, gfx_color_to_color32(bb->src_fg), gfx_color32_set_alpha(gfx_color_to_color32(bb->src_fg), 0)); - dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; - dma2d_handle.LayerCfg[0].InputOffset = + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; + drv->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); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); HAL_DMA2D_BlendingStart( - &dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2, + &drv->handle, (uint32_t)bb->src_row + bb->src_x / 2, (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); @@ -352,32 +405,37 @@ bool dma2d_rgb565_blend_mono4(const gfx_bitblt_t* params) { } bool dma2d_rgb565_blend_mono8(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + 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 = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_RGB565; + drv->handle.Init.Mode = DMA2D_M2M_BLEND; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; + HAL_DMA2D_Init(&drv->handle); + + 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); + HAL_DMA2D_ConfigLayer(&drv->handle, 1); + + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565; + drv->handle.LayerCfg[0].InputOffset = bb->dst_stride / sizeof(uint16_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); - 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, + HAL_DMA2D_BlendingStart(&drv->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); @@ -386,6 +444,12 @@ bool dma2d_rgb565_blend_mono8(const gfx_bitblt_t* bb) { } bool dma2d_rgba8888_fill(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + dma2d_wait(); if (!dma2d_accessible(bb->dst_row)) { @@ -393,38 +457,38 @@ bool dma2d_rgba8888_fill(const gfx_bitblt_t* bb) { } if (bb->src_alpha == 255) { - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; - dma2d_handle.Init.Mode = DMA2D_R2M; - dma2d_handle.Init.OutputOffset = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; + drv->handle.Init.Mode = DMA2D_R2M; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - HAL_DMA2D_Start(&dma2d_handle, gfx_color_to_color32(bb->src_fg), + HAL_DMA2D_Start(&drv->handle, gfx_color_to_color32(bb->src_fg), (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width, bb->height); } else { #ifdef STM32U5 - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; - dma2d_handle.Init.Mode = DMA2D_M2M_BLEND_FG; - dma2d_handle.Init.OutputOffset = + drv->handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; + drv->handle.Init.Mode = DMA2D_M2M_BLEND_FG; + drv->handle.Init.OutputOffset = bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; - dma2d_handle.LayerCfg[1].InputOffset = 0; - dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA; - dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; + drv->handle.LayerCfg[1].InputOffset = 0; + drv->handle.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA; + drv->handle.LayerCfg[1].InputAlpha = bb->src_alpha; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); - dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; - dma2d_handle.LayerCfg[0].InputOffset = + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; + drv->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); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); HAL_DMA2D_BlendingStart( - &dma2d_handle, gfx_color_to_color32(bb->src_fg), + &drv->handle, gfx_color_to_color32(bb->src_fg), (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); @@ -467,8 +531,15 @@ static void dma2d_rgba8888_copy_mono4_last_col(gfx_bitblt_t* bb, } bool dma2d_rgba8888_copy_mono4(const gfx_bitblt_t* params) { - const gfx_color32_t* src_gradient = NULL; + dma2d_driver_t* drv = &g_dma2d_driver; + if (!drv->initialized) { + return false; + } + + dma2d_wait(); + + const gfx_color32_t* src_gradient = NULL; gfx_bitblt_t bb_copy = *params; gfx_bitblt_t* bb = &bb_copy; @@ -498,48 +569,52 @@ bool dma2d_rgba8888_copy_mono4(const gfx_bitblt_t* params) { bb->width -= 1; } - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; - dma2d_handle.Init.Mode = DMA2D_M2M_PFC; - dma2d_handle.Init.OutputOffset = - bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + 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; + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; - dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = 0; - dma2d_handle.LayerCfg[1].InputAlpha = 0; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; + drv->handle.LayerCfg[1].AlphaMode = 0; + drv->handle.LayerCfg[1].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); dma2d_config_clut(1, gfx_color_to_color32(bb->src_fg), gfx_color_to_color32(bb->src_bg)); - HAL_DMA2D_Start(&dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2, + HAL_DMA2D_Start(&drv->handle, (uint32_t)bb->src_row + bb->src_x / 2, (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width, bb->height); return true; } bool dma2d_rgba8888_copy_rgb565(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + 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_PFC; - dma2d_handle.Init.OutputOffset = - bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + 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; + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; - dma2d_handle.LayerCfg[1].InputOffset = + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride / sizeof(uint16_t) - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = 0; - dma2d_handle.LayerCfg[1].InputAlpha = 0; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].AlphaMode = 0; + drv->handle.LayerCfg[1].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); - HAL_DMA2D_Start(&dma2d_handle, + HAL_DMA2D_Start(&drv->handle, (uint32_t)bb->src_row + bb->src_x * sizeof(uint16_t), (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width, bb->height); @@ -579,6 +654,12 @@ static void dma2d_rgba8888_blend_mono4_last_col(const gfx_bitblt_t* bb) { } bool dma2d_rgba8888_blend_mono4(const gfx_bitblt_t* params) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + dma2d_wait(); gfx_bitblt_t bb_copy = *params; @@ -605,31 +686,31 @@ bool dma2d_rgba8888_blend_mono4(const gfx_bitblt_t* params) { } if (bb->width > 0) { - dma2d_handle.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; - dma2d_handle.Init.Mode = DMA2D_M2M_BLEND; - dma2d_handle.Init.OutputOffset = + 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; - HAL_DMA2D_Init(&dma2d_handle); + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; - dma2d_handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; - dma2d_handle.LayerCfg[1].InputAlpha = bb->src_alpha; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_L4; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride * 2 - bb->width; + drv->handle.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; + drv->handle.LayerCfg[1].InputAlpha = bb->src_alpha; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); dma2d_config_clut( 1, gfx_color_to_color32(bb->src_fg), gfx_color32_set_alpha(gfx_color_to_color32(bb->src_fg), 0)); - dma2d_handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; - dma2d_handle.LayerCfg[0].InputOffset = + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; + drv->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); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); HAL_DMA2D_BlendingStart( - &dma2d_handle, (uint32_t)bb->src_row + bb->src_x / 2, + &drv->handle, (uint32_t)bb->src_row + bb->src_x / 2, (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); @@ -639,32 +720,37 @@ bool dma2d_rgba8888_blend_mono4(const gfx_bitblt_t* params) { } bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + 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 = + 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; + HAL_DMA2D_Init(&drv->handle); + + 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); + HAL_DMA2D_ConfigLayer(&drv->handle, 1); + + drv->handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888; + drv->handle.LayerCfg[0].InputOffset = bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + drv->handle.LayerCfg[0].AlphaMode = 0; + drv->handle.LayerCfg[0].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 0); - 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, + HAL_DMA2D_BlendingStart(&drv->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); @@ -673,26 +759,31 @@ bool dma2d_rgba8888_blend_mono8(const gfx_bitblt_t* bb) { } bool dma2d_rgba8888_copy_rgba8888(const gfx_bitblt_t* bb) { + dma2d_driver_t* drv = &g_dma2d_driver; + + if (!drv->initialized) { + return false; + } + 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_PFC; - dma2d_handle.Init.OutputOffset = - bb->dst_stride / sizeof(uint32_t) - bb->width; - HAL_DMA2D_Init(&dma2d_handle); + 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; + HAL_DMA2D_Init(&drv->handle); - dma2d_handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; - dma2d_handle.LayerCfg[1].InputOffset = + drv->handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; + drv->handle.LayerCfg[1].InputOffset = bb->src_stride / sizeof(uint32_t) - bb->width; - dma2d_handle.LayerCfg[1].AlphaMode = 0; - dma2d_handle.LayerCfg[1].InputAlpha = 0; - HAL_DMA2D_ConfigLayer(&dma2d_handle, 1); + drv->handle.LayerCfg[1].AlphaMode = 0; + drv->handle.LayerCfg[1].InputAlpha = 0; + HAL_DMA2D_ConfigLayer(&drv->handle, 1); - HAL_DMA2D_Start(&dma2d_handle, + HAL_DMA2D_Start(&drv->handle, (uint32_t)bb->src_row + bb->src_x * sizeof(uint32_t), (uint32_t)bb->dst_row + bb->dst_x * sizeof(uint32_t), bb->width, bb->height);