自学内容网 自学内容网

LVGL - RV1109 LVGL UI开发-01

RV1109 LVGL UI开发

前面在使用RK的RV1109平台用于产品中,使用的是QT做的UI,主要是继承原来海思平台的产品,随着分辨率的提高,UI响应也慢了不少!试着在RV1109上使用LVGL看看效果如何。
RV1109使用的是DRM的框架,在LVGL里已经有了DRM的一个实现,在720x 1280的分辨率下,跑起来效果体验很不好!在跑LVGL里的demo lv_demo_benchmark,平均只有可怜的4FPS,在海思平台上跑1920x1080的分辨率,没有任何TDE加速情况下,平均都跑到15FPS了,各种DEMO都很流畅,但在RV1109上表现的大跌眼睛。
只好使用RGA的加速来看看效果如何了!

RGA DRM 模块使用

从RK的RV1109的SDK中把RGA的DRM操作拷出来,主要是SDK里的以下文件:

  • display.c
  • display.h
  • draw_rect.c
  • draw_rect.h
  • rkdrm_display.c
  • rkdrm_display.h

这里面主要的实现,是借用RGA的RkRgaBlit过程来实现快速拷贝,在上面的代码实现里实现了一个 display_commit的过程,这里的实现方式基本也是一样操作。
在LVGL里是使用的32位的ARGB,所认在DRM这里初始化使用DRM_FORMAT_ARGB8888的格式。

display.h头文件定义,这里自己添加了一个commint(display_commit_ex)的实现,其他的方法都是原来即有的:

int display_init(int width, int height);
void display_exit(void);
void display_commit(void *ptr, int fd, int fmt, int w, int h, int rotation);
void display_commit_ex(void *ptr, int fd, int fmt, int x, int y, int w, int h, int rotation);
void display_draw(int x, int y, int w, int h, void* ptr);
void display_switch(enum display_video_type type);
void display_get_resolution(int *width, int *height);
void display_paint_box(int left, int top, int right, int bottom);
void display_set_color(YUV_Color color);

display.c中的一些改动:

int display_init(int width, int height)
{
int ret;
#ifdef USE_NV12
g_disp.fmt = DRM_FORMAT_NV12;
g_disp.rga_fmt = RK_FORMAT_YCbCr_420_SP;
#endif
#ifdef USE_RGB888
g_disp.fmt = DRM_FORMAT_BGR888;
g_disp.rga_fmt = RK_FORMAT_RGB_888;
#endif

#ifdef USE_RGBA8888
g_disp.fmt = DRM_FORMAT_ARGB8888;
g_disp.rga_fmt = RK_FORMAT_RGBA_8888;
#endif
g_disp.width = width;
g_disp.height = height;
g_disp.plane_type = DRM_PLANE_TYPE_OVERLAY;
g_disp.buf_cnt = BUF_COUNT;
g_disp.color = set_yuv_color(COLOR_R);
ret = drm_display_init(&g_disp);
if (ret)
return ret;

return 0;
}

drm_commit_ex提交UI的更产新,这里没有使用一个BUFF了,直接绘制RkRgaBlit更新!

