Android SurfaceFlinger和HWC2概述

转载夕月风大佬博客: https://www.jianshu.com/p/824a9ddf68b9
参考Android Q AOSP源码添加修改部分内容
参考源码: http://aosp.opersys.com/xref/android-10.0.0_r14/

SurfaceFlinger概述

大多数APP在屏幕通常显示三个部分:

  • 屏幕顶部的状态栏
  • 底部或者侧边的导航栏
  • 应用的界面

有些应用会显示更多或者更少的层。例如主屏幕会有一个单独的壁纸层;全屏幕的游戏可能会隐藏状态栏目。这些可以通过Dump Surfacelinger查看BufferLayers部分的信息来获取具体信息(adb shell dumpsys SurfaceFlinger)。从Dump结果看,layer呈树形结构(Tree)分布。

每个层都可以单独更新。状态栏和导航栏由系统进程渲染,而应用层由应用渲染,两者之间不进行协调。

SurfaceFlinger类定义

frameworks/native/services/surfaceflinger/SurfaceFlinger.h
1
2
3
4
5
6
7
8
9
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
private HWC2::ComposerCallback
{
public:
SurfaceFlingerBE& getBE() { return mBE; }
const SurfaceFlingerBE& getBE() const { return mBE; }
......

继承BnSurfaceComposer,实现ISurfaceComposer接口;实现ComposerCallback;继承辅助类PriorityDumper,主要提供SurfaceFlinger的Dump信息,并且提高提供信息的分离和格式设置。

ISurfaceComposer接口实现

ISurfaceComposer是提供给上层Client端的接口(Bp端),此处的SurfaceFlinger是Server端(Bn端)。接口内容包括:

frameworks/native/include/gui/ISurfaceComposer.h
1
2
3
4
5
6
7
8
9
class ISurfaceComposer: public IInterface {
public:
DECLARE_META_INTERFACE(SurfaceComposer)
......
/* returns information for each configuration of the given display
* intended to be used to get information about built-in displays */
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) = 0;
......

接口在SurfaceFlinger中都有对应的方法实现。Client端通过Binder跨进程调到SurfaceFlinger中。获取Display的信息,其实现就是SurfaceFlinger的getDisplayConfig函数。

ComposerCallback接口实现

ComposerCallback是HWC2的callback接口,包括以下接口:

frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace HWC2 {

class Display;
class Layer;

// Implement this interface to receive hardware composer events.
//
// These callback functions will generally be called on a hwbinder thread, but
// when first registering the callback the onHotplugReceived() function will
// immediately be called on the thread calling registerCallback().
//
// All calls receive a sequenceId, which will be the value that was supplied to
// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
// from different hardware composer instances.
class ComposerCallback {
public:
virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
Connection connection) = 0;
virtual void onRefreshReceived(int32_t sequenceId,
hwc2_display_t display) = 0;
virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
int64_t timestamp) = 0;
virtual ~ComposerCallback() = default;
};
.....

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

1
2
3
4
5
6
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
....
mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
....

此处registerCallbackthis就是SurfaceFlinger对ComposerCallback接口的实现。

  • onHotplugReceived: 热插拔事件的回调,显示屏幕连接或者断开时回调。
  • onRefreshReceived: 接收底层HWComposer的刷新请求。在repaintEverythingForHWC中,mRepaintEverythingtrue的时候,将触发一次刷新,重新进行合成显示。重新绘制说明底层配置、参数等有变动,SurfaceFlinger前面给的数据不能用,需要重新根据变动后的配置进行合成,给适合当前配置的显示数据。
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
1
2
3
4
5
6
7
8
9
10
11
12
void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
Mutex::Autolock lock(mStateLock);
if (sequenceId != getBE().mComposerSequenceId) {
return;
}
repaintEverythingForHWC();
}

