SurfaceFlinger学习笔记(一)应用启动流程
SurfaceFlinger学习笔记(二)之Surface
SurfaceFlinger学习笔记(三)之SurfaceFlinger进程
SurfaceFlinger学习笔记(四)之HWC2
SurfaceFlinger学习笔记(五)之HWUI
SurfaceFlinger学习笔记(六)之View Layout Draw过程分析
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的内容 |
在SurfaceFlinger学习笔记(三)之SurfaceFlinger进程中,SurfaceFlinger的init中注册HWComposer
SurfaceFlinger的事件线程
- SurfaceFlinger为主要线程,用于处理SurfaceFlinger接收到的事件
- EventControlThread,就像是Vsync信号产生的闸门,当然闸门肯定需要人去打开和关闭,这个人就是SF;即控制Vsync信号的开头
- DispSyncThread,是Vsync信号的模型,首先触发DispSyncThread,然后DispSyncThread再去驱动其他事件,它就是Vsync在SF中的代表
- EventThread,具体的事件线程,由DispSyncThread去驱动。EventThread线程有两个一个是用于SF的,别一个是用于APP
- 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的抽象
所以,整个显示系统的数据流如下图所示:
后端SurfaceFlingerBE
SurfaceFlingerBE是Android P上新分离出来的,没有太多信息,从目前的定义来看是将SurfaceFlinger分离为前端和后端,这里的SurfaceFlingerBE就是后端,现在的SurfaceFlinger充当前端的角色。后端SurfaceFlingerBE主要就是和底层合成打交道,前端和上层进行交互。在后续的版本中,更多的逻辑会被移到后端中
消息队列和主线程
和应用进程类似,SurfaceFlinger也有一个主线程,SurfaceFlinger的主线程主要进行显示数据的处理,也就是合成。SurfaceFlinger是一个服务,将会响应上层的很多请求,各个进程的请求都在SurfaceFlinger的各个Binder线程中,如果线程很耗时,那么应用端就会被block,显示也会被block。主线程就是将他们分离开来,各干各的事
dump信息
dump信息是很好的一个调试手段,dump命令 如下:
adb shell dumpsys SurfaceFlinger
HWC2 数据结构
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在每一层中的代码的实现不一样,基本上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
};
}
- Surfacelinger创建Surface的时候,会调用createLayer,然后调用addClientLayer函数,这里会把Layer对象放在mCurrentState的layerSortedByZ对象中
- Surfacelinger合成的时候,调用preComposition函数,会先调用mDrawingState的layerSortedByZ来获取上次绘图的Layer层列表(并不是所有layer都参与屏幕图像的绘制,因此通过State对象记录参与绘制的Layer对象)
- Layer对象在绘制图形时,使用的是mDrawingState变量;用户调用接口设置Layer对象属性时,设置的值保存在mCurrentState中。这样就不会因为用户的操作而干扰Layer对象的绘制了。
- Layer::doTransaction函数会比较这两个成员变量,如果有不同的地方,说明上次绘制后,用户改变了Layer的属性,要把这种变化通过flags返回
- layerStack字段是用户指定的一个值,用户可以给DisplayDevice指定一个layerStack值,只有Layer对象和DisplayDevice对象的layerStack相等,这个Layer才能在这个显示设备输出。这样的好处可以让显示设备只显示某个Surface的内容。例如,可以让HDMI显示设备只显示手机上播放的Surface窗口,但是不显示Activity窗口。
- Layer::doTransaction最后会调用commitTransaction函数,就是将mCurrentState赋值给mDrawingState
- 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;
};
- 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服务之间,很多函数,并没有直接的调用,而是通过Buffer的读写来实现调用和参数的传递的,基本通过以下相关的途径
通过IComposerClient.hal接口
通过IComposer.hal接口
通过command Buffer(为了解决Binder通信慢的问题)
HWC端回调SurfaceFlinger端,通过IComposerCallback.hal接口