Android SurfaceFlinger——SF与HWC交互流程(六)

        在上一篇 HWC2On1Adapter 初始化完成后,调用 initWithDevice() 实例化 HwcHal 对象,然后创建高级接口(IComposer),使得调用者能够通过这个接口与硬件进行交互。这里我们就来看一下 HwcHal 和 IComposer 的初始化流程。

一、HWC HAL初始化

1、HwcLoader.h

源码位置:/hardware/interfaces/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h

initWithDevice

namespace detail {
……
// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
template <typename Hal>
class HwcHalImpl : public Hal {public:virtual ~HwcHalImpl() {if (mDevice) {hwc2_close(mDevice);}}……bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) {// 从现在起,我们拥有这个设备mDevice = device;initCapabilities();if (requireReliablePresentFence &&hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {ALOGE("present fence must be reliable");mDevice->common.close(&mDevice->common);mDevice = nullptr;return false;}if (!initDispatch()) {mDevice->common.close(&mDevice->common);mDevice = nullptr;return false;}return true;}……
}  // namespace detailusing HwcHal = detail::HwcHalImpl<hal::ComposerHal>;

        HwcHalImpl 本质上就是继承 hal::ComposerHal,也就是说 ComposerHal 持有一个 hw_device_t 结构体,作为真正的操作对象。

        调用 initDispatch 为 mDispatch 结构体中所有的函数指针都初始化。

mDispatch

struct {HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;HWC2_PFN_CREATE_LAYER createLayer;HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;HWC2_PFN_DESTROY_LAYER destroyLayer;HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;HWC2_PFN_DUMP dump;HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;HWC2_PFN_GET_COLOR_MODES getColorModes;HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;HWC2_PFN_GET_DISPLAY_NAME getDisplayName;HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;HWC2_PFN_PRESENT_DISPLAY presentDisplay;HWC2_PFN_REGISTER_CALLBACK registerCallback;HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;HWC2_PFN_SET_CLIENT_TARGET setClientTarget;HWC2_PFN_SET_COLOR_MODE setColorMode;HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;HWC2_PFN_SET_LAYER_COLOR setLayerColor;HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;HWC2_PFN_SET_POWER_MODE setPowerMode;HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
} mDispatch = {};

        之后所有调用函数都是是通过 mDispatch 调用 hw_device_t 的方法。

二、创建IComposer接口 

1、createComposer

源码位置:/hardware/interfaces/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h

// 创建IComposer实例
static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) {return hal::Composer::create(std::move(hal)).release();
}

2、Composer.h

源码位置:/hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h 

static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {return std::make_unique<ComposerImpl>(std::move(hal));
}

        可以看到,这里本质上就是一个 ComposerImpl 持有了 ComposerHal。 接下来结合前两篇文章看一下整个 UML 图。

        硬件加载完成后创建了 HAL 实例,又完成了 IComposer 的创建,到这里就可以通过 IComposer 与 HWC 进行交互。 我们来看其中两个比较重要的方法,一个是通过 createClient() 方法创建 ComposerClient,而该函数是在 ComposerHal 中调用。另一个就是通过注册监听 Hal 层实现监听驱动的关键动作。

三、创建ComposerClient

1、HidlComposerHal.cpp

源码位置:/frameworks/native/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp

HidlComposer::HidlComposer(const std::string& serviceName) : mWriter(kWriterInitialSize) {mComposer = V2_1::IComposer::getService(serviceName);……if (sp<IComposer> composer_2_4 = IComposer::castFrom(mComposer)) {……} else if (sp<V2_3::IComposer> composer_2_3 = V2_3::IComposer::castFrom(mComposer)) {……} else {mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {if (tmpError != Error::NONE) {return;}mClient = tmpClient;if (sp<V2_2::IComposer> composer_2_2 = V2_2::IComposer::castFrom(mComposer)) {mClient_2_2 = V2_2::IComposerClient::castFrom(mClient);}});}if (mClient == nullptr) {LOG_ALWAYS_FATAL("failed to create composer client");}
}

        mComposer 通过 getService 拿到 Hal 层的 IComposer 对象。调用到 ComposerImpl 中的 createClient() 方法。

