After using gpu, the demo does not display properly. But without using gpu, it works fine

Description

I want to improve the display speed, so I opened the GPU, I consulted lv_port_stm32f746_disco_sw4stm32 engineering.
After enabling the GPU, demo showed abnormal, but do not use GPU, can display properly.

What MCU/Processor/Board and compiler are you using?

Processor is stm32h743iit6, this is my homemade board.

What do you want to achieve?

I want to improve the display speed

What have you tried so far?

Code to reproduce

static void lv_gpu_dma2d_config(void)
{
	/* Configure the DMA2D Mode, Color Mode and output offset */
	DMA2D_Handle.Init.Mode           = DMA2D_M2M_BLEND;
	#if LV_COLOR_DEPTH == 16
		DMA2D_Handle.Init.ColorMode    = DMA2D_OUTPUT_RGB565;
	#elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32
		DMA2D_Handle.Init.ColorMode    = LTDC_PIXEL_FORMAT_ARGB8888;
	#endif
	DMA2D_Handle.Init.OutputOffset   = 0;
	DMA2D_Handle.Init.RedBlueSwap    = DMA2D_RB_REGULAR;
	DMA2D_Handle.Init.AlphaInverted  = DMA2D_REGULAR_ALPHA;

	/* DMA2D Callbacks Configuration */
	DMA2D_Handle.XferCpltCallback  = DMA2D_TransferComplete;
	DMA2D_Handle.XferErrorCallback = DMA2D_TransferError;

	/* Foreground Configuration */
	DMA2D_Handle.LayerCfg[1].AlphaMode  = DMA2D_REPLACE_ALPHA;
	DMA2D_Handle.LayerCfg[1].InputAlpha = 0;
	DMA2D_Handle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
	DMA2D_Handle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;
	#if LV_COLOR_DEPTH == 16
		DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
	#elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32
		DMA2D_Handle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
	#endif
	DMA2D_Handle.LayerCfg[1].InputOffset = 0x0;

	/* Background Configuration */
	DMA2D_Handle.LayerCfg[0].AlphaMode = DMA2D_REPLACE_ALPHA;
	DMA2D_Handle.LayerCfg[0].InputAlpha = 0;
	DMA2D_Handle.LayerCfg[0].AlphaInverted = DMA2D_REGULAR_ALPHA;
	DMA2D_Handle.LayerCfg[0].RedBlueSwap = DMA2D_RB_REGULAR;
	#if LV_COLOR_DEPTH == 16
		DMA2D_Handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_RGB565;
	#elif LV_COLOR_DEPTH == 24 || LV_COLOR_DEPTH == 32
		DMA2D_Handle.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;
	#endif
	DMA2D_Handle.LayerCfg[0].InputOffset = 0x0;

	DMA2D_Handle.Instance   = DMA2D;

	/* DMA2D Initialization */
	if(HAL_DMA2D_Init(&DMA2D_Handle) != HAL_OK)
	{
		/* Initialization Error */
		Error_Handler(__FILE__, __LINE__);
	}

	HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 0);
	HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 1);
}

static void gpu_mem_blend(lv_disp_drv_t *disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa)
{
	/*Wait for the previous operation*/
	HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 100);
	DMA2D_Handle.Init.Mode      = DMA2D_M2M_BLEND;
	
	/* DMA2D Initialization */
	if(HAL_DMA2D_Init(&DMA2D_Handle) != HAL_OK)
	{
		/* Initialization Error */
		while(1);
	}

	DMA2D_Handle.LayerCfg[1].InputAlpha = opa;
	HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 1);
	HAL_DMA2D_BlendingStart(&DMA2D_Handle, (uint32_t) src, (uint32_t) dest, (uint32_t)dest, length, 1);
}

static void gpu_mem_fill(lv_disp_drv_t *disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
        const lv_area_t * fill_area, lv_color_t color)
{
	/*Wait for the previous operation*/
	HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 100);

   DMA2D_Handle.Init.Mode         = DMA2D_R2M;
   /* DMA2D Initialization */
   if(HAL_DMA2D_Init(&DMA2D_Handle) != HAL_OK)
   {
     /* Initialization Error */
     while(1);
   }

   DMA2D_Handle.LayerCfg[1].InputAlpha = 0xff;
   HAL_DMA2D_ConfigLayer(&DMA2D_Handle, 1);

   lv_color_t * dest_buf_ofs = dest_buf;

   dest_buf_ofs += dest_width * fill_area->y1;
   dest_buf_ofs += fill_area->x1;
   lv_coord_t area_w = lv_area_get_width(fill_area);

   uint32_t i;
   for(i = fill_area->y1; i <= fill_area->y2; i++) {
	   /*Wait for the previous operation*/
	   HAL_DMA2D_PollForTransfer(&DMA2D_Handle, 100);
	   HAL_DMA2D_BlendingStart(&DMA2D_Handle, (uint32_t) lv_color_to32(color), (uint32_t) dest_buf_ofs, (uint32_t)dest_buf_ofs, area_w, 1);
	   dest_buf_ofs += dest_width;
   }
}

