OpenHarmony硬件合成方案解析

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

环境说明:

  • OHOS版本:3.1-Release及以上

一、背景介绍

1.1 什么是合成

要理解什么是合成,合成做了什么?我们先通过分解设置界面来回答这个问题:

在设置界面中,一帧完整的图像是由4个部分构成的,每一个部分我们称之为一个layer。

layer的概念

layer(图层)是图形合成中最重要的单元,一个layer对应一个buffer及显示参数。一帧图像由一个或多个layer组成,每个layer单独负责一块区域的内容刷新,大大提升了渲染及显示效率。比如:我们把鼠标的显示单独设置成一个Layer,鼠标的移动,只需要更改layer的显示坐标,不需要重复渲染背景显示区域的数据等。

在设置界面中,4个layer分别是背景层、应用层、状态栏和工具栏。合成就是把这些layer组合在一起,最终变成一帧完整的图像。

我们可以通过如下命令获取当前界面的layers信息:

hidumper -s 10 -a surface

对当前界面截屏

snapshot_display -f /data/snapshot_display.jpeg

我们可以看到,layer2和layer3背景显示为黑色,与实际效果有较大区别。要理解这个差异的原因,我们需要要知道合成做了什么。

1.2 合成做了什么

从前面的介绍我们知道,合成就是把多个layer合成了一帧图像。那这个合成的过程中,主要处理了哪些事?总结如下:

  • 颜色混合。包含透明度处理、背景填充、阴影处理等。

  • 编码格式转换。支持RGB565、RGB888、ARGB888、YUV420_2P等

  • 缩放处理。支持1/16~24倍率缩放

  • 输入/输出旋转。

不同的硬件支持的能力有差别,最基本的能力需要支持透明度处理及编码转换。

上面layer背景显示黑色的原因,是因为背景的RGBA值都是0,RGB 值为0,显示黑色。Alpha值为0,为全透明。如果给他们添加一个背景图层,那图层就会显示成背景的颜色值。

理解了合成,我们再看看合成模块在OpenHarmony系统进程中的位置。

1.3 合成在OpenHarmony中位置

图像合成在OpenHarmony进程示意图,以便了解合成模块的生命周期及运行逻辑:

如上图所示,合成模块代码由虚框标记,运行在render_service进程中。硬件适配主要是适配display_device及display_gfx模块。

  • display_device: 为composer提供接口及适配

  • display_gfx:包含具体硬件sensor的功能实现。

    重启render_service服务,Dispaly HDI服务就会重启。

1.4 合成的方式

OpenHarmony中合成方式有以下几种:

  • CPU合成。由skia或pixmax提供。
  • GPU合成。由GPU硬件提供。
  • 纯硬件sensor合成。如展锐的gsp,瑞芯微的rga等
  • drm合成。由drm通用接口封装,一般集成合成和送显功能。如展锐的dpu。

以上合成方式在相同layers数量下,xx平台性能对比如下:

类型CPUGPUGFXDRM
合成时间(ms)>80ms12.07ms11.38ms7.5ms

从合成性能看,drm性能最佳,减少了内存复制开销。GFX与GPU性能相差不多,但能完成一些drm无法完成的合成场景。CPU最差,只有适配早期,其它硬件没有调试好时,临时使用。

二、适配的方法

适配硬件合成前,我们先要理清代码的运行逻辑,并且知道适配需要做什么,去哪里修改。以下通过流程图来展示代码的运行逻辑和位置。

当Layers准备好后,进入composer模块的repaint()处理。流程如下:

  • prepare阶段。
    • gfx_prepare:为每个layer选择具体的合成方式
    • drm_prepare:把dpu类型添加到List
    • 处理GPU合成
  • commit阶段。
    • gfx_commit:处理gfx硬件合成
    • drm_commit:处理drm合成及送显

2.1 合成方式的选择

Layer合成方式选择示例:

当前合成方式并没有使用GPU合成,是否使用,可根据其它硬件能力来选择。一般情况下,为了减轻GPU负担,尽量使用其它硬件来完成合成操作。

