SurfaceFlinger学习笔记(四)之HWC2

SurfaceFlinger学习笔记(一)应用启动流程
SurfaceFlinger学习笔记(二)之Surface
SurfaceFlinger学习笔记(三)之SurfaceFlinger进程
SurfaceFlinger学习笔记(四)之HWC2
SurfaceFlinger学习笔记(五)之HWUI
SurfaceFlinger学习笔记(六)之View Layout Draw过程分析

HWC概述

HWC(hwcomposer)是Android中进行窗口(Layer)合成和显示的HAL层模块,其实现是特定于设备的,而且通常由显示设备制造商 (OEM)完成,为SurfaceFlinger服务提供硬件支持。
HWC属于Binderized的HAL类型。Binderized类型的HAL,将上层Androd和底层HAL分别采用两个不用的进程实现,中间采用Binder进行通信,为了和前面的Binder进行区别,这里采用HwBinder
SurfaceFlinger可以使用OpenGL ES合成Layer,这需要占用并消耗GPU资源。大多数GPU都没有针对图层合成进行优化,当SurfaceFlinger通过GPU合成图层时,应用程序无法使用GPU进行自己的渲染。而HWC通过硬件设备进行图层合成,可以减轻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硬件模块都应该支持以下能力

  • HWC 应至少支持 4 个叠加层(状态栏、系统栏、应用和壁纸/背景)。
  • 叠加层可以大于屏幕,因此 HWC 应能处理大于显示屏的层(例如壁纸
  • 同时支持预乘每像素(per-pixel)Alpha混合和每平面(per-plane)Alpha混合。
  • HWC 应能处理 GPU、相机和视频解码器生成的相同缓冲区,因此支持以下某些属性很有帮助。
    RGBA 打包顺序、YUV 格式、Tiling, swizzling和步幅属性
    Tiling:可以把Image切割成MxN个小块,最后渲染时,再将这些小块拼接起来,就像铺瓷砖一样。
    Swizzling:一种拌和技术,表示向量单元可以被任意地重排或重复。

HWC专注于优化,智能地选择要发送到叠加硬件的 Surface,以最大限度减轻 GPU 的负载。另一种优化是检测屏幕是否正在更新;如果不是,则将合成委托给 OpenGL 而不是 HWC,以节省电量。当屏幕再次更新时,继续将合成分载到 HWC

但是并非所有情况下HWC都比GPU更高效,例如:当屏幕上没有任何变化时,尤其是叠加层有透明像素并且需要进行图层透明像素混合时。在这种情况下,HWC可以要求部分或者全部叠加层都进行GPU合成,然后HWC持有合成的结果Buffer,如果SurfaceFlinger要求合成相同的叠加图层列表,HWC可以直接显示之前合成的结果Buffer,这有助于提高待机设备的电池寿命
HWC也提供了VSync事件,用于管理渲染和图层合成时机

下面是GPU和HWC两种方式的优劣对比

合成类型 耗电情况 性能情况 Alpha处理 DRM内容处理 其他限制
Device合成(HWC) 耗电低 性能高 很多Vendor的HWC不支持Alpha的处理和合成 基本都能访问DRM内容 能合成的Surface层数有限,对每种Surface类型处理层数有限
Client合成(GPU) 耗电高 性能低 能处理每个像素的Alpha及每个Layear的Alpha 早期版本GPU不能访问DRM的内容

HWC2实现

在SurfaceFlinger学习笔记(三)之SurfaceFlinger进程中,SurfaceFlinger的init中注册HWComposer

SurfaceFlinger的事件线程

  • SurfaceFlinger为主要线程,用于处理SurfaceFlinger接收到的事件
  • EventControlThread,就像是Vsync信号产生的闸门,当然闸门肯定需要人去打开和关闭,这个人就是SF;即控制Vsync信号的开头
  • DispSyncThread,是Vsync信号的模型,首先触发DispSyncThread,然后DispSyncThread再去驱动其他事件,它就是Vsync在SF中的代表
  • EventThread,具体的事件线程,由DispSyncThread去驱动。EventThread线程有两个一个是用于SF的,别一个是用于APP

SurfaceFlinger学习笔记(四)之HWC2_第1张图片

  • Client端
    Client也就是SurfaceFlinger,不过SurfaceFlinger采用前后端的设计,以后和HWC相关的逻辑应该都会放到SurfaceFlinger后端也就是SurfaceFlingerBE中
  • HWC2 Client端
    这一部分属于SurfaceFlinger进程,其直接通过Binder通信,和HWC2的HAL Server交互。这部分的代码也在SurfaceFlinger进程中,但是采用Hwc2的命名空间
  • HWC Server端
    这一部分还是属于Android的系统,这里将建立一个进程,实现HWC的服务端,Server端再调底层Vendor的具体实现。并且,对于底层合成的实现不同,这里会做一些适配,适配HWC1.x,和FrameBuffer的实现。这部分包含三部分:接口,实现和服务,以动态库的形式存在

[email protected]
[email protected]
[email protected]
代码位置: hardware/interfaces/graphics/composer/2.1/default

  • HWC Vendor的实现
    这部分是HWC的具体实现,这部分的实现由硬件厂商完成。比如高通平台,代码位置一般为hardware/qcom/display

ComposerCallback接口实现

* frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
class ComposerCallback {
 public:
 	//热插拔事件的回调,显示屏幕连接或断开时回调
    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, Connection connection) = 0;
    //接收底层HWComposer的刷新请求
    virtual void onRefreshReceived(int32_t sequenceId,  hwc2_display_t display) = 0;
    //Vsync事件上报,接收底层硬件上报的垂直同步信号
    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, int64_t timestamp) = 0;
    virtual ~ComposerCallback() = default;
};
class Device
{
public:
    explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);
    void registerCallback(ComposerCallback* callback, int32_t sequenceId);
    ...
}