Screenshot and/or video

Could you tell me this how to solve

Next time please format your code like this:

```
your 
code 
here
```

It seems the opacity is not handled properly in gpu_blend.

I don’t have this board but I compared your dma2d_init function with the one from stm32f429 project and found that you set 0x00 instead of 0xff InputAlpha for the layers.

I’m sorry, I don’t have the correct fill in the template
My final code:

/**
 * @file lv_port_disp_templ.c
 *
 */

 /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1

/*********************
 *      INCLUDES
 *********************/
#include "bsp.h"
#include "lv_port_disp_template.h"

static lv_disp_t*          main_disp = NULL;
static __IO uint16_t* disp_flush_buf = (__IO uint16_t*)(SDRAM_BANK_ADDR);

static void disp_init(void);
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

#if LV_USE_GPU
static DMA2D_HandleTypeDef DMA2D_Handle;
static void lv_gpu_dma2d_config(void);
static void gpu_blend(struct _disp_drv_t* disp_drv, lv_color_t* dest, const lv_color_t* src, uint32_t length,lv_opa_t opa);
static void gpu_fill(struct _disp_drv_t* disp_drv, lv_color_t* dest_buf, lv_coord_t dest_width, const lv_area_t* fill_area, lv_color_t color);
#endif

void lv_port_disp_init(void)
{
  lv_init();  
	
	/*-------------------------
	* Initialize your display
	* -----------------------*/
	disp_init();
//	lv_disp_dma_config();

	/*-----------------------------
	* Create a buffer for drawing
	*----------------------------*/

	/* LittlevGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row
	*
	* There are three buffering configurations:
	* 1. Create ONE buffer with some rows: 
	*      LittlevGL will draw the display's content here and writes it to your display
	* 
	* 2. Create TWO buffer with some rows: 
	*      LittlevGL will draw the display's content to a buffer and writes it your display.
	*      You should use DMA to write the buffer's content to the display.
	*      It will enable LittlevGL to draw the next part of the screen to the other buffer while
	*      the data is being sent form the first buffer. It makes rendering and flushing parallel.
	* 
	* 3. Create TWO screen-sized buffer: 
	*      Similar to 2) but the buffer have to be screen sized. When LittlevGL is ready it will give the
	*      whole frame to display. This way you only need to change the frame buffer's address instead of
	*      copying the pixels.
	* */
		 
	static lv_disp_buf_t disp_buf;
	static lv_color_t* buf_1 = NULL;
	buf_1 = (lv_color_t*)osRtxMemoryAlloc(AppMallocSDRAM, LV_HOR_RES_MAX *LV_VER_RES_MAX*2, 0);                       
//	static lv_color_t* buf_2 = NULL;
//	buf_2 = (lv_color_t*)osRtxMemoryAlloc(AppMallocSDRAM, LV_HOR_RES_MAX * LV_VER_RES_MAX*2, 0);                       
	lv_disp_buf_init(&disp_buf, buf_1, NULL, LV_HOR_RES_MAX *LV_VER_RES_MAX);   /*Initialize the display buffer*/

	/*-----------------------------------
	* Register the display in LittlevGL
	*----------------------------------*/

	lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
	lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

	/*Set up the functions to access to your display*/

	/*Set the resolution of the display*/
	disp_drv.hor_res = 1024;
	disp_drv.ver_res = 600;

	/*Used to copy the buffer's content to the display*/
	disp_drv.flush_cb = disp_flush;

	/*Set a display buffer*/
	disp_drv.buffer = &disp_buf;

#if LV_USE_GPU
  lv_gpu_dma2d_config();
	
	/*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/
	/*Blend two color array using opacity*/
	disp_drv.gpu_blend_cb = gpu_blend;

	/*Fill a memory array with a color*/
	disp_drv.gpu_fill_cb  = gpu_fill;
#endif

	/*Finally register the driver*/
	main_disp = lv_disp_drv_register(&disp_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/* Initialize your display and the required peripherals. */
static void disp_init(void)
{
	/*You code here*/
	LCD_ConfigLTDC();
}

/* Flush the content of the internal buffer the specific area on the display
 * You can use DMA or any hardware acceleration to do this operation in the background but
 * 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{	
	/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->y2 < 0) return;
	if(area->x1 > LV_HOR_RES_MAX - 1) return;
	if(area->y1 > LV_VER_RES_MAX - 1) return;

	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
	int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
	int32_t act_x2 = area->x2 > LV_HOR_RES_MAX - 1 ? LV_HOR_RES_MAX - 1 : area->x2;
	int32_t act_y2 = area->y2 > LV_VER_RES_MAX - 1 ? LV_VER_RES_MAX - 1 : area->y2;
	
	uint32_t y; uint16_t* disbuf = (uint16_t*)SDRAM_BANK_ADDR;
	for(y = act_y1; y <= act_y2; y++) 
	{
		memcpy((void*)&disp_flush_buf[y * LV_HOR_RES_MAX + act_x1],
						color_p, (act_x2 - act_x1 + 1) * sizeof(disbuf[0]));
		color_p += area->x2 - area->x1 + 1;               /*Skip the parts out of the screen*/
	}	
	lv_disp_flush_ready(disp_drv);
}