每个硬件支持能力不同,比如:支持的layer数量,是否支持缩放时旋转,缩放倍率等。

合成方式的选择要结合具体的硬件来调整。硬件详细能力请查阅相关芯片手册。

注意事项:

  • 如果GSP列表非空,那clientLayer作为GSP的合成结果,会占用DPU的plane0.

  • 由于Layer图层是有顺序的,所以连续的图层会选择同一种硬件合成。

比如:DPU只支持4个图层,如果总图层有6个,那前面3个将使用GSP合成结果到clientLayer,再与后面的3个图层一起,共4个layer给DPU合成送显。

代码示例:

int32_t HdiGfxComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
{……HdiLayer *layer;uint32_t dpuSize = 0;for (uint32_t i = 0; i < layers.size(); i++) {layer = layers[i];if (CanHandle(*layer)) {if ((layer->GetCompositionType() != COMPOSITION_VIDEO) &&(layer->GetCompositionType() != COMPOSITION_CURSOR)) {if((mask == 0) && (layers.size() < 4)) {//直接给DPU处理layer->SetAcceleratorType(ACCELERATOR_DPU);……} else {//GSP+DPUint32_t tempMask = CheckLayers(layers, i);// 判断剩下的layers DPU是否支持uint32_t tempSize = layers.size() - i;if(tempMask) {//复杂场景交给GSPlayer->SetAcceleratorType(ACCELERATOR_GSP);……}  else {if((dpuSize + tempSize) < 5) {//dpu支持6个layer,先只使用4个layer->SetAcceleratorType(ACCELERATOR_DPU);……} else {layer->SetAcceleratorType(ACCELERATOR_GSP);……}}}} else {layer->SetDeviceSelect(layer->GetCompositionType());}mCompLayers.push_back(layer);} else { //GPUlayer->SetDeviceSelect(COMPOSITION_CLIENT);……}}……
}

2.2 GFX适配之GSP

2.3 DRM适配之DPU

2.4 GPU适配

三、调测及优化

3.1 测试程序-hello_composer

hello_composer在3.2-Release中默认没有参与编译,修改如下:

foundation/graphic/graphic_2d/bundle.json

--- a/bundle.json
+++ b/bundle.json
@@ -61,6 +61,7 @@"//foundation/graphic/graphic_2d/rosen/modules/2d_graphics:2d_graphics","//foundation/graphic/graphic_2d/rosen/samples/2d_graphics:drawing_sample_rs",
+            "//foundation/graphic/graphic_2d/rosen/samples/composer:hello_composer","//foundation/graphic/graphic_2d/rosen/samples/2d_graphics:drawing_engine_sample",

在第一次运行hello_composer前,需要先把render_service服务停止。

service_control stop render_service

执行hello_composer

cd /system/bin
./hello_composer

测试分以下几个点进行:

  • 图层数量测试
    foundation/graphic/graphic_2d/rosen/samples/composer/hello_composer.cpp
void HelloComposer::InitLayers(uint32_t screenId)
{
……
// status bardrawLayers.emplace_back(std::make_unique<LayerContext>(IRect { 0, 0, displayWidth, statusHeight },IRect { 0, 0, displayWidth, statusHeight },3, LayerType::LAYER_STATUS));
……
}
默认是4个图层,可以根据实际测试情况,添加、删除layers的信息。
  • 图层旋转
    foundation/graphic/graphic_2d/rosen/samples/composer/layer_context.h
drawLayers.emplace_back(std::make_unique<LayerContext>(IRect { layerPositionX, layerPositionY, 200, 400},IRect { 0, 0, 100, 200},1, LayerType::LAYER_EXTRA));
修改为true后,LayerType::LAYER_EXTRA 图层会周期旋转。
  • 图层缩放
    foundation/graphic/graphic_2d/rosen/samples/composer/hello_composer.cpp
bool testYUV_ = true;

通过修改目的图层的大小,来达到缩放测试的目的

  • yuv测试
    foundation/graphic/graphic_2d/rosen/samples/composer/layer_context.h
bool testYUV_ = true;
修改为true后,LayerType::LAYER_EXTRA图层会以yuv格式合成。
  • 透明度测试
    foundation/graphic/graphic_2d/rosen/samples/composer/layer_context.h
const std::vector<uint32_t> colors_ = {0xff0000ff, 0xffff00ff, 0xaa00ff00, 0xff00ffaa, 0xff0f0f00};
修改colors_最高8位值,可以测试透明度。0x00:全透明 0xFF:不透明

3.2 TRACE抓取分析

合成消耗了多少时间,帧率的统计都可以使用抓trace来分析。

trace命令:

hdc shell bytrace -t 5 --overwrite app graphic > mytrace.ftrace

帧率统计:

帧率首先由vsync频率决定,当合成总时间大于vsync间隔时,会影响帧率,并需要进行优化。合成计算帧率就是统计1s内合成帧的个数。

合成时间统计:

以上标记的时间就是实际硬件合成的时间,在commit方法中执行。我们从前面两个图片可看出,他们的合成间隔是有明显区别的,赵成这个现象的原因是同步及异步设置导致。

3.3 fence机制

当我们的操作需要使用其它硬件资源执行时,就涉及到同步的方式问题。总结如下:

  • 同步执行

    调用硬件接口后,需要等待硬件所有指令执行完成。libdrm接口中示例如下:

uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK;//去掉DRM_MODE_ATOMIC_NONBLOCK代表同步执行
ret = drmModeAtomicCommit(drmFd, atomicReqPtr.Get(), flags, nullptr);
  • 异步执行

    异步在图形中常用的就是fence机制。fence机制框架由内核提供,当硬件完成时,会修改fence的状态。常用的如AcqureFenceFd、ReleaseFenceFd。

    AcqureFenceFd 由GPU提供,标记渲染结果。

    ReleaseFenceFd 由drm crtc提供,标记送显结果。

    例如 ReleaseFenceFd:

ret = drmModeAtomicAddProperty(atomicReqPtr.Get(), mCrtc->GetId(), mCrtc->GetOutFencePropId(),(uint64_t)&crtcOutFence);
……
layer->SetReleaseFence(dup(crtcOutFence));
fence机制,让CPU在硬件工作时,释放生产力,继续执行与当前操作无关代码,把流程继续向前推进。当再次需要执行与当前硬件相关的操作时,再检查fence完成状态或等待。在整个周期中,大大增加了代码执行效率。

四、常见问题分析

4.1 状态栏背景为黑色

实际显示效果状态栏和工具栏为黑色。这个一般是透明度没有处理好。修改drm blend_mode可以解决。

drmModeAtomicAddProperty(pset,  drmPlane.GetId(), drmPlane.property_blend_mode, 0);//0-2.具体类型可以使用modetest查看

4.2 滑动列表时有闪烁的现象

如果硬件没有报错,那大概率是ReleaseFence没有同步。buffer还没有使用完成,又对buffer进行了操作。

layer->SetReleaseFence(dup(crtcOutFence));//step1: 检查ReleaseFence是否设置
currSbuffer_->releaseFence_ = Merge(currSbuffer_->releaseFence_, layerReleaseFence);//step2: 检查ReleaseFece是否有合并

4.3 滑动列表时有抖动的现象

这种一般只有在低端GPU上才会出现。原因是AcqureFence没有同步,使用了未准备好的渲染结果。增加对fence的等待:

if(layer->GetAcquireFenceFd() > 0) {sync_wait(layer->GetAcquireFenceFd(), 100);
}

4.4 Layer区域显示黑色或者丢失

主要有以下几种可能。

  • zorder顺序不对,被其它图层覆盖。

  • layer内容为空。显示成了背景填充色0

  • 超出硬件支持的图层上限,需要增加循环合成处理

五、知识分享

在模块开发过程中,如果我们对layer的数据不确定时,可以把layer的数据dumper出来。

setenforce 0
param set rosen.afbc.enabled 0//start
touch /data/bq_dump
//end
rm /data/bq_dump

数据生成在/data目录下。文件可以使用yuvplayer.exe工具查看,它支持yuv、rgb等不同的格式类型及分辨率大小。

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://gitee.com/MNxiaona/733GH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/314438.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

删除二叉搜索树中的节点

题目链接 删除二叉搜索树中的节点 题目描述 注意点 节点值唯一root 是合法的二叉搜索树节点数的范围 [0, 10000] 解答思路 可以根据二叉搜索树的性质找到要删除的节点&#xff0c;关键是删除节点后怎么重新构建成一棵新的二叉搜索树首先要找到的是删除节点node的父节点nod…

数智时代的AI人才粮仓模型解读白皮书(2024版)

来源&#xff1a;极客邦科技 自 2023 年上半年起&#xff0c;ChatGPT 等大模型技术蓬勃发展&#xff0c;AI 技术不断突破边界&#xff0c;展现 出惊人的潜力和发展速度。从早期的逻辑推理、专家系统&#xff0c;到如今的深度学习、神经网络&#xff0c; AI 技术显著缩小了科学…

【webrtc】Chrome和Firefox在SDP协商过程中,针对localhost的不同处理

内网下chrome端webrtc协商失败 现象 我有一个webrtc服务器在局域网内&#xff0c;使用chrome浏览器访问时&#xff0c;发现webrtc在做媒体协商时失败。 具体表现是&#xff0c;在交换sdp后&#xff0c;ice的状态是oniceconnectionstatechange: failed 但是换成Firefox浏览器…

编写Spark独立应用程序

执行本文之前&#xff0c;先搭建好spark的开发环境&#xff0c;我目前只搭建了standalone模式&#xff0c;参考链接 &#xff1a; Spark Standalone模式部署-CSDN博客 1. 安装sbt 1&#xff09;下载sbt 网址&#xff1a;https://www.scala-sbt.org/download.html &#xff0c…

设计模式——终止模式之两阶段终止模式

文章目录 1. 错误思路2. 两阶段终止模式2.1 利用 isInterrupted2.2 利用停止标记interrupt-打断park Two Phase Termination 在一个线程 T1 中如何“优雅”终止线程 T2&#xff1f;这里的【优雅】指的是给 T2 一个料理后事的机会。 1. 错误思路 使用线程对象的 stop() 方法停…

论文解读-面向高效生成大语言模型服务:从算法到系统综述

一、简要介绍 在快速发展的人工智能&#xff08;AI&#xff09;领域中&#xff0c;生成式大型语言模型&#xff08;llm&#xff09;站在了最前沿&#xff0c;彻底改变了论文与数据交互的方式。然而&#xff0c;部署这些模型的计算强度和内存消耗在服务效率方面带来了重大挑战&a…

Xinlinx FPGA内的存储器BRAM全解

目录 一、总体概述1.7系列FPGA的BRAM特点2.资源情况 二、BRAM分类1.单端口RAM2.简单双端口RAM3.真双端口RAM 三、BRAM的读写1、Primitives Output Registers读操作注意事项2.三种写数据模式&#xff08;1&#xff09;Write_First&#xff08;2&#xff09;Read_First&#xff0…

【iconv】Linux c++ 中文字符串转十六进制 GBK 编码/内码

文章目录 问题描述c 代码CMakeLists.txt参考链接 问题描述 Linux 系统默认使用的是 UTF-8 编码&#xff0c;并且 c 中没有标准库可以直接将中文字符转为 GBK 编码/内码。因此需要借助 iconv 库来实现。 在实现代码之前&#xff0c;可以在一下在线工具网站进行中文字符到各个编…

mac上安装Tomcat

1. 简介 Tomcat 是一个开源的 Java 服务器&#xff0c;它实现了 Java Servlet、JavaServer Pages&#xff08;JSP&#xff09;和Java WebSocket 技术。Tomcat 是 Apache 软件基金会的一个项目&#xff0c;是一个轻量级、高性能的 Web 容器。作为一个 Web 服务器&#xff0c;To…

前端工程化Vue使用Node.js设置国内高速npm镜像源(踩坑记录版)

前端工程化Vue使用Node.js设置国内高速npm镜像源&#xff08;踩坑记录版&#xff09; 此篇仅为踩坑记录&#xff0c;并未成功更换高速镜像源&#xff0c;实际解决方法见文末跳转链接。 1.自身源镜像 自身镜像源创建Vue项目下载速度感人 2.更改镜像源 2.1 通过命令行配置 前提…

常见的排序算法

前言 算法对于我们普通的工程师来说可算得上陌生又熟悉&#xff0c;因为在平时的业务代码中可能见到他的身影比较少&#xff0c;但在底层的代码中我们可能会经常发现排序算法的影子&#xff0c;如数据库索引&#xff0c;操作系统的进程调度。因此&#xff0c;掌握这种算法中的…

打造智能语音机器人-用语音控制机器人

人工智能现已成为国家发展重大战略&#xff0c;智能语音技术作为人工智能产业链上的关键一环&#xff0c;AI应用成熟的技术之一&#xff0c;人工智能的发展也进入了一个崭新的阶段。那么打造智能语音机器人怎样实现用语音控制机器人呢&#xff1f;和小编一起来看看。 选择合适的…

Xcode for Mac:强大易用的集成开发环境

Xcode for Mac是一款专为苹果开发者打造的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它集成了代码编辑器、编译器、调试器等一系列开发工具&#xff0c;让开发者能够在同一界面内完成应用的开发、测试和调试工作。 Xcode for Mac v15.2正式版下载 Xcode支持多种编程…

如何将web content项目导入idea并部署到tomcat

将Web Content项目导入IntelliJ IDEA并部署到Tomcat主要涉及以下几个步骤&#xff1a; 1. 导入Web Content项目 打开IntelliJ IDEA。选择“File” -> “New” -> “Project from Existing Sources…”。浏览到你的Web Content项目的文件夹&#xff0c;并选择它。Intell…

1.C++入门(上)

目录 1.C关键字 2.命名空间 作用域方面的优化 a.命名空间定义 b.命名空间使用 3.C 输入&输出 1.C关键字 C有63个关键字&#xff0c;C语言有32个关键字&#xff0c;存在重叠如荧光笔标出 2.命名空间 作用域方面的优化 如果变量&#xff0c;函数和类的名称都存在于全…

Hive服务详解

Hive服务 HiveServer2、Hive Metastore 服务服务共同构成了 Hive 生态系统中的核心功能&#xff0c;分别负责管理元数据和提供数据查询服务&#xff0c;为用户提供了一个方便、高效的方式来访问和操作存储在 Hive 中的数据。 1. Hive 查询服务&#xff08;HiveServer2&#xf…

STM32自己从零开始实操01:原理图

在听完老师关于 STM32 物联网项目的所有硬件课程之后&#xff0c;就是感觉自己云里雾里&#xff0c;明明课程都认真听完了&#xff0c;笔记也认真记录&#xff0c;但是就是感觉学到的知识还不是自己。 遂决定站在老师的肩膀上自己开始设计项目&#xff0c;将知识变成自己的&am…

沉浸式推理乐趣:体验线上剧本杀小程序的魅力

在这个信息爆炸的时代&#xff0c;人们的娱乐方式也在不断地推陈出新。其中&#xff0c;线上剧本杀小程序以其独特的沉浸式推理乐趣&#xff0c;成为了许多人的新宠。它不仅让我们在闲暇之余享受到了推理的快乐&#xff0c;更让我们在虚拟的世界里感受到了人性的复杂与多彩。 线…

【Linux网络编程】数据链路层

数据链路层 1.以太网帧格式2.重谈局域网转发的原理(基于协议)3.认识MTU3.1MTU对IP协议的影响3.2MTU对UDP协议的影响3.3MTU对于TCP协议的影响 4.ARP协议 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励…

Windows系统下将MySQL数据库表内的数据全量导入Elasticsearch

目录 下载安装Logstash 配置Logstash配置文件 运行配置文件 查看导入结果 使用Logstash将sql数据导入Elasticsearch 下载安装Logstash 官网地址 选择Windows系统&#xff0c;需下载与安装的Elasticsearch相同版本的&#xff0c;下载完成后解压安装包。 配置Logstash配…