Android下HWC以及drm_hwcomposer普法(上)

Android下HWC以及drm_hwcomposer普法(上)



引言

按摩得全套,错了,做事情得全套,普法分析也是如此。drm_hwcomposer如果对Android图形栈有一定研究的童鞋们应该知道它是Android提供的一个的图形后端合成处理HAL模块的实现。但是在分析这个之前我们非常有必要了解一下Android的HWC前世今生,然后再来看drm_hwcomposer是如何配合HWC框架的



一.普法HWC

这里我们对HWC的普法主要从如下接方面展开进行:

  • HWC的概述
  • HWC的进化
  • HWC中重要概念和实现逻辑

1.1 HWC概述

我们知道SurfaceFlinger可以使用OpenGLES合成Layer,但是这需要占用并消耗大量的GPU资源。大多数GPU都没有针对图层合成进行优化,当SurfaceFlinger通过GPU合成图层时,应用程序无法使用GPU进行自己的渲染。为了解放GPU的绘制能力,很多芯片厂家会提供硬件叠加合成,如果硬件叠加器支持的场景都可以走硬件叠加,解放GPU的绘制能力专心绘制,提升的渲染性能同时还能大幅度的降低功耗(GPU强绘制,叠加搬移并不擅长,高功耗)这个时候我们的HWC就登场了,HWC(hwcomposer)是Android中进行窗口(Layer)合成和显示的HAL层模块,其实现是特定于设备的,而且通常由显示设备制造商(OEM)完成,为SurfaceFlinger服务提供硬件支持。而HWC通过硬件设备进行图层合成,可以减轻GPU的合成压力。应用把要显示的layers交给SurfaceFlinger,SurfaceFlinger直接把这些layers交给hwc,hwc就可以在自己能力范围内做好合成,再把合成好的结果拿去显示。如果芯片显示硬件模块功能较弱,不支持某些合成场景,就会用CPU(纯软件合成)或者GPU去做。

在这里插入图片描述

显示设备的能力千差万别,很难直接用API表示硬件设备支持合成的Layer数量,Layer是否可以进行旋转和混合模式操作,以及对图层定位和硬件合成的限制等。因此HWC描述上述信息的流程是这样的:

  • SurfaceFlinger向HWC提供所有Layer的完整列表,让HWC根据其硬件能力,决定如何处理这些Layer。

  • HWC会为每个Layer标注合成方式,是通过GPU还是通过HWC合成。

  • SurfaceFlinger负责先把所有注明GPU合成的Layer合成到一个输出Buffer,然后把这个输出Buffer和其他Layer(注明HWC合成的Layer)一起交给HWC,让HWC完成剩余Layer的合成和显示。
    虽然每个显示设备的能力不同,但是官方要求每个HWC硬件模块都应该支持以下能力:

  • 至少支持4个叠加层:状态栏、系统栏、应用本身和壁纸或者背景。

  • 叠加层可以大于显示屏,例如:壁纸

  • 同时支持预乘每像素(per-pixel)Alpha混合和每平面(per-plane)Alpha混合。

  • 为了支持受保护的内容,必须提供受保护视频播放的硬件路径。
    RGBA packing order, YUV formats, and tiling, swizzling, and stride properties

虽然上述官网要求如此,但是,但是很多hwc是没有达到上述要求的,有的叠加只支持一层的primary plane,也不支持各种混合,各种特性,毕竟建议还是建议。
Tiling:可以把Image切割成MxN个小块,最后渲染时,再将这些小块拼接起来,就像铺瓷砖一样。
Swizzling:一种拌和技术,表示向量单元可以被任意地重排或重复。 但是并非所有情况下HWC都比GPU更高效,例如:当屏幕上没有任何变化时,尤其是叠加层有透明像素并且需要进行图层透明像素混合时。在这种情况下,HWC可以要求部分或者全部叠加层都进行GPU合成,然后HWC持有合成的结果Buffer,如果SurfaceFlinger要求合成相同的叠加图层列表,HWC可以直接显示之前合成的结果Buffer,这有助于提高待机设备的电池寿命。