/*OPTIONAL: GPU INTERFACE*/
#if LV_USE_GPU

 static void lv_dma_color_mix(uint32_t * pColorFG,   
															uint32_t OffLineSrcFG, 
															uint32_t * pColorDst,  
															uint32_t OffLineDst, 
															uint32_t xSize,  
															uint32_t ySize,  
															uint8_t Intens) 
{  
	/* DMA2D USES memory to memory model, 
	 this model foreground and background layer as DMA2D input, 
	 and support for color conversion and color mixing */
	DMA2D->CR      = 0x00020000UL | (1 << 9); 
	DMA2D->FGMAR   = (uint32_t)pColorFG; 
	DMA2D->BGMAR   = (uint32_t)pColorDst; 
	DMA2D->OMAR    = (uint32_t)pColorDst; 
	DMA2D->FGOR    = OffLineSrcFG; 
	DMA2D->BGOR    = OffLineDst; 
	DMA2D->OOR     = OffLineDst; 
	
	/* Set foreground layer, background layer 
	   and the output area for RGB565 format */ 
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565 
	| (1UL << 16)    | ((uint32_t)Intens << 24); 
	DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_RGB565; 
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;   
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize; 

	/* Start mixing */ 
	DMA2D->CR   |= DMA2D_CR_START;    

	/* Wait to finish */ 
	while (DMA2D->CR & DMA2D_CR_START) {}  
} 

static void lv_dma2d_fill(void * pDst, uint32_t xSize, uint32_t ySize,  
												uint32_t OffLine, uint32_t ColorIndex, uint32_t PixelFormat)  
{     	 
       /*  DMA2D use registers to store model, 
	*  this model does not use the foreground and background layer */  
	DMA2D->CR      = 0x00030000UL | (1 << 9); 
	DMA2D->OCOLR   = ColorIndex; 
	DMA2D->OMAR    = (uint32_t)pDst; 
	DMA2D->OOR     = OffLine; 
	DMA2D->OPFCCR  = PixelFormat; 
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize; 

	/* Starting */ 
	DMA2D->CR   |= DMA2D_CR_START;    

	/* Wait to finish */
	while (DMA2D->CR & DMA2D_CR_START) {}   SCB_CleanInvalidateDCache(); 
} 

/* If your MCU has hardware accelerator (GPU) then you can use it to blend to memories using opacity
 * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
static void gpu_blend(struct _disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length,
                         lv_opa_t opa)
{	
	lv_dma_color_mix((uint32_t *)src, 0, (uint32_t *)dest, 0, length, 1, opa);
	SCB_CleanInvalidateDCache();
}


/* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color
 * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/
static void gpu_fill(struct _disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
                        const lv_area_t * fill_area, lv_color_t color)
{	
	uint32_t tmp  = 0;
	uint32_t tmp1 = 0;
	uint32_t tmp2 = 0;
	uint32_t tmp3 = 0;
	uint32_t tmp4 = 0;
	
	lv_color_t * dest_buf_ofs = dest_buf;
	
	dest_buf_ofs += dest_width * fill_area->y1;
	dest_buf_ofs += fill_area->x1;
	lv_coord_t area_w = lv_area_get_width(fill_area);
	
	tmp  = lv_color_to32(color);
	tmp1 = tmp & DMA2D_OCOLR_ALPHA_1;
	tmp2 = tmp & DMA2D_OCOLR_RED_1;
	tmp3 = tmp & DMA2D_OCOLR_GREEN_1;
	tmp4 = tmp & DMA2D_OCOLR_BLUE_1;
	
	tmp2 = (tmp2 >> 19);
	tmp3 = (tmp3 >> 10);
	tmp4 = (tmp4 >> 3 );
	tmp  = ((tmp3 << 5) | (tmp2 << 11) | tmp4); 

	uint32_t i;
	for(i = fill_area->y1; i <= fill_area->y2; i++) 
	{
		lv_dma2d_fill((uint32_t*)dest_buf_ofs, area_w, 1,
								 1024-area_w, (uint32_t)tmp, LTDC_PIXEL_FORMAT_RGB565);
		dest_buf_ofs += dest_width;
	}
}

static void lv_gpu_dma2d_config(void)
{
	/* Enable the dma clock */
	__HAL_RCC_DMA2D_CLK_ENABLE();
}

#endif  /*LV_USE_GPU*/

#else /* Enable this file at the top */

/* This dummy typedef exists purely to silence -Wpedantic. */
typedef int keep_pedantic_happy;
#endif

So this code is working?

No, I still don’t know what to do about this issue. :sob:can you help me? thank you

In your last post lv_gpu_dma2d_config is empty. The function you posted here looked good except the InputApha fields as I’ve described here.