OpenHarmony开源GPU库Mesa3D适配说明

本文档主要讲解在OpenHarmony中,Mesa3D的适配方法及原理说明。

环境说明:

  • OHOS版本: 适用3.2-Beta3及以上

  • 内核版本: linux-5.10

  • 硬件环境: Dayu200-rk3568

一、背景介绍

OpenHarmony对图形的渲染,支持CPU和GPU两种方式。为了支持流畅的用户体现,GPU适配是必不可少的。OpenHarmony使用GPU渲染,就必须依赖OpenGL接口。

OpenGL(Open Graphics Library) 开放图形库,是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(仅定义了接口及规范,没有实现)。OpenGL的高效性(利用了图形加速硬件)依赖于显示设备厂家的硬件及实现。

OpenGL API实现的方式又分为闭源及开源两种方式。闭源实现一般由设备厂家完成,这种方式充分保证了它的高效性,但移植起来比较麻烦。今天我们要重点介绍的是另外一种开源实现的方式:mesa3D。

Mesa3D 图形库就是OpenGL API的一种开源实现。新版本还支持OpenCL、OpenGL ES等等。Mesa3D对上提供标准的OpenGL接口,对下使用Gallium框架,屏蔽驱动差异。在RK3568中,panfrost对ARM GPU提供了非常好的开源驱动支持。

二、适配方法

在RK3568 GPU 开源库mesa3D适配时,我们同时依赖了drm panfrost的实现。目前OpenHarmony 3.2-Release基线中,支持4.19及5.10两个Linux版本,而只有5.10才提供了对panfrost的支持。如果当前Linux版本不支持panfrost,那就需要升级内核版本,或者把panfrost移植到当前版本上。

2.1 适配框架说明

以下是我们这次适配的框架示意图:

img

通过上图我们可以看出,一个大致的UI显示流程如下:

JS创建window->调用skia完成接口封装->调用mesa3D的OpenGL接口完成渲染->返回EglSurface数据->送到Dislay HDI的GFX合成->调用KMS完成数据转换->LCD硬件完成显示

2.2 适配前提条件

从适配框架图可以看出,GPU适配,需要建立在Dislay HDI、DRM、LCD驱动完整的基础之上,否则Launcher没有启动,也不能确定适配是否完好。所以,在GPU适配之前,需要确保在CPU渲染的基础上,Launcher是能正常启动的。

CPU渲染修改方法: 设置graphic_standard_feature_ace_enable_gpu = false。包含在以下路径中:

foundation/graphic/standard/graphic_config.gni
productdefine/common/inherit/rich.json
productdefine/common/products/ohos-arm64.json

编译过程中,旧版本可能会报如下错误:

img

解决方案如下:

vendor/hihope/rk3568/config.json
"ace_engine_feature_enable_web = false"

使用CPU模式能正常进入桌面,代表系统启动正常。

2.3 Mesa3D适配

  • 依赖库安装

    sudo apt-get install -y meson cmake llvm ninja-build pkg-config 
    python3 -m pip install meson==0.62.0
    python -m pip install --upgrade pip
    pip install mako atomic  markupsafe
    
    ./build.sh --product-name rk3568 --build-target expat
    
  • 合入patch

    https://gitee.com/openharmony/third_party_mesa3d/pulls/13 //mesa3D相关 必须合入
    https://gitee.com/zleoyu/device_soc_rockchip/commit/4467466a50adca43f26a77912cab710901f909e4 //合入产品配置 必须合入。

    单独测试mesa3d编译:

      python3 ohos/build_ohos.py OH目录 rk3568 OH目录/third_party/mesa3d
    
  • 修改成GPU模式

    foundation/graphic/standard/graphic_config.gni
    productdefine/common/inherit/rich.json
    productdefine/common/products/ohos-arm64.json

      graphic_standard_feature_ace_enable_gpu = true
    
  • GPU合成

    如果需要使用GPU合成,需要打开如下开关:

    foundation/graphic/standard/graphic_config.gni

      graphic_standard_feature_rs_enable_eglimage = true
    
  • patch错误修改:

    • mesa3d patch合入报错:

img

修改方案:

~~~shell
diff --git a/src/loader/loader.c b/src/loader/loader.c
index fd2ce99..3b443d6 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -77,7 +77,7 @@ static void default_logger(int level, const char *fmt, ...)
         va_list args;
         va_start(args, fmt);
         vfprintf(stderr, fmt, args);
-        sprintf_s(log_string, MAX_BUFFER_LEN, fmt, args);
+        sprintf(log_string, fmt, args);
         va_end(args);
     }
     DISPLAY_LOGI();
@@ -89,7 +89,7 @@ static void ohos_logger(int level, const char *fmt, ...)
     char log_string[MAX_BUFFER_LEN];
     va_list args;
     va_start(args, fmt);
