lvgl / lv_drivers

TFT and touch pad drivers for LVGL embedded GUI library
https://docs.lvgl.io/master/porting/index.html
MIT License
291 stars 310 forks source link

lvgl drm drivers: The test numbers seem a little low? #263

Closed zack-huangzihan closed 1 year ago

zack-huangzihan commented 1 year ago

The version I use is lv_drivers-8.3.0 I used an arm linux device and used benchmark to test the frame rate, and the results I got were not very good:

lv_example/benchmark is 6 FPS with DRM

Here's how I call it in my application:

void drm_disp_drv_init(lv_disp_drv_t * disp_drv)
{
    int ret;
    uint32_t dpi = 0;
    lv_disp_drv_init(disp_drv);
    drm_get_sizes(&disp_drv->hor_res, &disp_drv->ver_res, &dpi);
    disp_drv->flush_cb = drm_flush;
    lv_disp_draw_buf_t *disp_buf = lv_mem_alloc(sizeof(lv_disp_draw_buf_t));
    ret = drm_allocate_dumb(&drm_dev.draw_buf1);
    if (ret) {
        printf("drm_disp_drv_init: drm_allocate_dumb buf1\n");
        return ret;
    }
    ret = drm_allocate_dumb(&drm_dev.draw_buf2);
    if (ret) {
        printf("drm_disp_drv_init: drm_allocate_dumb buf2\n");
        return ret;
    }
    lv_disp_draw_buf_init(disp_buf, drm_dev.draw_buf1.map, drm_dev.draw_buf2.map,
                  drm_dev.width * drm_dev.height);
    // lv_disp_draw_buf_init(disp_buf, drm_dev.draw_buf1.map, NULL,
    //            drm_dev.width * drm_dev.height);
    disp_drv->draw_buf = disp_buf;
    disp_drv->wait_cb = drm_wait_vsync;
}

But the cpu power of my device has never been this low, I looked up some information: https://forum.lvgl.io/t/drm-driver-is-slow/3479

According to the following patch:

diff --git a/display/drm.c b/display/drm.c
index bda938e..0c7311d 100644
--- a/display/drm.c
+++ b/display/drm.c
@@ -713,31 +713,22 @@ void drm_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color

    dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h);

-   /* Partial update */
-   if (w != drm_dev.width || h != drm_dev.height && drm_dev.cur_bufs[0])
-       memcpy(fbuf->map, drm_dev.cur_bufs[0]->map, fbuf->size);
-
    for (y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
                 memcpy(fbuf->map + (area->x1 * (LV_COLOR_SIZE/8)) + (fbuf->pitch * i),
                        (void *)color_p + (w * (LV_COLOR_SIZE/8) * y),
               w * (LV_COLOR_SIZE/8));
    }