void SurfaceFlinger::repaintEverythingForHWC() {
mRepaintEverything = true;
mEventQueue->invalidate();
}
  • onVsyncReceived: Vsync事件上报,接收底层硬件上报的垂直同步信号。此处可以通过抓取Systrace的方式查看具体的Vsync的信息(底层硬件、SurfaceFlinger、APP三部分的Vsync,一般Android版本升级的时候会进行vsync的tuning
  • 显示周期Vsync: 设备显示会按照一定速率更新(一般是一秒60帧,即16.6ms刷新一次)。如果显示内容在刷新期间更新,则会出现撕裂现象,因此必须在周期之间更新(这也是vsync tunning的必要性,保持SurfaceFlinger和draw frame都在vsync周期里面,并且不重叠)在可以安全更新内容时,系统便会接收来自显示设备的信号。

刷新率可能会随时间而变化,例如一些设备的刷新范围在58fps至62fps之间,具体视当前条件而定。对于连接了HDMI的电视,刷新率在理论上可以下降到24Hz或者48Hz,以便和视频匹配。由于每个刷新周期只能更新屏幕一次,因此以200fps的刷新率为显示设备提交缓冲区并没有必要性,因为大部分桢不能被看到(人眼合适的是60fps)。SurfaceFlinger不会在应用提交缓冲区时进行操作,而是在显示设备准备好接收新缓冲区的时候才会唤醒。

当Vsync信号到达的时候,SurfaceFlinger会遍历层列表,以寻找新的缓冲区。如果找到会获取该缓冲区,否则会使用以前获取的缓冲区。SurfaceFlinger总是需要可显示的内容,因此会保留一个缓冲区。如果在某个层没有提交缓冲区,则该层会被忽略。

此处会在合成调用到handlePageFlip函数,函数中先调用latchBuffer从BufferQueue取Buffer,然后等待Vsync信号更新到FrameBuffer。

  • 合成方式: 目前SurfaceFlinger支持两种合成方式:一种是Device合成,一种是Client合成。SurfaceFlinger在收集可见层的所有缓冲区之后,便会询问HardwareComposer应该如何进行合成。
    • Client合成:之前称之为GLES合成,也可以称之为GPU合成,该合成方式是相对于硬件合成来说的,将各个Layer的内容用GPU渲染到暂存缓冲区中,最后将暂存缓冲区传送到显示硬件Client合成采用RenderEngine进行合成。
    • Device合成: 用专门的硬件合成器进行合成HWComposer,所以硬件合成的能力就取决于硬件的实现。其合成方式是将各个Layer的数据全部传给显示硬件,并告知它从不同的缓冲区读取屏幕不同部分的数据。HWComposer是Device合成的抽象。

合成方式可以从Dump SurfaceFlinger中查看到Layer的具体合成方式,GPU合成一般可以通过开发者选项中启动,强制GPU合成;而Device合成在Dump信息中一般显示成SDE合成。

GPU合成数据后,作为一个特殊的Layer传给显示硬件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Display 0 HWC layers:
-------------------------------------------------------------------------------
Layer name
Z | Comp Type | Disp Frame (LTRB) | Source Crop (LTRB)
-------------------------------------------------------------------------------
com.android.systemui.ImageWallpaper#0
rel 0 | Client | 0 0 1080 2280 | 0.0 0.0 1080.0 2280.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
net.oneplus.launcher/net.oneplus.launcher.Launcher#0
rel 0 | Client | 0 0 1080 2280 | 0.0 0.0 1080.0 2280.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StatusBar#0
rel 0 | Client | 0 0 1080 80 | 0.0 0.0 1080.0 80.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GestureButtonRegion#0
rel 0 | Client | 0 2216 1080 2280 | 0.0 0.0 1080.0 64.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ScreenDecorOverlay#0
rel 0 | Device | 0 0 1080 106 | 0.0 0.0 1080.0 106.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ScreenDecorOverlayBottom#0
rel 0 | Device | 0 2198 1080 2280 | 0.0 0.0 1080.0 82.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

|-----|------------|-----------|------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|
| Idx | Comp Type | Split | Pipe | W x H | Format | Src Rect (L T R B) | Dst Rect (L T R B) | Z | Flags | Deci(HxV) | CS | Rng |
|-----|------------|-----------|------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|
| 6 | GPU_TARGET | Pipe-1 | 94 | 1088 x 2288 | RGBA_8888_UBWC | 0 0 1080 2280 | 0 0 1080 2280 | 0 | 0x00000002 | 0 x 0 | 0 | 0 |
| 4 | SDE | Pipe-1 | 103 | 1088 x 112 | RGBA_8888_UBWC | 0 0 1080 106 | 0 0 1080 106 | 1 | 0x00000000 | 0 x 0 | 1 | 1 |
| 5 | SDE | Pipe-1 | 92 | 1088 x 96 | RGBA_8888_UBWC | 0 0 1080 82 | 0 2198 1080 2280 | 2 | 0x00000000 | 0 x 0 | 1 | 1 |
|-----|------------|-----------|------|-------------|--------------------------|---------------------|---------------------|----|------------|-----------|----|-----|
  • SurfaceFlingerBE: 从Android P上分离出来,定义上看是将Surfacelinger分离为前后端。
  • 消息队列和主线程: 和应用进程类似,SurfaceFlinger也有一个主线程,主要是进行显示数据的处理,即合成。Surfacelinger是一个服务,将会响应上层的请求,各个进程的请求都在SurfaceFlinger的各个Binder线程中,如果线程很耗时,那么应用端就会被block。主线程将他们分离开来,各干各的。

Note:

  1. SurfaceFligner有两个状态,Layer也有两个状态,一个是mCurrentState,一个是mDrawingState。
  2. 两个EventThread,一个是给SurfaceFlinger本身使用,一个是为了给应用分发事件的。

mCurrentStatemDrawingState

  1. 这两个成员是Layer类中Layer::State的类型。
Layer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct State {
Geometry active; //计算后的实际尺寸
Geometry requested; //用户设置的尺寸
int32_t z; //Layer的Z轴值,值越小位置就越靠小
uint32_t layerStack; //和显示设备的关联值

unit8_t alpha; //Layer的透明度
uint8_t flags; //Layer的标志(如果上次绘制后用户改变了Layer)
uint8_t reserved[2];
int32_t sequence; //序列值,Layer的属性变化一次就会加一(例如setAlpha,setSize,setLayer等)
...
// the transparentRegion hint is a bit special, it's latched only
// when we receive a buffer -- this is because it's "content"
// dependent.
Region activeTransparentRegion; //实际的透明区域
Region requestedTransparentRegion; //用户中的透明区域
...
};
  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。


  1. 以上的是在Layer.cpp中的两个成员变量,而在SurfaceFlinger.cpp也有同名的mCurrentStatemDrawingState两个成员变量(定义在SurfaceFlinger.h中),定义不一样,只是名字相同。
SF.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class State {
public:
explicit State(LayerVector::StateSet set) : stateSet(set), layersSortedByZ(set) {}
State& operator=(const State& other) {
// We explicitly don't copy stateSet so that, e.g., mDrawingState
// always uses the Drawing StateSet.
layersSortedByZ = other.layersSortedByZ;
displays = other.displays;
colorMatrixChanged = other.colorMatrixChanged;
if (colorMatrixChanged) {
colorMatrix = other.colorMatrix;
}
return *this;
}

const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid;
LayerVector layersSortedByZ; //保存所有参与绘制的Layer对象
DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays; //保存所有输出设备的DisplayDeviceState对象

bool colorMatrixChanged = true;
mat4 colorMatrix;

void traverseInZOrder(const LayerVector::Visitor& visitor) const;
void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
};
  1. SF.cpp中的handleTransactionLocked函数会根据eTraversalNeeded标志决定是否要检查所有的Layer对象。如果某个Layer对象有这个标志,将会调用他的doTransaction函数。Layer::doTransaction函数返回的flags如果有eVisibleRegion说明这个Layer需要更新,就把mVisibleRegionDirty设置为true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
// Notify all layers of available frames
mCurrentState.traverseInZOrder([](Layer* layer) {
layer->notifyAvailableFrames();
});

/*
* Traversal of the children
* (perform the transaction for each of them if needed)
*/

if (transactionFlags & eTraversalNeeded) {
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) return;

const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
mVisibleRegionsDirty = true;
});
}