void drm_commit_ex(struct display* disp, int num, void *ptr, 
int fd, int fmt, int x, int y, int w, int h, int rotation)
{
int ret;
rga_info_t src, dst;
char *map = disp->buf[num].map;
int dst_w = disp->width;
int dst_h = disp->height;
int dst_fmt = disp->rga_fmt;

memset(&src, 0, sizeof(rga_info_t));
src.fd = -1;
src.virAddr = ptr;
src.mmuFlag = 1;
src.rotation = rotation;
src.blend = 0xff0105;
rga_set_rect(&src.rect, 0, 0, w, h, w, h, fmt);
//printf("src rect x:%d y:%d sw:%d sh:%d\n", x, y, src.rect.width, src.rect.height);
memset(&dst, 0, sizeof(rga_info_t));
dst.fd = -1;
dst.virAddr = map;
dst.mmuFlag = 1;

rga_set_rect(&dst.rect, x, y, w, h, dst_w, dst_h, dst_fmt);
//printf("dst rect x:%d y:%d sw:%d sh:%d\n", x, y, dst.rect.width, dst.rect.height);
if (c_RkRgaBlit(&src, &dst, NULL)) {
printf("%s: rga fail\n", __func__);
printf("===========failure!============= w %d h %d\n", w, h);
return;
}else{
//printf("===========ok====123========= w %d h %d\n", w, h);
}

//pthread_mutex_lock(&g_lock);
//YUV_Rect rect = {g_disp.x, g_disp.y, g_disp.w, g_disp.h};
//YUV_Color color = g_disp.color;
//pthread_mutex_unlock(&g_lock);
//if (rect.x || rect.y || rect.width || rect.height)
//yuv420_draw_rectangle(map, dst_w, dst_h, rect, color);
ret = drmCommit(&disp->buf[num], disp->width, disp->height, 0, 0, &disp->dev, disp->plane_type);
if (ret) {
fprintf(stderr, "display commit error, ret = %d\n", ret);
}
}

LVGL对应的接口实现 lvgl_drm_display.h:

#ifndef APP_APPMAIN_VIEW_LVGL_LVGL_DRM_DISPLAY_H_
#define APP_APPMAIN_VIEW_LVGL_LVGL_DRM_DISPLAY_H_

#include "lvgl/lvgl.h"

#ifdef __cplusplus
extern "C" {
#endif

void lvgl_drm_init(int width, int height);
void lvgl_drm_exit(void);
void lvgl_drm_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p);


#ifdef __cplusplus
}
#endif

LVGL对应的接口实现 lvgl_drm_display.c:


void lvgl_drm_init(int width, int height)
{
int ret = -1;
ret = display_init(width, height);
if(ret != 0)
{
printf("display_init(%d %d) failure!\n", width, height);
return;
}

g_width = width;
g_height = height;
printf("display_init(%d %d) ok!\n", width, height);
}

void lvgl_drm_exit(void)
{
display_exit();
}


/**
 * Flush a buffer to the marked area
 * @param drv pointer to driver where this function belongs
 * @param area an area where to copy `color_p`
 * @param color_p an array of pixel to copy to the `area` part of the screen
 */
void lvgl_drm_flush(lv_disp_drv_t *drv, const lv_area_t *area,
lv_color_t *color_p)
{
static unsigned long long ts = 0;

lv_coord_t w = (area->x2 - area->x1 + 1);
lv_coord_t h = (area->y2 - area->y1 + 1);
if(w >= 2 && h >= 2) //这里在RGA的接口里宽,高为1时会报错,不会进行操作,这里先过滤一下
{
ts = _clockTime_getCurrentMscTime();
display_commit_ex(color_p, -1, RK_FORMAT_RGBA_8888, area->x1, area->y1, w, h, 0);
printf("display_commit_ex %llums\n", _clockTime_checkLostMscTime(ts));
}
lv_disp_flush_ready(drv);
}

最后效果

通过上面的RGA操作过程,跑lv_demo_benchmark的测试,FPS也还是平均的可怜的8FPS这样子,比其他平台还是差了不少,这个分辨率还是在720x1280的情况下,如果切换到1920x1080上是不是更差呢?在一些刷新不高的界面,虽然操作还可以了,但如在跑lv_demo_widgets的第二个TAB页时,界面一直在刷新,在用触摸时就会响应不过来,获接上鼠标操作时,单击就时常失效,用户体验很不好!如果只是简单的交互,界面里没有实时刷新的操作,也还是可以,但如果刷新率要求高的场景体验就不好了!

通过各种尝试,也没有能提高刷新的FPS!通过上面的时间打印,display_commit_ex一个操作在在20ms这样子,应该也是不高啊?是DRM的操作不对吗?后续问问原厂看看什么情况!


原文地址:https://blog.csdn.net/jhting/article/details/122890975

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!