-   if (drm_dev.req)
+   if (!drm_dev.cur_bufs[0]) {
+       /* show fbuf plane */
+       if (drm_dmabuf_set_plane(fbuf)) {
+           err("Flush fail");
+           return;
+       }
+       else
+           dbg("Flush done");
        drm_wait_vsync(disp_drv);
-
-   /* show fbuf plane */
-   if (drm_dmabuf_set_plane(fbuf)) {
-       err("Flush fail");
-       return;
    }
-   else
-       dbg("Flush done");
-
-   if (!drm_dev.cur_bufs[0])
-       drm_dev.cur_bufs[1] = &drm_dev.drm_bufs[1];
-   else
-       drm_dev.cur_bufs[1] = drm_dev.cur_bufs[0];

    drm_dev.cur_bufs[0] = fbuf;

I found that the test values are normal, but is this standard practice? @superna9999 I did exactly what I did, but the result is the same, What do I need to do?

superna9999 commented 1 year ago

While looking at the wayland driver, it seems we should take lv_disp_flush_is_last in account.

Something like this should be better (haven't tried nor compiled it):

void drm_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
    struct drm_buffer *fbuf = drm_dev.cur_bufs[1];
    uint32_t w = (area->x2 - area->x1 + 1);
    uint32_t h = (area->y2 - area->y1 + 1);
    int i, y;

    dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h);

    for (y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
                memcpy((uint8_t *)fbuf->map + (area->x1 * (LV_COLOR_SIZE/8)) + (fbuf->pitch * i),
                       (uint8_t *)color_p + (w * (LV_COLOR_SIZE/8) * y),
               w * (LV_COLOR_SIZE/8));
    }

    if (lv_disp_flush_is_last(disp_drv)) {
        if (drm_dev.req)
            drm_wait_vsync(disp_drv);

        /* show fbuf plane */
        if (drm_dmabuf_set_plane(fbuf)) {
            err("Flush fail");
            return;
        }
        else
            dbg("Flush done");

        if (!drm_dev.cur_bufs[0])
            drm_dev.cur_bufs[1] = &drm_dev.drm_bufs[1];
        else
            drm_dev.cur_bufs[1] = drm_dev.cur_bufs[0];

        drm_dev.cur_bufs[0] = fbuf;

        /* Sync displaying buffers */
        memcpy(drm_dev.cur_bufs[1]->map, drm_dev.cur_bufs[0]->map, fbuf->size);
    }

    lv_disp_flush_ready(disp_drv);
}

Could you try this ?

zack-huangzihan commented 1 year ago

Unfortunately, it's not showing any improvement, right I'm not using a wayland device

It's worth noting that I use the above patch: https://forum.lvgl.io/t/drm-driver-is-slow/3479 An fps can reach 150

Whether the drm driver needs to be optimized?

Unfortunately, it's not showing any improvement, right I'm not using a wayland device

It's worth noting that I use the above patch: https://forum.lvgl.io/t/drm-driver-is-slow/3479 An fps can reach 150

Whether the drm driver needs to be optimized?

superna9999 commented 1 year ago

@zack-huangzihan which patch are you referring to ?

zack-huangzihan commented 1 year ago

@zack-huangzihan which patch are you referring to ?

diff --git a/display/drm.c b/display/drm.c
index bda938e..0c7311d 100644
--- a/display/drm.c
+++ b/display/drm.c
@@ -713,31 +713,22 @@ void drm_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color

    dbg("x %d:%d y %d:%d w %d h %d", area->x1, area->x2, area->y1, area->y2, w, h);

-   /* Partial update */
-   if (w != drm_dev.width || h != drm_dev.height && drm_dev.cur_bufs[0])
-       memcpy(fbuf->map, drm_dev.cur_bufs[0]->map, fbuf->size);
-
    for (y = 0, i = area->y1 ; i <= area->y2 ; ++i, ++y) {
                 memcpy(fbuf->map + (area->x1 * (LV_COLOR_SIZE/8)) + (fbuf->pitch * i),
                        (void *)color_p + (w * (LV_COLOR_SIZE/8) * y),
               w * (LV_COLOR_SIZE/8));
    }

-   if (drm_dev.req)
+   if (!drm_dev.cur_bufs[0]) {
+       /* show fbuf plane */
+       if (drm_dmabuf_set_plane(fbuf)) {
+           err("Flush fail");
+           return;
+       }
+       else
+           dbg("Flush done");
        drm_wait_vsync(disp_drv);
-
-   /* show fbuf plane */
-   if (drm_dmabuf_set_plane(fbuf)) {
-       err("Flush fail");
-       return;
    }
-   else
-       dbg("Flush done");
-
-   if (!drm_dev.cur_bufs[0])
-       drm_dev.cur_bufs[1] = &drm_dev.drm_bufs[1];
-   else
-       drm_dev.cur_bufs[1] = drm_dev.cur_bufs[0];

    drm_dev.cur_bufs[0] = fbuf;
symfund commented 1 year ago

Should LVGL Wayland DRM driver use DMA-BUF, by "zero copy" and Wayland frame callbacks mechanisms higher FPS could be achieved.