Callback提供了注册接口registerCallback,在SurfaceFlinger初始化的时候注册

初始化时先构造HWComposer,getHwcServiceName通过属性系统debug.sf.hwcservicename获取const std::string mHwcServiceName并以此来创建HWC2::Device mHwcDevice, 及HWC2::Device 的成员android::Hwc2::Composer mComposer,此时会根据mHwcServiceName来判断是不是使用的VR及要作为要Binder的服务名,注VrComposer使用的Composer服务名为“vr,具体即Composer调用IComposer::getService()

  • onHotplugReceived: 热插拔事件的回调,显示屏幕连接或者断开时回调。
  • onRefreshReceived: 接收底层HWComposer的刷新请求。在repaintEverythingForHWC中,mRepaintEverything为true的时候,将触发一次刷新,重新进行合成显示。重新绘制说明底层配置、参数等有变动,SurfaceFlinger前面给的数据不能用,需要重新根据变动后的配置进行合成,给适合当前配置的显示数据
  • onVsyncReceived: Vsync事件上报,接收底层硬件上报的垂直同步信号。此处可以通过抓取Systrace的方式查看具体的Vsync的信息(底层硬件、SurfaceFlinger、APP三部分的Vsync,一般Android版本升级的时候会进行vsync的tuning)
* frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {
	...
	mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
    ...
}
void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
    Mutex::Autolock lock(mStateLock);
    if (sequenceId != getBE().mComposerSequenceId) {
        return;
    }
    repaintEverythingForHWC();
}
void SurfaceFlinger::repaintEverythingForHWC() {
    mRepaintEverything = true;
    //重新绘制,说明底层配置,参数等有变动,SurfaceFlinger前面给的数据不能用,得重新根据变动后的配置进行进行合成,给适合当前配置的显示数据
    mEventQueue->invalidate();
}
* frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
void HWComposer::registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) {
    mHwcDevice->registerCallback(callback, sequenceId);
}

显示周期Vsync

  • 设备显示会按照一定速率更新(一般是一秒60帧,即16.6ms刷新一次)。如果显示内容在刷新期间更新,则会出现撕裂现象,因此必须在周期之间更新(这也是vsync tunning的必要性,保持SurfaceFlinger和draw frame都在vsync周期里面,并且不重叠)在可以安全更新内容时,系统便会接收来自显示设备的信号。
  • 刷新率可能会随时间而变化,例如,一些移动设备的刷新率范围在 58 fps 到 62 fps 之间,具体要视当前条件而定。对于连接了 HDMI 的电视,刷新率在理论上可以下降到 24 Hz 或 48 Hz,以便与视频相匹配。由于每个刷新周期只能更新屏幕一次,因此以 200 fps 的刷新率为显示设备提交缓冲区只是在做无用功,因为大多数帧永远不会被看到。SurfaceFlinger 不会在应用提交缓冲区时执行操作,而是在显示设备准备好接收新的缓冲区时才会唤醒
  • 当 VSYNC 信号到达时,SurfaceFlinger 会遍历它的层列表,以寻找新的缓冲区。如果找到新的缓冲区,它会获取该缓冲区;否则,它会继续使用以前获取的缓冲区。SurfaceFlinger 总是需要可显示的内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略
  • 此处会在合成调用到SurfaceFlinger::handlePageFlip函数,函数中先调用BufferLayer::latchBuffer从BufferQueue取Buffer,然后等待Vsync信号更新到FrameBuffer