2、createClient

public:
Return<void> createClient(IComposer::createClient_cb hidl_cb) override {std::unique_lock<std::mutex> lock(mClientMutex);if (!waitForClientDestroyedLocked(lock)) {hidl_cb(Error::NO_RESOURCES, nullptr);return Void();}sp<IComposerClient> client = createClient();if (!client) {hidl_cb(Error::NO_RESOURCES, nullptr);return Void();}mClient = client;hidl_cb(Error::NONE, client);return Void();
}protected:
virtual IComposerClient* createClient() {auto client = ComposerClient::create(mHal.get());if (!client) {return nullptr;}auto clientDestroyed = [this]() { onClientDestroyed(); };client->setOnClientDestroyed(clientDestroyed);return client.release();
}void onClientDestroyed() {std::lock_guard<std::mutex> lock(mClientMutex);mClient.clear();mClientDestroyedCondition.notify_all();
}

        这里最终调用了 ComposerClient::create() 方法实例化一个 IComposerClient,并调用相关回调。同时让 Composer 持有一个 mClient 对象,当销毁的时候,会调用 mClient 的 clear 方法,并且唤起阻塞。也就是销毁一个 HWC::Device 的 mClient 对象。

3、ComposerClient.h

源码位置:/hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h

static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {auto client = std::make_unique<ComposerClientImpl>(hal);return client->init() ? std::move(client) : nullptr;
}using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;

         这里实际调用的是 ComposerClient 的实现类 ComposerClientImpl 中的对应方法,接着调用 init() 方法。

bool init() {mResources = createResources();if (!mResources) {ALOGE("failed to create composer resources");return false;}mCommandEngine = createCommandEngine();return true;
}

        可以看到 Client 会持有两个对象,一个是 ComposerResources,另一个是ComposerCommandEngine。 

  • ComposerResources 控制整个 SurfaceFlinger 的 Hal 的资源,如绘制面 Layer、图元等。
  • ComposerCommandEngine 处理从 SurfaceFlinger 上层到hal层的一些命令,用来实现一些需要直接通信到驱动的命令。
virtual std::unique_ptr<ComposerResources> createResources() {return ComposerResources::create();
}virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
}

ComposerResources 初始化

源码位置:/hardware/interfaces/graphics/composer/2.1/utils/resources/ComposerResources.cpp

std::unique_ptr<ComposerResources> ComposerResources::create() {auto resources = std::make_unique<ComposerResources>();return resources->init() ? std::move(resources) : nullptr;
}bool ComposerResources::init() {return mImporter.init();
}

        可以看到在 ComposerResources 初始化时,调用了 ComposerHandleImporter 的 init() 方法。 

bool ComposerHandleImporter::init() {mMapper4 = mapper::V4_0::IMapper::getService();if (mMapper4) {return true;}ALOGI_IF(!mMapper4, "failed to get mapper 4.0 service, falling back to mapper 3.0");mMapper3 = mapper::V3_0::IMapper::getService();if (mMapper3) {return true;}ALOGI_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");mMapper2 = mapper::V2_0::IMapper::getService();ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");return mMapper2 != nullptr;
}

        该对象初始化了一个 IMapper 的 Hal 服务,其实该 Hal 服务就是图元申请器。换句话说 Composer 将会通过 ComposerResources 调用 ComposerHandleImporter 控制图元的状态。

ComposerCommandEngine 初始化

ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) : mHal(hal), mResources(resources) {mWriter = createCommandWriter(kWriterInitialSize);
}

        对于 ComposerCommandEngine 这个对象,等到用的时候再去详细分析。这里只要记住这两个比较重要的重要对象即可,后面会和它们打交道。

        到这里 ComposerClient 就算创建完成了,也完成了一次与 HWC 的交互流程,对于注册监听的分析我们放到下一篇文章。

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

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

