天天看點

lvgl硬體加速一、關于硬體加速二、關于雙framebuffer

基于lvgl v7.11.0

一、關于硬體加速

LVGL提供了一些GPU的硬體加速接口 lv_hal_disp.h

可以在lv_conf.h 中将宏打開。

相關接口如下:

/** MANDATORY: Write the internal buffer (VDB) to the display. 'lv_disp_flush_ready()' has to be
     * called when finished */
    void (*flush_cb)(struct _disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

    /** OPTIONAL: Extend the invalidated areas to match with the display drivers requirements
     * E.g. round `y` to, 8, 16 ..) on a monochrome display*/
    void (*rounder_cb)(struct _disp_drv_t * disp_drv, lv_area_t * area);

    /** OPTIONAL: Set a pixel in a buffer according to the special requirements of the display
     * Can be used for color format not supported in LittelvGL. E.g. 2 bit -> 4 gray scales
     * @note Much slower then drawing with supported color formats. */
    void (*set_px_cb)(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
                      lv_color_t color, lv_opa_t opa);

    /** OPTIONAL: Called after every refresh cycle to tell the rendering and flushing time + the
     * number of flushed pixels */
    void (*monitor_cb)(struct _disp_drv_t * disp_drv, uint32_t time, uint32_t px);

    /** OPTIONAL: Called periodically while lvgl waits for operation to be completed.
     * For example flushing or GPU
     * User can execute very simple tasks here or yield the task */
    void (*wait_cb)(struct _disp_drv_t * disp_drv);

    /** OPTIONAL: Called when lvgl needs any CPU cache that affects rendering to be cleaned */
    void (*clean_dcache_cb)(struct _disp_drv_t * disp_drv);

    /** OPTIONAL: called to wait while the gpu is working */
    void (*gpu_wait_cb)(struct _disp_drv_t * disp_drv);

#if LV_USE_GPU

    /** OPTIONAL: Blend two memories using opacity (GPU only)*/
    void (*gpu_blend_cb)(struct _disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length,
                         lv_opa_t opa);

    /** OPTIONAL: Fill a memory with a color (GPU only)*/
    void (*gpu_fill_cb)(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
           

flush_cb 雙framebuffer切換

gpu_fill_cb 區域色彩填充

gpu_blend_cb 區域 alpha 操作

是以就是說你要實作cpu自帶的硬體加速比如海思的tde等需要自己實作上述的接口。可以參考在lv_port_disp.c 中實作。

二、關于雙framebuffer

fb一般都有雙buffer的機制,用于前台顯示背景繪制,當背景繪制完成後lcd控制器切換到背景buffer顯示,這樣繪制過程就不會讓界面顯示出現撕裂及閃爍的情況。

lvgl提供了雙buffer的模式。lv_port_disp.c

void lv_port_disp_init(void)
		/* 3. Create TWO screen-sized buffer:
     *      Similar to 2) but the buffer have to be screen sized. When LVGL 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.
     * */
    /* Example for 3) */
    static lv_disp_buf_t draw_buf_dsc_3;
    static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*A screen sized buffer*/
    static lv_color_t draw_buf_3_2[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*An other screen sized buffer*/
    lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX);   /*Initialize the display buffer*/
    disp_drv.buffer = &draw_buf_dsc_3;
    disp_drv.flush_cb = disp_flush; //注冊硬體加速函數
    #if LV_USE_GPU
    /*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*/
    lv_disp_drv_register(&disp_drv);
           

注意注釋部分

lvgl在拿到這兩個buffer的時候會在背景的buffer上直接繪制,等待繪制成功後再切換buffer,切換動作在flush_cb 上完成,然後再同步前背景更新的内容,儲存兩個buffer間的圖像同步。lvgl的繪制流程是上述這樣,v8.0換了一種繪制模式,就是小區域的ui更新将引發整個screen的更新也就是每次都繪制整個界面的obj,是以這時候就不用做雙buffer間的圖像同步了。

這兩種重新整理方式我覺得還是第一中比較友善。因為做圖像同步的過程可以加入硬體加速。這樣整體流程會快很多。相較于第二種更新方式,每次都是刷整個screen耗時較多且沒有地方能加入加速。

關于v8.0注意在移植的時候如果你開了雙buffer的模式記得使能disp_drv.full_refresh = 1.

繼續閱讀