合成方式

目前SurfaceFlinger中支持两种合成方式,一种是Device合成,一种是Client合成。SurfaceFlinger 在收集可见层的所有缓冲区之后,便会询问 Hardware Composer 应如何进行合成

  • Client合成
    Client合成方式是相对与硬件合成来说的,其合成方式是,将各个Layer的内容用GPU渲染到暂存缓冲区中,最后将暂存缓冲区传送到显示硬件。这个暂存缓冲区,我们称为FBTarget,每个Display设备有各自的FBTarget。Client合成,之前称为GLES合成,我们也可以称之为GPU合成。Client合成,采用RenderEngine进行合成,GPU合成后数据,作为一个特殊的Layer,传给显示硬件
  • Device合成
    就是用专门的硬件合成器进行合成HWComposer,所以硬件合成的能力就取决于硬件的实现。其合成方式是将各个Layer的数据全部传给显示硬件,并告知它从不同的缓冲区读取屏幕不同部分的数据。HWComposer是Devicehec的抽象

所以,整个显示系统的数据流如下图所示:
SurfaceFlinger学习笔记(四)之HWC2_第2张图片
后端SurfaceFlingerBE

SurfaceFlingerBE是Android P上新分离出来的,没有太多信息,从目前的定义来看是将SurfaceFlinger分离为前端和后端,这里的SurfaceFlingerBE就是后端,现在的SurfaceFlinger充当前端的角色。后端SurfaceFlingerBE主要就是和底层合成打交道,前端和上层进行交互。在后续的版本中,更多的逻辑会被移到后端中

消息队列和主线程

和应用进程类似,SurfaceFlinger也有一个主线程,SurfaceFlinger的主线程主要进行显示数据的处理,也就是合成。SurfaceFlinger是一个服务,将会响应上层的很多请求,各个进程的请求都在SurfaceFlinger的各个Binder线程中,如果线程很耗时,那么应用端就会被block,显示也会被block。主线程就是将他们分离开来,各干各的事

dump信息
dump信息是很好的一个调试手段,dump命令 如下:

adb shell dumpsys SurfaceFlinger

SurfaceFlinger学习笔记(四)之HWC2_第3张图片

HWC2 数据结构
SurfaceFlinger学习笔记(四)之HWC2_第4张图片
HWC2 中提供了几个数据结构来描述合成以及可以显示设备的就交互,比如图层(Layer),显示屏(Display)。HWC2的一些常用接口定义在头文件hwcomposer2.h中

hardware/libhardware/include/hardware/hwcomposer_defs.h
hardware/libhardware/include/hardware/hwcomposer.h
hardware/libhardware/include/hardware/hwcomposer2.h
hardware/interfaces/graphics/common/1.0/types.hal

图层Layer

图层(Layer)是合成的最重要单元;每个图层都有一组属性,用于定义它与其他层的交互方式。Layer在每一层中的代码的实现不一样,基本上Laye的理念都是一样的

SurfaceFlinger中Layer
frameworks/native/services/surfaceflinger/Layer.h frameworks/native/services/surfaceflinger/BufferLayer.h frameworks/native/services/surfaceflinger/BufferQueueLayer.h frameworks/native/services/surfaceflinger/ColorLayer.h frameworks/native/services/surfaceflinger/ContainerLayer.h

HWC2中定义了HWC2::Layer
frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h

在HAL中实现时,定义为hwc2_layer_t,这是在头文件hwcomposer2.h中定义的
hardware/libhardware/include/hardware/hwcomposer2.h
typedef uint64_t hwc2_layer_t;

BufferQueueLayer 、BufferStateLayer继承自BufferLayer,ContainerLayer 、ColorLayer 继承自Layer,BufferLayer继承Layer

  • BufferLayer 顾名思义,就是有Buffer的Layer,需要上层应用Producer去生产
  • ColorLayer 可以绘制一种制定的颜色,和制定的透明度Alpha。它是取代之前的Dim Layer的,可以设置任何的颜色只,而不只是黑色

位置属性

