OpenHarmony开源GPU库Mesa3D适配说明

鸿蒙小青娃 2023-03-13 14:27:46

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

环境说明:

  • OHOS版本: OpenHarmony 3.1-Release

  • 内核版本: 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.1-Release基线中,支持4.19及5.10两个Linux版本,而只有5.10才提供了对panfrost的支持。如果当前Linux版本不支持panfrost,那就需要升级内核版本,或者把panfrost移植到当前版本上。

RK3568开源GPU Mesa3D适配的方法主要分为下以三步:

  • 下载并编译Mesa3D
  • 修改Linux内核适配panfrost
  • 适配Mesa3D so库

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渲染修改方法:

foundation/graphic/standard/graphic_config.gni

} else if ("${product_name}" == "rk3566" || "${product_name}" == "rk3568") {
  gpu_defines = [ "ACE_DISABLE_GL" ]
  ace_enable_gpu = false
  libgl = []
} else {

2.3 编译Mesa3D

2.3.1 安装依赖库:

sudo apt-get install -y meson cmake llvm pkg-config
python3 -m pip install --upgrade pip
python3 -m pip install meson==0.62.0
pip install mako markupsafe

./build.sh --product-name rk3568 --build-target expat

2.3.2 下载Mesa3D 源码

git clone https://gitee.com/openharmony/third_party_mesa3d.git
cd third_party_mesa3d/
git checkout 68565a

2.3.3 编译

python3 ohos/build_ohos.py ~/ohos/openHarmony/3.1-release rk3568 ~/ohos/openHarmony/3.1-release/third_party_mesa3d

2.3.4 拷贝so库到相应目录

cp build-ohos/src/egl/libEGL.so.1.0.0 ../device/hihope/hardware/gpu/
cp build-ohos/install/lib/libGLESv1_CM.so.1.1.0 ../device/hihope/hardware/gpu/
cp build-ohos/install/lib/libGLESv2.so.2.0.0 ../device/hihope/hardware/gpu/
cp build-ohos/install/lib/libgbm.so.1.0.0 ../device/hihope/hardware/gpu/
cp build-ohos/install/lib/libglapi.so.0.0.0 ../device/hihope/hardware/gpu/
cp build-ohos/src/gallium/targets/dri/libgallium_dri.so ../device/hihope/hardware/gpu/
cp build-ohos/install/lib/dri/panfrost_dri.so ../device/hihope/hardware/gpu/

2.4 修改内核

内核的修改部分,主要是为了适配panfrost 开源GPU驱动部分,最简单的是在原厂家GPU的dts配置基础上修改。

2.4.1 内核dts文件修改

out/kernel/src_tmp/linux-5.10/arch/arm64/boot/dts/rockchip/rk3568.dtsi

  • 增加panfrost驱动名称

    gpu: gpu@fde60000 {
    -                compatible = "arm,mali-bifrost";
    +                compatible = "arm,mali-bifrost", "arm,mali-bifrost";
    
  • 修改中断名称

    - interrupt-names = "GPU", "MMU", "JOB";
    + interrupt-names = "gpu", "mmu", "job";
    
  • 修改时钟名称

    - clock-names = "clk_mali", "clk_gpu"; 
    + clock-names = "core", "bus";
    

其它ARM GPU可以参考以下配置选择相应的型号:

drivers/gpu/drm/panfrost/panfrost_drv.c

static const struct of_device_id dt_match[] = {
    /* Set first to probe before the generic compatibles */
    { .compatible = "amlogic,meson-gxm-mali",
      .data = &amlogic_data, },
    { .compatible = "amlogic,meson-g12a-mali",
      .data = &amlogic_data, },
    { .compatible = "arm,mali-t604", .data = &default_data, },
    { .compatible = "arm,mali-t624", .data = &default_data, },
    { .compatible = "arm,mali-t628", .data = &default_data, },
    { .compatible = "arm,mali-t720", .data = &default_data, },
    { .compatible = "arm,mali-t760", .data = &default_data, },
    { .compatible = "arm,mali-t820", .data = &default_data, },
    { .compatible = "arm,mali-t830", .data = &default_data, },
    { .compatible = "arm,mali-t860", .data = &default_data, },
    { .compatible = "arm,mali-t880", .data = &default_data, },
    { .compatible = "arm,mali-bifrost", .data = &default_data, },
    {}
};

2.4.2 内核deconfig修改

out/kernel/src_tmp/linux-5.10/arch/arm64/configs/rockchip_linux_defconfig

#CONFIG_DRM_IGNORE_IOTCL_PERMIT=y 屏蔽忽略IOCTL权限(可选)
CONFIG_DRM_GEM_SHMEM_HELPER=y panfrost gem内存管理用到(必选)
CONFIG_DRM_SCHED=y GPU命令流调度接口,必须打开(必选)
CONFIG_DRM_PANFROST=y 打开panfrost功能(必选)

2.5 适配Mesa3D so库

由于Mesa3D就是OpenGL的开源实现,所以so库的适配就是替换厂家提供的闭源GPU库。

2.5.1 生成mesa-gpu-libs

device/hihope/hardware/gpu/BUILD.gn

# Copyright (C) 2021 HiHope Open Source Organization .
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import("//build/ohos.gni")
import("//build/ohos/ndk/ndk.gni")

ohos_prebuilt_shared_library("mesa_gbm") {
  source = "libgbm.so.1.0.0"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libgbm.so.1",
    "libgbm.so",
  ]
}
ohos_prebuilt_shared_library("mesa_egl") {
  source = "libEGL.so.1.0.0"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libEGL.so.1",
    "libEGL.so",
    "libGLESv1.so",
  ]
}
ohos_prebuilt_shared_library("mesa_glapi") {
  source = "libglapi.so.0.0.0"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libglapi.so.0",
    "libglapi.so",
  ]
}
ohos_prebuilt_shared_library("mesa_glesv1") {
  source = "libGLESv1_CM.so.1.1.0"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libGLESv1_CM.so.1",
    "libGLESv1_CM.so",
  ]
}
ohos_prebuilt_shared_library("mesa_glesv2") {
  source = "libGLESv2.so.2.0.0"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libGLESv2.so.2",
    "libGLESv2.so",
  ]
}
ohos_prebuilt_shared_library("libgallium_dri") {
  source = "libgallium_dri.so"
  install_images = [ chipset_base_dir ]
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "libgallium_dri.so",
    #"rockchip_dri.so",
  ]
}
ohos_prebuilt_shared_library("panfrost_dri") {
  source = "panfrost_dri.so"
  install_enable = true
  subsystem_name = "hdf"
  part_name = "display_device_driver"
  symlink_target_name = [
    "rockchip_dri.so",
  ]
}
group("mesa-gpu-libs") {
  public_deps = [
    ":mesa_gbm",
    ":mesa_egl",
    ":mesa_glapi",
    ":mesa_glesv1",
    ":mesa_glesv2",
    ":panfrost_dri",
   ]
 }

