Black flickering boxes intermittently appearing on display when scrolling

Hi @kdschlosser, @Baldhead, @Marian_M,

Thank you to all for your suggestions and support…

Just wanted to report I have finally resolved my issues with this platform.

@kdschlosser I was unable to get good performance by copying the buffers in the way you suggested. Having a Full HD 1920 x 1080 pixel (8Megabyte) frame buffer was just taking to long to copy. :slightly_frowning_face:

It turned out there were multiple issues to resolve:

  1. The manufacturers bare metal drivers are broken, I have created my own.
  2. Some of the hardware registers are not documented in the official documentation, I found some clues by examining the driver provided by the manufacturer in the Linux source tree. Now I am able to create proper frame synchronisation.
  3. Generally the manufacturers documentation is very poor for the Displayport Interface on my chosen platform, the language and description is quite ambiguous and not easy to interpret.
  4. There were also some caching issues to do with the update of the DMA descriptors causing the use of incorrect buffer addresses intermittently.
  5. Triple buffering was also required to allow the smooth change between an active buffer and an offline buffer during VSYNC, it seems LVGL now supports this natively in the latest master so I have used it. I can confirm it works well. Currently it doesn’t seem to be documented, but I did this to initialise LVGL:
	lv_init();
	lv_log_register_print_cb( lv_log_print );
	cpu0_globals->gui.disp = lv_display_create( HOR_RES_MAX, VER_RES_MAX);
	lv_display_set_color_format(cpu0_globals->gui.disp, LV_COLOR_FORMAT_ARGB8888 ); 
	lv_display_set_buffers(cpu0_globals->gui.disp, (void*)cpu0_globals->dp_data->raw_vbuf_ptr1,
		(void*)cpu0_globals->dp_data->raw_vbuf_ptr2, DP_BUF_SIZE, LV_DISPLAY_RENDER_MODE_DIRECT);
	static lv_draw_buf_t third_vid_buf;
	memset( &third_vid_buf, 0, sizeof( third_vid_buf ) );
    lv_color_format_t cf = lv_display_get_color_format(cpu0_globals->gui.disp);
    uint32_t w = lv_display_get_original_horizontal_resolution(cpu0_globals->gui.disp);
    uint32_t h = lv_display_get_original_vertical_resolution(cpu0_globals->gui.disp);
    uint32_t stride = lv_draw_buf_width_to_stride(w, cf);
    lv_draw_buf_init(&third_vid_buf, w, h, cf, stride, cpu0_globals->dp_data->raw_vbuf_ptr3, DP_BUF_SIZE);
	lv_display_set_3rd_draw_buffer( cpu0_globals->gui.disp, &third_vid_buf );
	lv_display_set_flush_cb(cpu0_globals->gui.disp, (lv_display_flush_cb_t)dp_flush);
	// Initialise Display Port Hardware
	init_dp_controller(); 

Then the 3 buffers are managed like this in the flush callback:

void dp_flush( lv_display_t *disp_drv, const lv_area_t *area, uint8_t *data ) {

	uint32_t		event = 0;
	otg_sysmsg_t	msg = { 0, NULL, 0, 0, log_src_dp, NULL, 0 };

	if( cpu0_globals->dp_data->status & DP_LINK_TRAINED ) {
		if( lv_display_flush_is_last( disp_drv ) && (cpu0_globals->dp_data->dma_next_buf != NULL) ) {
			if( ( (uintptr_t)data == cpu0_globals->dp_data->dma_fb1.addr ) ) {	// Set the new buffer
				cpu0_globals->dp_data->dma_next_buf = &cpu0_globals->dp_data->dma_fb1;
			} else if( ( (uintptr_t)data == cpu0_globals->dp_data->dma_fb2.addr ) ) {
				cpu0_globals->dp_data->dma_next_buf = &cpu0_globals->dp_data->dma_fb2;
			} else {
				cpu0_globals->dp_data->dma_next_buf = &cpu0_globals->dp_data->dma_fb3;
			}
		}
	}
	lv_display_flush_ready(disp_drv);

This works well for me…

I also have two ARM A53 cores running a FreeRTOS SMP port so I also added a single software draw unit and this has improved the frame rate also.

Hopefully this will be helpful to someone else in the future.

Thanks again for the help and suggestions…

Kind Regards,

Pete

1 Like