定义层在其显示设备上的显示位置。包括层边缘的位置及其相对于其他层的 Z-Order(指示该层在其他层之前还是之后)等信息。Layer中为实现这一点,定义了除了z-order外,定义了很多个区域Region
SurfaceFlinger中定义的Region都是上层传下来的,在WindowManager空间。而在HWC中,用下面的结构描述

frameworks/native/services/surfaceflinger/Layer.h
class Layer : public virtual compositionengine::LayerFE {
    static std::atomic<int32_t> sSequence;
public:
    mutable bool contentDirty{false};
    // regions below are in window-manager space
    Region visibleRegion;
    Region coveredRegion;
    Region visibleNonTransparentRegion;
    Region surfaceDamageRegion;
    ...
}
hardware/libhardware/include/hardware/hwcomposer_defs.h
typedef struct hwc_frect {
    float left;
    float top;
    float right;
    float bottom;
} hwc_frect_t;
typedef struct hwc_rect {
    int left;
    int top;
    int right;
    int bottom;
} hwc_rect_t;
typedef struct hwc_region {
    size_t numRects;
    hwc_rect_t const* rects;
} hwc_region_t;

Layer.cpp状态–mCurrentState和mDrawingState

每一个Layer的都有两个状态:mCurrentState和mDrawingState,mCurrentState是给SurfaceFlinger的前端准备数据,mDrawingState是给将数据给到合成;每个状态有两个Geometry的描述requested和active,requested是上层请求的,active是当前正在用的;每个Geometry中,有一个Transform变换矩阵,一个Transform包含一个mat33的阵列,这个阵列包含平移、缩放、错切信息。

struct State {
        Geometry active_legacy;//计算后的实际尺寸
        Geometry requested_legacy;//用户设置的尺寸
        int32_t z;//Layer的Z轴值,值越小位置就越靠小
        uint32_t layerStack;//和显示设备的关联值

        uint8_t flags;//Layer的标志(如果上次绘制后用户改变了Layer)
        uint8_t reserved[2];
        int32_t sequence; //序列值,Layer的属性变化一次就会加一(例如setAlpha,setSize,setLayer等)
        。。。
        Region activeTransparentRegion_legacy;//实际的透明区域
        Region requestedTransparentRegion_legacy;//用户中的透明区域
        。。。
}
frameworks/native/libs/ui/include/ui/Transform.h
class Transform {
public:
    enum orientation_flags {
        ROT_0   = 0x00000000,
        FLIP_H  = HAL_TRANSFORM_FLIP_H,
        FLIP_V  = HAL_TRANSFORM_FLIP_V,
        ROT_90  = HAL_TRANSFORM_ROT_90,
        ROT_180 = FLIP_H|FLIP_V,
        ROT_270 = ROT_180|ROT_90,
        ROT_INVALID = 0x80
    };
    enum type_mask : uint32_t {
        IDENTITY            = 0,
        TRANSLATE           = 0x1,
        ROTATE              = 0x2,
        SCALE               = 0x4,
        UNKNOWN             = 0x8
    };
}
  1. Surfacelinger创建Surface的时候,会调用createLayer,然后调用addClientLayer函数,这里会把Layer对象放在mCurrentState的layerSortedByZ对象中
  2. Surfacelinger合成的时候,调用preComposition函数,会先调用mDrawingState的layerSortedByZ来获取上次绘图的Layer层列表(并不是所有layer都参与屏幕图像的绘制,因此通过State对象记录参与绘制的Layer对象)
  3. Layer对象在绘制图形时,使用的是mDrawingState变量;用户调用接口设置Layer对象属性时,设置的值保存在mCurrentState中。这样就不会因为用户的操作而干扰Layer对象的绘制了。
  4. Layer::doTransaction函数会比较这两个成员变量,如果有不同的地方,说明上次绘制后,用户改变了Layer的属性,要把这种变化通过flags返回
  5. layerStack字段是用户指定的一个值,用户可以给DisplayDevice指定一个layerStack值,只有Layer对象和DisplayDevice对象的layerStack相等,这个Layer才能在这个显示设备输出。这样的好处可以让显示设备只显示某个Surface的内容。例如,可以让HDMI显示设备只显示手机上播放的Surface窗口,但是不显示Activity窗口。
  6. Layer::doTransaction最后会调用commitTransaction函数,就是将mCurrentState赋值给mDrawingState
  7. SurfaceFlinger.cpp中的handleTransactionLocked函数会根据eTraversalNeeded标志决定是否要检查所有的Layer对象。如果某个Layer对象有这个标志,将会调用他的doTransaction函数。Layer::doTransaction函数返回的flags如果有eVisibleRegion说明这个Layer需要更新,就把mVisibleRegionDirty设置为true。handleTransaction的作用是处理系统在两次刷新期间的各种变化

