sunwengang blog

developer | android display/graphics

  1. 1. SurfaceFlinger概述
    1. 1.1. SurfaceFlinger类定义
    2. 1.2. ISurfaceComposer接口实现
    3. 1.3. ComposerCallback接口实现
    4. 1.4. mCurrentState和mDrawingState
  2. 2. 硬件合成HWC2概述
    1. 2.1. HWC常规准则
    2. 2.2. HWC2框架
    3. 2.3. HWC2数据结构
    4. 2.4. 图层Layer
      1. 2.4.1. Layer按照类型划分
      2. 2.4.2. Layer按照数据划分
    5. 2.5. Layer属性*
      1. 2.5.1. 位置属性
      2. 2.5.2. 内容属性
      3. 2.5.3. 合成属性(确认用哪种合成方式)
      4. 2.5.4. 优化属性
  3. 3. 小结

转载夕月风大佬博客: 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显示设备的信息重新划分单独的一篇学习。

本文作者 : sunwengang
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://alonealive.github.io/Blog/2019/12/22/2019/191222_android_HWC2/

本文最后更新于 天前,文中所描述的信息可能已发生改变