-    (void)sprintf_s(log_string, MAX_BUFFER_LEN, fmt, args);
+    (void)sprintf(log_string, fmt, args);
     va_end(args);
     switch (level) {
         case _LOADER_WARNING:
~~~
  • 合入产品配置报错

img

解决方案:

~~~
diff --git a/rk3568/hardware/display/BUILD.gn b/rk3568/hardware/display/BUILD.gn
index 85daf66..773abdc 100644
--- a/rk3568/hardware/display/BUILD.gn
+++ b/rk3568/hardware/display/BUILD.gn
@@ -242,7 +242,7 @@ ohos_static_library("display_utils") {
   cflags = [ "-Wno-macro-redefined" ]
   deps = [
     "//third_party/libdrm:libdrm",
-    "//utils/native/base:utils",
+#    "//utils/native/base:utils",
   ]
   external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
 }
~~~

三、下载及验证

3.1 编译及下载img

RK3568 在ubuntu环境中,通过以下命令下载到设备:

//让内核重新编译
touch device/board/hihope/rk3568/kernel/build_kernel.sh
//编译OpenHarmony
./build.sh --product-name rk3568 --compile-config enable_mesa3d

//下载img
cd out/rk3568/packages/phone/images
upgrade_tool di -p parameter.txt -uboot uboot.img -boot_linux boot_linux.img -resource resource.img -vendor vendor.img -system system.img -userdata userdata.img -updater updater.img

//重启
upgrade_tool RD

3.2 panfrost正确日志打印

以下是panfrost启动成功后的串口日志打印:

    Line  480: [    0.780211] panfrost fde60000.gpu: clock rate = 594000000
    Line  481: [    0.780254] panfrost fde60000.gpu: bus_clock rate = 500000000
    Line  482: [    0.780476] panfrost fde60000.gpu: [drm:panfrost_devfreq_init] *ERROR* Couldn't set OPP regulators
    Line  824: [    2.008794] panfrost fde60000.gpu: clock rate = 594000000
    Line  825: [    2.008852] panfrost fde60000.gpu: bus_clock rate = 500000000
    Line  826: [    2.010067] panfrost fde60000.gpu: mali-g52 id 0x7402 major 0x1 minor 0x0 status 0x0
    Line  827: [    2.010100] panfrost fde60000.gpu: features: 00000000,13de77ff, issues: 00000000,00000400
    Line  828: [    2.010114] panfrost fde60000.gpu: Features: L2:0x07110206 Shader:0x00000002 Tiler:0x00000209 Mem:0x1 MMU:0x00002823 AS:0xff JS:0x7
    Line  829: [    2.010124] panfrost fde60000.gpu: shader_present=0x1 l2_present=0x1
    Line  830: [    2.012042] [drm] Initialized panfrost 1.1.0 20180908 for fde60000.gpu on minor 1

3.3 GPU渲染标志性打印

输入hilog并输出egl相关,能看到如下打印:

hilog -e egl

OHOS::ROSEN: RSSurfaceOhosGl:RequestFrame, eglsurface is 0x38f1ab0, width is 720, height is 48
OHOS::ROSEN: RSSurfaceOhosGl: FlushFrame, SwapBuffers eglsurface is 0x38f1ab0
OHOS::ROSEN: RSSurfaceOhosGl:RequestFrame, eglsurface is 0x39c1ba0, width is 720, height is 72
OHOS::ROSEN: RSSurfaceOhosGl: FlushFrame, SwapBuffers eglsurface is 0x39c1ba0
OHOS::ROSEN: RSSurfaceOhosGl:RequestFrame, eglsurface is 0x2df8350, width is 720, height is 1280

如果这个时候屏幕能够正常显示launcher想着内容,就恭喜你适配成功了。

四、知识分享

从上面的适配框架可以看出,除了Mesa3D外,drm、panfrost、Display HDI也是至关重要的,下面我们简单介绍相关知识及验证方法。

4.1 drm

drm(Direct Rendering Manager) 直接渲染管理,是Linux目前主流的图形显示框架。并且管理着GPU及Display驱动,使得软件架构更为统一,方便管理和维护。

DRM从模块上划分,可以简单分为3部分。

  • libdrm

    为用户态提供各种IOCTL操作接口。

  • KMS(Kernel Mode Setting)

    包换以下模块的实现:CRTC,ENCODER,CONNECTOR,PLANE,FB,VBLANK,property

  • GEM

    显示内存的分配管理。包含:DUMB、PRIME、fence

一个新设备drm的实现就是对KMS及GEM的实现,drm提供了一个虚拟设备例子参考:drivers/gpu/drm/vkms。以下链接非常详细的介绍了drm相关知识:

https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzIxMjE1MzU4OA==&action=getalbum&album_id=2434512719333982211&subscene=159&subscene=&scenenote=https%3A%2F%2Fmp.weixin.qq.com%2Fs%2Fs8lqVnTUZLa-YCP9oYGDow&nolastread=1#wechat_redirect

在用户态,libdrm提供了modetest工具,来检测drm基础功能,是否适配成功。它可以测试基本显示功能,并列举出几大组件的参数。但一些扩展的硬件功能,modetest无法检测,比如显存压缩技术AFBC。但适配前期,modetest还是非常好用的。

4.2 panfrost

panfrost的是对ARM 系列GPU驱动的开源实现,它的功能主要是完成对GPU硬件的初始化,以及以job的方式,完成对渲染数据硬件处理。在本文档中,GPU相关的配置,渲染管理等都是通过Mesa3D对panfrost ioctl来实现的。

4.3 Display HDI

Display HDI是OpenHarmony显示接口适配层。主要功能分三部分:

  • Display 显示管理及配置
  • Gralloc 显存管理
  • GFX Layer合成管理

HDI 通过libdrm提供的接口来管理显示设备及送显。OpenHarmony 使用的是atomic接口,需要drm支持atomic的property操作方式。HDI操作流程基本与modetest代码一致。在使用modetest确保drm驱动基本完整的情况下,可以使用hello_composer工具来测试HDI是否适配成功。

4.4 常用错误及处理方法

以下是适配过程中遇到的一些问题,为文档阅读者提供一些参考思路。

4.4.1 panfrost 初始化失败

panfrost初始化GPU硬件时,会遇到写复位寄器超时,有如下打印:

gpu soft reset timed out

这个时候发现读写GPU寄存器都表现异常,应该考虑GPU是否上电成功。

4.4.2 Launcher显示异常

桌面显示异常,状态和文字相关能正常显示,与图片相关的只显示一个框框,其它都是白色。并报如下错误:

[ 39.747285] panfrost 60000000.gpu: js fault, js=0, status=DATA_INVALID_FAULT, head=0x659c5c0, tail=0x659c5c0
[ 39.757132] panfrost 60000000.gpu: gpu sched timeout, js=0, config=0x3300, status=0x58, head=0x659c5c0, tail=0x659c5c0, sched_job=f77ff5d1

从错误来看,显示数据无效错误。经过定位,发现GPU是支持AFBC(显存压缩技术),但DRM没有适配。最后在Mesa3D中关闭该功能,显示正常。

--- a/src/panfrost/lib/pan_props.c
+++ b/src/panfrost/lib/pan_props.c
@@ -241,7 +241,7 @@ panfrost_open_device(void *memctx, int fd, struct panfrost_device *dev)
dev->quirks = panfrost_get_quirks(dev->gpu_id, revision);
dev->compressed_formats = panfrost_query_compressed_formats(fd);
dev->tiler_features = panfrost_query_tiler_features(fd);
- dev->has_afbc = panfrost_query_afbc(fd, dev->arch);
+ dev->has_afbc = false;//panfrost_query_afbc(fd, dev->arch);

4.4.3 ISA Config配置异常

案例参考: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7228

4.4.5 其它调试手段

如果OpenHarmony无法点亮屏幕,可以用buildroot来先测试,成功后再使用OpenHarmony验证。

buildroot小巧,修改编译调试都比较方便,并且自带glmark2测试工具。

步骤一: 关闭ramdisk

# CONFIG_BLK_DEV_INITRD=y
# CONFIG_INITRAMFS_SOURCE=""

步骤二:编译buildroot。

参考:https://blog.csdn.net/u013131156/article/details/124337444

步骤三:下载

使用rootfs.ext4 替换OHOS的system.img。

步骤四:调试

1、开机必要的环境变量配置:
mkdir /tmp/xdg
export XDG_RUNTIME_DIR=/tmp/xdg

2 打开日志(可选):
export PAN_MESA_DEBUG=trace
export MESA_DEBUG=1 
export EGL_LOG_LEVEL=debug 
export LIBGL_DEBUG=verbose 
export WAYLAND_DEBUG=1

3 启动桌面
weston --tty 1 & //GPU
或者
weston --tty=1 --use-pixman & //CPU

4 运行glmark2性能测试工具
glmark2-es2-wayland

4.4.5 闭源GPU so适配

闭源GPU so库适配最简单的是修改这个mali-bifrost-g52-g2p0-ohos动态库的实现。

ohos_prebuilt_shared_library("mali-bifrost-g52-g2p0-ohos") {
  if (target_cpu == "arm") {
    source = "lib/libmali-bifrost-g52-g2p0-ohos.so"//修改成厂家so库
  } else if (target_cpu == "arm64") {
    source = "lib64/libmali-bifrost-g52-g2p0-ohos.so"
  }

  # decoupling system.img and vendor.img
  install_images = [ chipset_base_dir ]
  relative_install_dir = "chipsetsdk"
  subsystem_name = "rockchip_products"
  part_name = "rockchip_products"
  install_enable = true
  symlink_target_name = [
    "libEGL_impl.so",
    "libGLESv1_impl.so",
    "libGLESv2_impl.so",
    "libGLESv3_impl.so",
    "libmali.so.0",
    "libmali.so.1",
  ]
}

如果要修改mali-bifrost-g52-g2p0-ohos这个动态库名字,那在另外一个gn中也要同步修改:

device/soc/rockchip/rk3568/hardware/BUILD.gn

group("hardware_group") {
  deps = [
    "//device/soc/rockchip/rk3568/hardware/gpu:mali-bifrost-g52-g2p0-ohos",//这个名字需要同步修改
    "//device/soc/rockchip/rk3568/hardware/isp:isp",
    "//device/soc/rockchip/rk3568/hardware/mpp:mpp",
    "//device/soc/rockchip/rk3568/hardware/wifi:ap6xxx",
  ]
}
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