相关文章

到底什么是载波聚合?

载波聚合技术是无线通信系统中的一项关键创新&#xff0c;它极大地提升了数据传输的效率和速度。 这项技术的核心思想其实相当直观&#xff0c;即&#xff1a;如果能够将多个独立的通信路径或连接聚合起来&#xff0c;那么相比单一路径&#xff0c;就能够传输更多的信息。 这就…

mysql设置密码复杂度策略,登录失败次数限制

在配置文件中加入如下配置&#xff0c;重启mysql服务 [mysqld] #密码复杂度插件 plugin-load-addvalidate_password.so validate-passwordFORCE_PLUS_PERMANENT validate_password_policy2 # 0简单 1普通 2困难 validate_password_length9 # 密码长度限制 #登录失败次数、时间…

描述React Hooks中的useMemo和useCallback的区别和用途。

React Hooks API中的useMemo和useCallback都是用于优化性能的钩子&#xff0c;但它们的用途和工作方式略有不同&#xff1a; 推荐大家看看我过往的文章 useMemo useMemo是一个性能优化钩子&#xff0c;它返回一个记忆化的值。useMemo可以避免在组件渲染时进行昂贵的计算或操作…

一文读懂数据仓库ODS层

数据仓库一般分为三层&#xff0c;分别为数据贴源层&#xff08;ODS&#xff0c;Operation Data Store&#xff09;、数据公共层&#xff08;CDM&#xff0c;Common Data Model&#xff09;和数据应用层&#xff08;ADS&#xff0c;Application Data Service&#xff09;。其中…

方舟云康亏损收窄:三年近10亿销售成本,平均付费及月活仍大幅承压

《港湾商业观察》施子夫 三度递表后&#xff0c;终于通过聆讯&#xff0c;方舟云康控股有限公司(以下简称&#xff0c;方舟云康)有望近期内挂牌港交所。方舟云康的国内运营主体为广州方舟云康信息科技集团有限公司、广州方舟医药有限公司。 值得关注的是&#xff0c;亏损的难…

Python中文自然语言处理(NLP)中文分词工具库之pkuseg使用详解

概要 在中文自然语言处理(NLP)中,分词是一个基础且关键的任务。pkuseg 是由北京大学开发的一个中文分词工具,专为处理现代汉语而设计。它采用了先进的深度学习技术,能够准确地进行中文分词,同时支持自定义词典和多领域分词。本文将详细介绍 pkuseg 库,包括其安装方法、…

《图数据库:理论与实践》书籍销售火爆,二次印刷重磅来袭!

好书共享&#xff0c;就在此刻&#xff01; 由创邻科技联合电子工业出版社匠心打磨三年&#xff0c;最终成稿的图数据库书籍《图数据库&#xff1a;理论与实践》发行上线后&#xff0c;获得了广泛好评&#xff0c;各平台销量迅速破千&#xff0c;并荣登京东 “数据库图书榜”热…

【Nprogress】页面跳转进度条

【Nprogress】页面跳转进度条 介绍安装引入并简单使用基本用法配置项常用方法 参考文档&#xff1a; 【博主&#xff1a;码农键盘上的梦】vue使用Nprogress进度条功能实现 【博主&#xff1a;夜幕506】vue项目的进度条插件 – nprogress 【官方项目地址】https://www.npmjs.com…

【C语言】数据的存储

本章重点 1. 数据类型详细介绍 2. 整形在内存中的存储&#xff1a;原码、反码、补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 Ⅰ、数据类型介绍 前面我们已经学习了基本的内置类型&#xff1a; 空间大小&#xff08;字节&#xff09; char //字…

别只看影响因子了!又1本毕业神刊偷偷被On Hold了!请谨慎投递

【SciencePub学术】昨日&#xff0c;2023JCR正式发布&#xff0c;现在影响因子的话题依旧是“热搜第一”。大家可以根据自己的研究方向&#xff0c;参考最新发布的JCR报告进行投稿选刊。若大家对于投稿选刊方面有任何问题&#xff0c;都可联系张老师为您解答&#xff01; 相关…