......//这部分代码是根据每种显示设备的不同,设置和显示设备关联在一起的Layer(主要看LayerStack是否和DisplayDevice的layerStack相同)的TransformHint(主要指设备的显示方向orientation)

commitTransaction();

updateCursorAsync();
}

Note: handleTransaction的作用是处理系统在两次刷新期间的各种变化。Surfacelinger模块中不管是SurfaceFlinger类和Layer类


硬件合成HWC2概述

Hardware Composer HAL(HWC)是指硬件完成图像数据组合并显示的能力。

SurfaceFlinger是一个系统服务(系统启动时启动),作用是接收来自多个源的Buffer数据,并进行合成,然后发送到显示设备进行显示。

SurfaceFlinger和HWC的相互配合,实现Android系统的合成和显示(非GPU合成)。


Android 7.0包含新版本的HWC(HWC2),Android需要自行配置。

Android 8.0,HWC2正式开启,并且版本升级为2.1。(/frameworks/native/services/surfaceflinger/DisplayHardware/

HWC2是SurfaceFlinger用来与专门的窗口合成硬件进行通信(Device合成方式)。SurfaceFlinger包含使用3D图形处理器(GPU)执行窗口合成任务的备用途径,但是此路径并不理想(GPU合成方式),因为:

  1. 通常,GPU没有针对此进行优化,因此能耗可能大于执行合成所需的能耗;
  2. 每次SUrfaceFlinger使用GPU合成时,应用都无法使用处理器进行自我渲染,因此应尽可能使用专门的硬件而不是GPU进行合成。

GPU(Client合成)和HWC(Client合成)两种方式对比:

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

Note:

  1. Alpha处理: 图片的透明度(0~255或者0.0f~1.0f),数值越小透明度越高
  2. DRM内容处理:(Digital Rights Management)一种业界使用广泛的数字内容版权保护技术。

HWC常规准则

Hardware Composer抽象层后的物理显示设备硬件可因设备而异。但是一般来说,遵循以下规则:

  1. HWC应至少支持4个叠加层(状态栏、系统栏、应用、壁纸/背景)
  2. 层可以大于屏幕,因此HWC应能处理大于显示屏的层(例如壁纸)
  3. 应该同时支持预乘每个像素Alpha混合和每个平面Alpha混合
  4. HWC应能够处理GPU、Camera、视频解码器(Video Decoder)生成的相同缓冲区,因此支持以下某些属性会很有帮助:
    • RGBA打包顺序
    • YUV格式
    • Tiling,swizzling和步幅属性
  1. 为了支持受保护的内容(Secure layer),必须提供受保护视频播放的硬件路径

Note:

  1. RGBA是一种颜色值
  2. YUV是一种颜色编码格式,可以说YUV流媒体是原始流数据,大部分的视频领域都在使用。他与RGB类似,但RGB更多的用于渲染时,而YUV则用在数据传输,因为它占用更少的频宽。当然,实时通讯为了降低带宽都会采用H264/H265编码。从字面意思理解,YUV的含义:Y代表亮度信息(灰度),UV分别代表色彩信息。YUV的常用名称有许多,如YUV422这是大部分镜头出来的数据,还有许多(yuv420,yuv444等)
  3. Tiling简单来说就是将image进行切割,切成M * N小块,最后用的时候再进行拼接,类似铺瓷砖
  4. swizzling是一种拌和技术,这是向量的单元可以被任意的重新排放或重复

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

为常见的用例做准备,比如:

  • 纵向和横向模式下的全屏游戏
  • 带着字幕和播放控件的全屏视频
  • 主屏幕(状态栏、系统栏目、应用、动态壁纸)
  • 受保护的视频播放
  • 多显示设备支持

HWC2框架

从Android 8.0开始的Treble项目,对Android架构做了调整,让制造商以更低的成本更加轻松快速的将设备更新到Android系统。这就对HAL层有了很大的调整,利用提供给Vendor的接口,将Vendor的实现和Android上层分离开来。

这样的架构也使得HWC架构变得复杂,HWC属于Binderized的HAL类型。Binderized类型的HAL将上层Android和底层HAL分别采用两个不同的进程实现,中间采用Binder进行通信,为了和前面的Binder进行区别,这里采用HWBinder

可以将HWC分为以下几个部分:

  • Binder 1:

    • SurfaceFlinger Service
    • HWC2 Client
  • Binder 2:

    • HWC2 Server
    • HWC2 Vendor Impl

具体解释:

  1. Client端:Client就是指SurfaceFlinger。不过SurfaceFlinger采用前后端设计,以后和HWC相关的逻辑应该会放到后端(SurfaceFlingerBE),即/frameworks/native/services/surfaceflinger/
  2. HWC Client端: 这一部分属于SurfaceFlinger进程,直接用过Binder通信,和HWC2的HAL Server交互。在SurfaceFlinger中采用namespace HWC2的命名空间,即frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
  3. HWC2 Server端: 这里将建立一个进程实现HWC的Server端。服务端再调用底层Vendor的具体实现。并且,对于底层合成的实现不同,此处会做一些适配(适配HWC1.x),和FrameBuffer的实现。这部分包含三部分:接口、实现、服务,以动态库的形式存在:(hardware/interfaces/graphics/composer/2.1/default/
  1. HWC Vendor实现: 这部分是HWC的具体实现,由硬件厂商完成,(例如高通QCOM),代码一般是hardware/qcom/display/。HWC必须采用Binderized HAL模式,但是不一定要实现HWC2的HAL版本。HWC2的实现需要配置,以Android 8.0为例,包含:
    • 添加宏定义TARGET_USERS_HWC2
    • 编译打包HWC2相关的so库
    • SELinux相关的权限添加
    • 配置manifest.xml
      1
      2
      3
      4
      5
      6
      7
      8
      9
      <hal format="hidl">
      <name>android.hardware.graphics.composer</name>
      <transport>hwbinder</transport>
      <version>2.1</version>
      <interface>
      <name>IComposer</name>
      <instance>default</instance>
      </interface>
      </hal>

HWC2数据结构

  1. HWC2的一些常用接口定义在头文件hardware/libhardware/include/hardware/hwcomposer2.h中,一些共用的数据定义是HAL的接口中:
  • hardware/interfaces/graphics/common/1.0/
  • hardware/interfaces/graphics/composer/2.1/

图层Layer

每个Layer都有一组属性,用来定义和其他Layer的交互方式。他在每一个模块(层)代码定义的实现不一样,但是Layer的理念是一样的。

  • SurfaceFlinger中

    1
    2
    3
    4
    5
    6
    7
    8
    frameworks/native/services/surfaceflinger
    ├── Layer.h
    ├── Layer.cpp
    ├── ColorLayer.h
    ├── ColorLayer.cpp
    ├── BufferLayer.h
    └── BufferLayer.cpp
    |__ ...
  • HWC2中

1
2
3
frameworks/native/services/surfaceflinger/DisplayHardware
├── HWC2.h
└── HWC2.cpp
  • 在HAL中实现时,定义为hwc2_layer_t,是在头文件hwcomposer2.h中定义的:typedef uint64_t hwc2_layer_t;
  • HIDL中定义为Layer,这个Layer和hwc2_layer_t是一样的:typedef uint64_t Layer;

Layer按照类型划分

大致分为BufferLayerCOlorLayer(在SF中createLayer中),BufferLayer就是有Buffer的Lyaer(Bufferueue,GraphicsBuffer),需要上层应用Producer生长;ColorLayer可以绘制一种制定的颜色和透明度Alpha(取代之前的Dim Layer)。

Layer按照数据划分

大致分为RGB LayerYUV Layer,前者是RGB格式,比较常见的就是UI界面的数据;后者的Buffer是YUV类型的,平常播放Video,Camera预览等,都是YUV类型的。

Layer属性*

Layer的属性定义他和其他模块(层)的关系,和显示屏(DeisplayDevice)的关系等。Layer包含的属性类别如下(上述也有部分内容):

位置属性

定义层在其显示设备上的现实位置,包含层边缘的位置和其相对于其他层的Z-Order等,并且还定义了很多个区域Region

frameworks/native/services/surfaceflinger/Layer.h
1
2
3
4
5
6
7
8
9
class Layer : public virtual RefBase {
... ...
public:
... ...
// regions below are in window-manager space
Region visibleRegion;
Region coveredRegion;
Region visibleNonTransparentRegion;
Region surfaceDamageRegion;

Region中是很多个Rect的集合,即一个Layer的visibleRegion可能是几个Rect的集合(rect对象用来存储一个矩形框的左上角坐标、宽度和高度。描述矩形的宽度、高度和原点)

SurfaceFlinger中定义的Region都是从上层(WMS)传递过来的。而在HWC中,是用的下面的结构描述:

hardware/libhardware/include/hardware/hwcomposer_defs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

typedef struct hwc_color {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} hwc_color_t;

typedef struct hwc_float_color {
float r;
float g;
float b;
float a;
} hwc_float_color_t;

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;
  • Transform,这个在SurfaceFlinger中定义的一个重要的结构,意思是变换矩阵,是一个3*3的矩阵。

联系流程:
Rect <- Region <- Layer <- State <- Geometry <- Transform <- mat33

  • Layer的两个状态:mCurrentState和mDrawingState,前者是给SurfaceFlinger的前段准备数据,后者是将数据给到合成。每个状态有两个Geometry的描述request(上层请求的)和active(当前正在使用的)。每个Geometry中有一个Transform矩阵,一个Transform包含一个mat33的整列。

Transform中包含两部分,一部分是位置Postion,另一部分是真正的2D的变换矩阵。通过下面两个函数设置:(对应Layer中的setPostion和setMatrix函数,这是上层WMS设置下来的)

frameworks/native/libs/ui/Transform.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Transform::set(float tx, float ty)
{
mMatrix[2][0] = tx;
mMatrix[2][1] = ty;
mMatrix[2][2] = 1.0f;

if (isZero(tx) && isZero(ty)) {
mType &= ~TRANSLATE;
} else {
mType |= TRANSLATE;
}
}

void Transform::set(float a, float b, float c, float d)
{
mat33& M(mMatrix);
M[0][0] = a; M[1][0] = b;
M[0][1] = c; M[1][1] = d;
M[0][2] = 0; M[1][2] = 0;
mType = UNKNOWN_TYPE;
}
......

内容属性

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

frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
struct 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};

// The buffer cache for this layer. This is used to lower the
// cost of sending reused buffers to the HWC.
HwcBufferCache hwcBufferCache;
};

// The HWC state is optional, and is only set up if there is any potential
// HWC acceleration possible.
std::optional<Hwc> hwc;

// Debugging
void dump(std::string& result) const;
};