2.5.2 替换闭源GPU库

foundation/graphic/standard/graphic_config.gni

 } else if ("${product_name}" == "rk3566" || "${product_name}" == "rk3568") {
   gpu_defines = [ "ACE_ENABLE_GL" ]
   ace_enable_gpu = true
-  libgl = [ "//device/hihope/hardware/gpu:mali-bifrost-g52-g2p0-ohos" ]
+  #libgl = [ "//device/hihope/hardware/gpu:mali-bifrost-g52-g2p0-ohos" ]
+  libgl = [ "//device/hihope/hardware/gpu:mesa-gpu-libs" ]

2.5.3 关闭surfaceimage

由于surfaceimage依赖闭源GPU实现,需要关掉

foundation/graphic/standard/BUILD.gn

 group("libsurface") {
   public_deps = [ "frameworks/surface:surface" ]
   if (ace_enable_gpu) {
-    public_deps += [ "frameworks/surfaceimage:libsurfaceimage" ]
+    #public_deps += [ "frameworks/surfaceimage:libsurfaceimage" ]
   }
 }

2.5.4 添加GPU驱动框架

device/hihope/rk3568/BUILD.gn

     "build/rootfs:init_configs",
     "distributedhardware:distributedhardware",
-    "kernel:kernel"
+    "kernel:kernel",
+    "//device/hihope/hardware/gpu:libgallium_dri"
   ]
 }

2.5.5 其它修改

如果有创建card1及renderD129节点,需要给它添加读写权限。

base/startup/init_lite/ueventd/etc/ueventd.config

/dev/dri/card1 0666 0 1003
/dev/dri/renderD129 0666 0 1003

如果Display HDI gralloc模块使用的是renderD128节点,需要改成card0

device/hihope/hardware/display/src/display_gralloc/display_gralloc_gbm.c

-const char *g_drmFileNode = "/dev/dri/renderD128";
+const char *g_drmFileNode = "/dev/dri/card0";
 static GrallocManager *g_grallocManager = NULL;

三、下载及验证

3.1 编译及下载img

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

//编译kernel
cd out/kernel/src_tmp/linux-5.10/
./make-ohos.sh TB-RK3568X0 disable_ramdisk

//编译OpenHarmony
./build.sh --product-name rk3568

//下载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是否适配成功。OpenHarmony默认已经编译进系统。在/system/bin目录下。

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.4 其它调试手段

如果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
...全文
4962 1 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
不知道123555 2023-06-07
  • 打赏
  • 举报
回复

3.2 release版本这样适配失败了,提示panfrost_mmu_reset这边异常了,请问这是啥原因了?

571

社区成员

发帖
与我相关
我的任务
社区描述
OpenHarmony开发者社区
其他 企业社区
社区管理员
  • csdnsqst0025
  • shewaliujingli
  • BaoWei
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