HWC也提供了VSync事件,用于管理渲染和图层合成时机。


1.2 HWC的进化

Android的HWC模块经历了HWC和HWC2两个版本,现在高版本默认使用HWC2,然后其加载方式也由原来的的SurfaceFlinger直接通过loader加载HAL模块,变成现在的通过HIDL调用到composer service单独加载HAL模块实现。活是越来越整得复杂了。

无论通过和中方式加载HAL的实现,我们需要知道的一点就是HAL加载的流程是,先加载hwcomposer模块得到hw_module_t,再打开composer设备得到hw_device_t。hw_module_t和hw_device_t定义在hardware/libhardware/include/hardware/hardware.h,表示一个HAL层模块和属于该模块的一个实现设备。注意这里是先有HAL模块,再有实现此模块的硬件设备。

struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;


typedef struct hw_module_t {
   
    uint32_t tag;

    uint16_t module_api_version;
#define version_major module_api_version
#define version_minor hal_api_version

    /** Identifier of module */
    const char *id;

    /** Name of this module */
    const char *name;

    /** Author/owner/implementor of the module */
    const char *author;

    /** Modules methods */
    struct hw_module_methods_t* methods;

    /** module's dso */
    void* dso;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

typedef struct hw_module_methods_t {
   
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;


typedef struct hw_device_t {
   
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    uint32_t tag;


    uint32_t version;

    /** reference to the module this device belongs to */
    struct hw_module_t* module;

    /** padding reserved for future use */
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif

    /** Close this device */
    int (*close)(struct hw_device_t* device);

} hw_device_t;

#ifdef __cplusplus
#define TO_HW_DEVICE_T_OPEN(x) reinterpret_cast<struct hw_device_t**>(x)
#else
#define TO_HW_DEVICE_T_OPEN(x) (struct hw_device_t**)(x)
#endif

/**
 * Name of the hal_module_info
 */
#define HAL_MODULE_INFO_SYM         HMI

/**
 * Name of the hal_module_info as a string
 */
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"


int hw_get_module(const char *id, const struct hw_module_t **module);


int hw_get_module_by_class(const char *class_id, const char *inst,
                           const struct hw_module_t **module);

__END_DECLS

#endif  /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */

我们是基于HWC2协议实现,则需要实现hwcomposer2.h中定义的hwc2_device_t接口,而我们后续要分析的drm_hwcomposer就是基于HWC2的实现。每个HAL层模块实现都要定义一个HAL_MODULE_INFO_SYM数据结构,并且该结构的第一个字段必须是hw_module_t。这里关于它们之间的对应关系,和一些数据结构这里暂时不分析,太多了,这里我们不做过多分析。


1.3 HWC中重要的概念和核心调用逻辑

这里我们的重点不是SurfaceFlinger里面HWC相关的代码部分分析,但是该有的概念和一些核心调用逻辑还是必须提前知道:

但是我们如下的几个重要的概念我们必须要有:

  • HWC2::Device:表示硬件合成显示设备
  • HWC2::Display:表示一个显示屏幕,可以是物理显示屏(可以热插拔接入或者移除),也可以是虚拟显示屏,现在的游戏录屏一般都是基于虚拟屏幕实现的。
  • HWC2::Layer:表示一个叠加图层,对应与应用侧的Surface。

在进行接下来的分析前,我们先来一个Layer的合成方式是怎么确定的那?大致流程如下所示!

在这里插入图片描述

其基本流程可以归纳总结为如下:

  • 当VSync信号到来时,SurfaceFlinger被唤醒,处理Layer的新建,销毁和更新,并且为相应Layer设置期望的合成方式。
  • 所有Layer更新后,SurfaceFlinger调用validateDisplay,让HWC决定每个Layer的合成方式。
  • SurfaceFlinger调用getChangedCompositionTypes检查HWC是否对任何Layer的合成方式做出了改变,若是,那么SurfaceFlinger则调整对应Layer的合成方式,并且调用acceptDisplayChanges通知HWC。
  • SurfaceFlinger把所有Client类型的Layer合成到Target图形缓冲区,然后调用setClientTarget把Target Buffer设置给HWC。(如果没有Client类型的Layer,则可以跳过该方法)
  • 最后,SurfaceFlinger调用presentDisplay,让HWC完成剩余Layer的合成,并且在显示屏上展示出最终的合成结果。

  • HWC2::Layer的创建流程
SurfaceFlinger::onMessageReceived
  onMessageRefresh()//Android 13上面是通过andler::handleMessage compositor.composite
    mCompositionEngine->present(refreshArgs)
      output->prepare(args, latchedLayers)
        Output::rebuildLayerStacks
          Output::collectVisibleLayers
            Output::ensureOutputLayerIfVisible
              BaseOutput::createOutputLayer(layerFE)
                Display::createOutputLayer
                  hwc.createLayer
                    mComposer.createLayer
                        HwcDisplay::CreateLayer//drm_hwcomposer
05-26 01:57:17.427  2264  2264 D createOutputLayer: #00 pc 000000000013f994  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::Display::createOutputLayer(android::sp<android::compositionengine::LayerFE> const&) const+84)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #01 pc 0000000000140dfc  /system/lib64/libsurfaceflinger.so (std::__1::shared_ptr<android::compositionengine::impl::Display> android::compositionengine::impl::createOutputTemplated<android::compositionengine::impl::Display, android::compositionengine::CompositionEngine>(android::compositionengine::CompositionEngine const&)::Output::ensureOutputLayer(std::__1::optional<unsigned long>, android::sp<android::compositionengine::LayerFE> const&)+80)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #02 pc 00000000001475e0  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::Output::ensureOutputLayerIfVisible(android::sp<android::compositionengine::LayerFE>&, android::compositionengine::Output::CoverageState&)+1692)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #03 pc 0000000000146e60  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::Output::collectVisibleLayers(android::compositionengine::CompositionRefreshArgs const&, android::compositionengine::Output::CoverageState&)+128)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #04 pc 0000000000146d38  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::Output::rebuildLayerStacks(android::compositionengine::CompositionRefreshArgs const&, std::__1::unordered_set<android::sp<android::compositionengine::LayerFE>, android::compositionengine::LayerFESpHash, std::__1::equal_to<android::sp<android::compositionengine::LayerFE> >, std::__1::allocator<android::sp<android::compositionengine::LayerFE> > >&)+340)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #05 pc 0000000000146a3c  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::Output::prepare(android::compositionengine::CompositionRefreshArgs const&, std::__1::unordered_set<android::sp<android::compositionengine::LayerFE>, android::compositionengine::LayerFESpHash, std::__1::equal_to<android::sp<android::compositionengine::LayerFE> >, std::__1::allocator<android::sp<android::compositionengine::LayerFE> > >&)+56)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #06 pc 000000000013eb3c  /system/lib64/libsurfaceflinger.so (android::compositionengine::impl::CompositionEngine::present(android::compositionengine::CompositionRefreshArgs&)+116)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #07 pc 0000000000111c08  /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::onMessageRefresh()+1524)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #08 pc 000000000010ee5c  /system/lib64/libsurfaceflinger.so (android::SurfaceFlinger::onMessageReceived(int, long)+88)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #09 pc 0000000000019b8c  /system/lib64/libutils.so (android::Looper::pollInner(int)+372)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #10 pc 00000000000199b0  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
05-26 01:57:17.428  2264  2264 D createOutputLayer: #11 pc 00000000000f7850  /system/lib64/libsurfaceflinger.so (android::impl::MessageQueue::waitMessage(
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值