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

news2024/11/25 6:56:12

        在上一篇 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 detail

using 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.coloradmin.cn/o/1846029.html

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

相关文章

超级ai 必须有个,超级大的词表,必须是个向量库 faiss is all you need

说明优点图像表示流程代码实现如下全部代码 说明 使用极其庞大的词表在模型压缩和图像token化方面带来了显著优势。由于词表巨大&#xff0c;我们不得不利用向量数据库对词表进行搜索&#xff0c;以找到最匹配的token。预测出的token会再次通过嵌入矩阵&#xff08;em&#xf…

短剧片源授权,类目丰富优惠多,抢先一步更新你的短剧系统片库!

前言 如今的短剧作为一种新兴的视听艺术形式&#xff0c;正以其独特的魅力迅速占领市场高地。为了满足广大短剧爱好者和从业者的需求&#xff0c;我们提供短剧片源授权服务&#xff0c;凭借剧场独家提供的丰富片源&#xff0c;助力您轻松更新短剧系统片库&#xff0c;抢占市场…

不见五陵高管墓,无花无酒锄做田

不见五陵高管墓&#xff0c;无花无酒锄做田 Golang 通用代码生成器仙童 2.4.0 电音仙女尝鲜版七已发布&#xff0c;此版本测试修复了 PostgreSQL 数据库自动反射功能。此版本更新修复了前端代码生成器&#xff0c;并修复了前端多对多界面的缺陷。PostgreSQL 的数据库反射功能刚…

安装TensorFlow报错问题ERROR: Failed building wheel for h5py解决

安装TensorFlow报错问题&#xff1a; 安装命令: pip install tensorflow2.12.0 -i https://pypi.tuna.tsinghua.edu.cn/simple Building wheel for h5py (PEP 517) ... error ERROR: Command errored out with exit status 1: command: /usr/bin/python3 /tmp/tmpz0y9yg…

代码生成器技术乱弹五十三,人工智能和通用代码生成器的共同点:Token

代码生成器技术乱弹五十三&#xff0c;人工智能和通用代码生成器的共同点&#xff1a;Token 现在&#xff0c;随着人工智能的快速发展&#xff0c;特别是生成式人工智能的爆火&#xff0c;大家逐渐熟悉了一个概念&#xff0c;Token。我称之为字牌。在生成式人工智能的语境下&a…

【每日刷题】Day72

【每日刷题】Day72 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1287. 有序数组中出现次数超过25%的元素 - 力扣&#xff08;LeetCode&#xff09; 2. 993. 二叉树的…

视创云展为企业虚拟展厅搭建,提供哪些功能?

在当下数字化浪潮中&#xff0c;如何为用户创造更富生动性和真实感的展示体验&#xff0c;已成为企业营销策略的核心。借助视创云展的线上虚拟3D企业展厅搭建服务&#xff0c;利用3D空间漫游和VR技术的融合&#xff0c;可以为用户呈现出一个既真实又充满想象力的全景图或三维模…

中央空调水系统安装

冷热水管&#xff1a; 空调冷热水管道的材质应由业主或使用方明确&#xff1a; 1、普通焊接钢管&#xff1b; 2、无缝钢管&#xff1b; 3、镀锌钢管&#xff1b; 4、PP-R管&#xff1b; 5、紫铜管&#xff1b; 6、水管内外表面应光洁、无疵孔、裂缝、结疤、层裂或气泡。…

Python12 列表推导式

1.什么是列表推导式 Python的列表推导式&#xff08;list comprehension&#xff09;是一种简洁的构建列表&#xff08;list&#xff09;的方法&#xff0c;它可以从一个现有的列表中根据某种指定的规则快速创建一个新列表。这种方法不仅代码更加简洁&#xff0c;执行效率也很…

【总线】AXI4第四课时:信号描述

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣&#xff0c;那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者&#xff0c;AXI4以其高性能和高度可扩展性&#xff0c;成为了现代电子系统中不可或缺的通信桥梁…

05 Pytorch 数据读取 + 二分类模型

