LVGL - RV1109 LVGL UI开发-01

本文介绍了在RV1109平台上使用LVGL进行UI开发遇到的性能问题。作者通过对比QT和LVGL在不同分辨率下的运行效果,发现LVGL在DRM框架下的性能不佳,平均FPS仅为4。为提升性能,作者尝试引入RGA加速,并详细展示了修改DRM和LVGL接口的实现过程。然而,即使使用RGA,FPS仍只有8,且在高刷新率场景下表现欠佳。作者计划进一步咨询原厂寻求解决方案。
摘要由CSDN通过智能技术生成

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的操作不对吗?后续问问原厂看看什么情况!

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值