内容属性

定义显示的内容如何呈现(即Buffer)。Layer的显示,除了之前的几个区域Region描述,还有很多结构进一步描述才能显示,例如裁减(用来扩展内容的一部分以填充层的边界)和转换(用来显示旋转或者翻转的内容)等信息

frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h

truct OutputLayerCompositionState {
    // The region of this layer which is visible on this output
    Region visibleRegion;
    // If true, client composition will be used on this output
    bool forceClientComposition{false};
    // If true, when doing client composition, the target may need to be cleared
    bool clearClientTarget{false};
    // The display frame for this layer on this output
    Rect displayFrame;
    // The source crop for this layer on this output
    FloatRect sourceCrop;
    // The buffer transform to use for this layer o on this output.
    Hwc2::Transform bufferTransform{static_cast<Hwc2::Transform>(0)};
    // The Z order index of this layer on this output
    uint32_t z;
    /*
     * HWC state
     */
    struct Hwc {
        explicit Hwc(std::shared_ptr<HWC2::Layer> hwcLayer) : hwcLayer(hwcLayer) {}
        // The HWC Layer backing this layer
        std::shared_ptr<HWC2::Layer> hwcLayer;
        // The HWC composition type for this layer
        Hwc2::IComposerClient::Composition hwcCompositionType{
                Hwc2::IComposerClient::Composition::INVALID};

        HwcBufferCache hwcBufferCache;
    };

    std::optional<Hwc> hwc;
    void dump(std::string& result) const;
};

SurfaceFlinger学习笔记(四)之HWC2_第5张图片

  • Layer区域和屏幕区域,就是Layer和屏幕本身的大小区域
  • sourceCrop:剪切区域,sourceCrop是对Layer进行剪切的,值截取部分Layer的内容进行显示;sourceCrop不超过Layer的大小,超过没有意义。
  • displayFrame:显示区域,displayFrame表示Layer在屏幕上的显示区域,具体说来,是sourceCrop区域在显示屏上的显示区域。displayFrame一般来说,小于屏幕的区域。而displayFrame可能比sourceCrop大,可能小,这都是正常的,只是需要做缩放,这就是合成时需要处理的。
  • visibleRegion:可见区域,displayFrame 区域不一定都能看到的,如果存在上层Layer,那么displayFrame区域可能部分或全部被盖住,displayFrame没有被盖住的部分就是可见区域visibleRegion。
  • damageRegion 受损区域,或者称之为更新区域。damageRegion表示Layer内容被破坏的区域,也就是说这部分区域的内容变了,所以这个属性一般是和上一帧相比时才有意义。这算是对合成的一种优化,重新合成时,我们只去合成damageRegion区域,其他的可见区域还是用的上一帧的数据。
  • visibleNonTransparentRegion:可见非透明区域。透明区域transparentRegion是可见区域visibleRegion的一部分,只是这一部分透明的看到的是底层Layer的内容。在SurfaceFlinger的Layer中定义visibleNonTransparentRegion,表示可见而又不透明的部分。
  • coveredRegion:被覆盖的区域。表示Layer被TopLayer覆盖的区域,一看图就很好理解。从图中,你可以简单的认为是displayFrame和TopLayer区域重合的部分。

HWC空间的区域大小是SurfaceFlinger空间的区域经过缩放,经过Transform旋转,移动等后才得出的

合成属性(确认用哪种合成方式)

定义层应如何与其他层合成。包括混合模式和用于Alpha合成的全层Alpha值等信息。总的说来,合成分为两个大类:GPU合成和HWC合成。根据具体的情况,分为下列几类

  • Client 相对HWC2硬件合成的概念,主要是处理BufferLayer数据,用GPU处理。
  • Device HWC2硬件设备,主要处理BufferLayer数据,用HWC处理
  • SolidColor 固定颜色合成,主要处理ColorLayer数据,用HWC处理或GPU处理。
  • Cursor 鼠标标识合成,主要处理鼠标等图标,用HWC处理或GPU处理
  • Sideband Sideband为视频的边频带,一般需要需要硬件合成器作特殊处理,但是也可以用GPU处理