关系图:

Layer显示结构图

解释:

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

注意: 这里之所以说简单的认为,这是因为HWC空间的区域大小是SurfaceFlinger空间的区域经过缩放,经过Transform旋转,移动等后才得出的,要是混淆了就理解不对了。

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

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

hardware/libhardware/include/hardware/hwcomposer2.h
1
2
3
4
5
6
7
8
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,
};

释义:

  1. Client 相对HWC2硬件合成的概念,主要是处理BufferLayer数据,用GPU处理。
  2. Device HWC2硬件设备,主要处理BufferLayer数据,用HWC处理
  3. SolidColor 固定颜色合成,主要处理ColorLayer数据,用HWC处理或GPU处理。
  4. Cursor 鼠标标识合成,主要处理鼠标等图标,用HWC处理或GPU处理
  5. Sideband Sideband为视频的边频带,一般需要需要硬件合成器作特殊处理,但是也可以用GPU处理。

在合成信息HWCInfo中,包含成的类型。通过Layer的setCompositionType方法进行指定:

frameworks/native/services/surfaceflinger/Layer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
if (getBE().mHwcLayers.count(hwcId) == 0) {
ALOGE("setCompositionType called without a valid HWC layer");
return;
}
auto& hwcInfo = getBE().mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
static_cast<int>(callIntoHwc)); //默认true
if (hwcInfo.compositionType != type) {
ALOGV(" actually setting");
hwcInfo.compositionType = type;
if (callIntoHwc) {
auto error = hwcLayer->setCompositionType(type); //合成方式
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set "
"composition type %s: %s (%d)",
mName.string(), to_string(type).c_str(), to_string(error).c_str(),
static_cast<int32_t>(error));
}
}
}

确定合成类型分成三步:

  1. SurfaceFlinger制定合成类型,此时callIntoHwc=true,将类型制定给HWC
  2. HWC根据实际情况看SurfaceFlinger制定的合成类型是否可以执行,如果不满足,作出修改
  3. SurfaceFlinger根据HWC的修改情况再作出调整,最终确认合成类型,此时callIntoHwc=false

优化属性

提供一些非必须的参数,以供HWC进行合成的优化。包括层的可见区域以及层的哪个部分自上一帧以来已经更新等信息。也就是前面说到的visibleRegion,damageRegion等。

小结

本篇主要是SurfaceFlinger概述,和HWC2的概述,还有Layer的属性和类型,合成方式的内容。
另外还有关于HWC的内容,和Display显示设备的信息重新划分单独的一篇学习。

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2020 sunwengang
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信