05 Pytorch 数据读取 二分类模型05 Pytorch 数据读取 二分类模型05 Pytorch 数据读取 二分类模型 01 数据读取 DataLoader&#xff08;set作为参数&#xff09; 02 Dataset 从哪读&#xff0c;怎么读&#xff1f; 功能&#xff1a;数据从哪里读取&#xff1f; 如何读取…

BEV端到端视觉论文合集|从不同的视角解析BEV感知技术

随着自动驾驶技术的不断发展&#xff0c;基于摄像头的感知系统已成为关键&#xff0c;而Bird’s Eye View (BEV)大模型在其中发挥着重要作用。BEV大模型是一种将摄像头捕捉到的2D图像转换为自上而下视角的3D感知的技术&#xff0c;使得车辆能够更好地理解周围环境。 BEV大模型…

吴恩达机器学习 第三课 week1 无监督机器学习(下)

目录 01 学习目标 02 异常检测算法 2.1 异常检测算法的概念 2.2 基于高斯模型的异常检测 03 利用异常检测算法检测网络服务器的故障 3.1 问题描述 3.2 算法实现 3.3 问题升级 04 总结 01 学习目标 &#xff08;1&#xff09;理解异常检测算法&#xff08;Anomaly Det…

编程精粹—— Microsoft 编写优质无错 C 程序秘诀 06:危险的行业

这是一本老书&#xff0c;作者 Steve Maguire 在微软工作期间写了这本书&#xff0c;英文版于 1993 年发布。2013 年推出了 20 周年纪念第二版。我们看到的标题是中译版名字&#xff0c;英文版的名字是《Writing Clean Code ─── Microsoft’s Techniques for Developing》&a…

Mac安装多个jdk环境(jdk8+jdk17)保姆级

Mac安装多个jdk环境&#xff08;jdk8jdk17&#xff09;保姆级 背景&#xff1a;新机安装开发环境发现需要找很多文章&#xff0c;&#xff0c;&#xff0c;&#xff0c;这里一篇文章安装所有环境 文章目录 Mac安装多个jdk环境&#xff08;jdk8jdk17&#xff09;保姆级&#x1f…

基于springboot实现火车票订票系统项目【项目源码+论文说明】

基于springboot实现火车票订票系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火车票订票系统软件来…

【SpringCloud】Eureka的简单使用

本文使用的是jdk17&#xff0c;mysql8。 以下用两个服务做演示&#xff1a; 订单服务&#xff1a;提供订单ID&#xff0c;获取订单详细信息。 商品服务&#xff1a;提供商品ID&#xff0c;获取商品详细信息。 对于上篇http://t.csdnimg.cn/vcWpo 订单服务调用商品服务的时候&a…

一文读懂 HTTP 和 RPC 的区别

随着互联网技术的发展&#xff0c;网络通信在各种应用中扮演着至关重要的角色。无论是构建 Web 应用还是进行服务之间的交互&#xff0c;选择合适的通讯协议成为开发者们需要深入思考的问题。在众多协议中&#xff0c;HTTP&#xff08;HyperText Transfer Protocol&#xff09;…

JavaSE 面向对象程序设计进阶 抽象类和接口 2024年详解

目录 抽象类 抽象方法 抽象类和抽象方法的注意事项 ​编辑 接口 如何定义接口 注意 代码实现 ​编辑 接口中的成员特点 接口和类之间的关系 1.类与类的关系 2.类与接口的关系 3.接口与接口的关系 ​编辑 拓展 接口中的默认方法 接口中的静态方法 ​编辑 接口…

全新升级微信分销商城小程序源码系统 前后端分离 带完整的安装代码包以及搭建部署教程

系统概述 微信分销商城小程序源码系统是基于先进的技术和理念开发而成的。它旨在为企业和商家打造一个功能齐全、用户体验良好的分销平台&#xff0c;帮助他们更好地管理商品、销售渠道和用户关系&#xff0c;实现业务的快速增长和持续发展。 代码示例 系统特色功能一览 1.多…