hardware/libhardware/include/hardware/hwcomposer2.h
enum class Composition : int32_t {
    Invalid = HWC2_COMPOSITION_INVALID,
    Client = HWC2_COMPOSITION_CLIENT,
    Device = HWC2_COMPOSITION_DEVICE,
    SolidColor = HWC2_COMPOSITION_SOLID_COLOR,
    Cursor = HWC2_COMPOSITION_CURSOR,
    Sideband = HWC2_COMPOSITION_SIDEBAND,
};

合成OutputLayerCompositionState包含成的类型。通过Layer的setCompositionType方法进行指定

oid Layer::setCompositionType(const sp<const DisplayDevice>& display,
                               Hwc2::IComposerClient::Composition type) {
    const auto outputLayer = findOutputLayerForDisplay(display);
	...
    auto& compositionState = outputLayer->editState();

    if ((*compositionState.hwc).hwcCompositionType != type) {
        (*compositionState.hwc).hwcCompositionType = type;
        auto error = (*compositionState.hwc).hwcLayer->setCompositionType(static_cast<HWC2::Composition>(type));
       
    }
}

显示屏Display

显示屏Display是合成的另一个重要单元。系统可以具有多个显示设备,并且在正常系统操作期间可以添加或删除显示设备。该添加/删除可以应 HWC 设备的热插拔请求,或者应客户端的请求进行,这允许创建虚拟显示设备,其内容会渲染到离屏缓冲区(而不是物理显示设备)
HWC中,SurfaceFlinger中创建的Layer,在合成开始时,将被指定到每个Display上,此后合成过程中,每个Display合成指定给自己的Layer
SurfaceFlinger前端,每个显示屏,用DisplayDevice类描述,在后端显示数据用DisplayData描述。而在HWC2的Client端,定义了Display类进行描述。对于HWC2服务端则用hwc2_display_t描述,hwc2_display_t只是一个序号,Vendor具体实现时,才具体的去管理Display的信息
HWC2 提供相应函数来确定给定显示屏的属性,在不同配置(例如 4k 或 1080p 分辨率)和颜色模式(例如native颜色或真彩 sRGB)之间切换,以及打开、关闭显示设备或将其切换到低功率模式(如果支持)

Android支持多屏幕,多个屏幕可以显示一样的内容,也可以显示不一样的内容。我们通常的把他们称为主显,外显和虚显。主显就是内置的,默认的手机屏幕;外显就是HDMI,MHL等连接的屏幕;虚显,就是虚拟显示器,通过WFD连接的屏幕,或者是类似屏幕一样的Buffer消费者。
每添加一个显示屏,都会创建一个DisplayDevice,屏幕都是通过ID来标记的,一个屏幕可以有多个config信息,当前再用的是activeconfig,在SurfaceComposerClient中,获取config信息时,先获取多有的config信息,再获取active的config的ID,根据ID去取DisplayInfo

合成设备
HWC设备就一个,在头文件中定义如下

在HWC 的Client端,采用Device描述,底层采用hwc2_device_t描述。整个合成服务都是围绕hwc2_device_t展开的

hardware/libhardware/include/hardware/hwcomposer2.h
typedef struct hwc2_device {
    struct hw_device_t common;
    void (*getCapabilities)(struct hwc2_device* device, uint32_t* outCount,
            int32_t* /*hwc2_capability_t*/ outCapabilities);
    hwc2_function_pointer_t (*getFunction)(struct hwc2_device* device,
            int32_t /*hwc2_function_descriptor_t*/ descriptor);
} hwc2_device_t;

接口指针

HWC2 头文件中,HWC 接口函数由 lowerCamelCase 命名惯例 定义,但是这些函数名称的字段并不实际存在于接口中。相反,几乎每个函数都是通过使用 hwc2_device_t 提供的 getFunction 请求函数指针来进行加载。例如,函数 createLayer 是一个 HWC2_PFN_CREATE_LAYER 类型的函数指针,当枚举值 HWC2_FUNCTION_CREATE_LAYER 传递到 getFunction 中时便会返回该指针
接口指针定义在hwcomposer2.h中,基本上都是以HWC2_PFN*开始命名,而每个接口,都对应一个接口描述hwc2_function_descriptor_t

SurfaceFlinger和HWC通信

SurfaceFlinger和HWC服务之间,很多函数,并没有直接的调用,而是通过Buffer的读写来实现调用和参数的传递的,基本通过以下相关的途径

通过IComposerClient.hal接口
通过IComposer.hal接口
通过command Buffer(为了解决Binder通信慢的问题)

HWC端回调SurfaceFlinger端,通过IComposerCallback.hal接口

你可能感兴趣的:(技术总结,SurfaceFlinger)