V8 display driver (double buffer) low FPS & high CPU

Hi @gianlucacornacchia ,

My hardware will be different to yours but I am doing the same thing from a hardware/software functional point of view.

You haven’t shared all of your relevant code but here is my approach, hopefully it will show something to help:

void gui_update_thread(void *p) {

	cpu0_globals->spawn_stat |= GUI_RUN;
	// Initialise VGA Hardware
	set_vga_prams( VGA_1440X900_60HZ_CVTR );
	// Initialise GUI
	lv_init();
	lv_theme_default_init(cpu0_globals->gui.disp, shmem_p->personality == OTG_IDU ? confp->sys.IDU_gui_colour :
	  confp->sys.ODU_gui_colour, lv_palette_main(LV_PALETTE_PURPLE), (((shmem_p->personality == OTG_IDU) ? confp->sys.IDU_style :
	  confp->sys.ODU_style) ? 0 : 1), LV_FONT_DEFAULT);
	lv_disp_drv_init((lv_disp_drv_t*)&cpu0_globals->gui.disp_drv);
	lv_disp_draw_buf_init(&cpu0_globals->gui.disp_buf, (void*)LV_VDB_ADR, (void*)LV_VDB2_ADR, (LV_HOR_RES_MAX*LV_VER_RES_MAX));
	cpu0_globals->gui.disp_drv.flush_cb = vga_disp_flush;
	cpu0_globals->gui.disp_drv.hor_res = LV_HOR_RES_MAX;                 /*Set the horizontal resolution in pixels*/
	cpu0_globals->gui.disp_drv.ver_res = LV_VER_RES_MAX;                 /*Set the vertical resolution in pixels*/
	cpu0_globals->gui.disp_drv.draw_buf = &cpu0_globals->gui.disp_buf;
	cpu0_globals->gui.disp_drv.full_refresh = pdFALSE;
	cpu0_globals->gui.disp_drv.direct_mode = pdTRUE;
	cpu0_globals->gui.disp = lv_disp_drv_register((lv_disp_drv_t*)&cpu0_globals->gui.disp_drv);
	lv_disp_set_bg_opa(NULL, LV_OPA_TRANSP);
	startup_gui_create();
	lv_timer_create((lv_timer_cb_t)process_msg_q, 10, NULL);	// Check for GUI thread messages every 10ms
	while(1) {
		lv_task_handler();
		vTaskDelay(pdMS_TO_TICKS(4));
	}
}

void vga_irq_handler( void *p ) {

	vga->vga_fbuf_addr = cpu0_globals->gui.dma_src;
	cpu0_globals->gui.buf_switched = pdTRUE;
	XScuGic_Disable(&xInterruptController, XPAR_FABRIC_VGA_IP_0_FRM_CPT_IRQ_INTR);
	lv_disp_flush_ready((lv_disp_drv_t*)&cpu0_globals->gui.disp_drv);
}

static void update_dual_buf( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *colour_p ) {

	lv_disp_t*	disp = _lv_refr_get_disp_refreshing();
	lv_coord_t	y, hres = lv_disp_get_hor_res(disp);
    uint16_t	a;
    lv_color_t	*buf_cpy;

    if( colour_p == disp_drv->draw_buf->buf1)
        buf_cpy = disp_drv->draw_buf->buf2;
    else
        buf_cpy = disp_drv->draw_buf->buf1;

    for(a = 0; a < disp->inv_p; a++) {
    	if(disp->inv_area_joined[a]) continue;
        lv_coord_t w = lv_area_get_width(&disp->inv_areas[a]);
        for(y = disp->inv_areas[a].y1; y <= disp->inv_areas[a].y2 && y < disp_drv->ver_res; y++) {
            memcpy(buf_cpy+(y * hres + disp->inv_areas[a].x1), colour_p+(y * hres + disp->inv_areas[a].x1), w * sizeof(lv_color_t));
        }
    }
}

void vga_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *colour_p) {

	static uint8_t	first_call = 1;

	if( first_call ) {
		cpu0_globals->gui.dma_src = (uint32_t)colour_p;
		first_call =  0;
		vga->total_pixels &= ~DMA_FIFO_RST; 	// Release Reset
		vga->total_pixels |= DMA_FRAME_READY;	// Start Proceedings
		vga->irq_reg = VGA_IRQ_EN;				// Enable DMA complete interrupt
	}
	if( lv_disp_flush_is_last( disp_drv ) ) {
		cpu0_globals->gui.dma_src = (uint32_t)colour_p;
		cpu0_globals->gui.buf_switched = pdFALSE;
		XScuGic_Enable(&xInterruptController, XPAR_FABRIC_VGA_IP_0_FRM_CPT_IRQ_INTR);
		while(!cpu0_globals->gui.buf_switched);// vTaskDelay(1);
		update_dual_buf(disp_drv, area, colour_p);
	}

	lv_disp_flush_ready( disp_drv );
}

Also it may be worth checking your artefacts aren’t being caused by an unflushed cache.

Kind Regards,

Pete