C++之STL(四)

1、迭代器 通过重载*、->、、--等运算符来支持指针操作。 迭代器是容器与算法的桥梁。 2、迭代器的类型 个人理解&#xff0c;迭代器是一个模板类&#xff0c;会根据你传入的类型&#xff0c;生成对应的类型。这个模板类里面存放这该类型的指针&#xff0c;里面重载了*、!…

Boom 3D软件安装包下载-Boom 3D官网最新版下载

众多使用者向我们证明了Boom3D软件31段均衡器和预设&#xff1a;均衡器允许您仅通过手指滑动来调制音频&#xff0c;并将其另存为自定义预设&#xff0c;预设已经精心设计为不同类型的歌曲&#xff0c;因此您能够简单地拨入音频以适应您的心情。相信大家都认同Boom 3D 是一款出…

189.二叉树:将有序数组转换为二叉搜索树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…

AI选美大赛揭晓10位入围AI佳丽

全球首届AI小姐选美大赛&#xff08;WAICAs&#xff09;于上月拉开帷幕&#xff0c;总奖池积累到1.6万英镑&#xff0c;1万余名AI创作者参与&#xff0c;报送了超过1500个AI角色参加这场比赛。WAICAs 全称是未来派世界人工智能创造者大奖&#xff0c;由 Fanvue 主办。日前&…

qt打包失败 ,应用程序无法正常启动0xc000007b解决办法

用 windeployqt 打包QT程序&#xff0c;运行时提示程序无法正常启动0xc000007b #原因&#xff1a;因本机装了多个版本的Qt&#xff0c;包括32位&#xff0c;64位的&#xff0c;在cmd下可能是环境变量原因&#xff0c;用 windeployqt 打的包无法运行 解决办法&#xff1a; 1、…

以餐厅为例,来谈谈VOC(客户之声)

VOC&#xff0c;即客户之声&#xff0c;是指通过收集和分析客户的反馈意见&#xff0c;了解他们的需求和期望&#xff0c;进而指导企业改进产品和服务。在餐厅经营中&#xff0c;VOC的应用不仅能够帮助餐厅了解顾客的口味偏好、用餐习惯&#xff0c;还能揭示服务流程中的不足和…

记录一个因 MYSQL 服务端和JDBC驱动版本不一致导致 HMS 启动失败问题

记录一个因 MYSQL 服务端和JDBC驱动版本不一致导致 HMS 启动失败问题 1. 问题现象 某运维同学安装 CDH 后 HIVE 服务报警&#xff0c;查看发现 HS2 的金丝雀检查失败&#xff0c;进一步查看发现&#xff0c;HS2 无法创建默认数据库&#xff0c;且 HMS 启动失败。遂找到笔者进…

vue3中如何使用pinia -- pinia使用教程(一)

vue3中如何使用pinia -- pinia使用教程&#xff08;一&#xff09; 安装使用创建 store使用 store访问修改 store 使用组合式 api 创建 store -- setup storepinia 和 hook 的完美结合如何解决上面的问题 使用 hook 管理全局状态和 pinia 有何优缺点&#xff1f;参考小结 pinia…

上位机图像处理和嵌入式模块部署(mcu之iap升级)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 mcu种类很多&#xff0c;如果是开发的时候需要对固件升级&#xff0c;整体还是比较容易的。不管是dap&#xff0c;还是st-link v2、j-link&#xf…

Modbus协议转Profibus协议网关接温控表与PLC通讯

一、前言 在智能化飞速发展的时代&#xff0c;各个行业都在使用自动化系统。在智能楼宇系统中&#xff0c;温控表和PLC&#xff08;可编程逻辑控制器&#xff09;通讯是至关重要的&#xff0c;在智能楼宇系统中&#xff0c;温控表起着监测和控制室内温度的重要作用。而PLC作为…