Android P加载Composer:
SurfaceFlingerBE封装了HWComposer,处理与HAL层的业务相关业务。SurfaceFlingerBE的mComposerSequenceId代表当前
使用的HWComposer的类型,0为正常SurfaceFlinger使用,1为VR使用,并且只能使用一个显示相关的HAL层。
1、初始化时先构造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()。
2,屏幕个数在hwcomposerdefs.h中定义:
/* Display types and associated mask bits. */
enum {
HWC_DISPLAY_PRIMARY = 0,
HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc.
HWC_DISPLAY_VIRTUAL = 2,
HWC_NUM_PHYSICAL_DISPLAY_TYPES = 2,
HWC_NUM_DISPLAY_TYPES = 3,
};
根据此来创建VSYNC信息资源。 并且在HWComposer类的成员std::vector<DisplayData> mDisplayData;被默认初始元素个数为2。
3,HAL层调用流程 Composer::Composer类的构造函数中通过IComposer::getService()加载HAL层实现,在Treble项目中会有宏HIDL_FETCH_×××××,其中XXXXX表示的为具体的HIDL脚本中的声名,这里即(HIDL_FETCH_IComposer),HIDL_FETCH_IComposer的实现是在composer/2.1/default/Hwc.cpp中,可以看到HwcHal(即IComposer)。HwcHal的构造函数调用了vendor类实现的HAL接口,获取到hw_device_t,hw_device_t定义了接口函数, HwcHal::initDispatch 用于关联 实现层hwc2_function_pointer_t ,与HAL接口的对应。调用例子如:mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount(); 先是会调用android::Hwc2::Composer的实现getMaxVirtualDisplayCount()然后会调用IComposerClient通过Binder的服务来调用ComposerClient的getMaxVirtualDisplayCount()
4,class ComposerCallbackBridge : public Hwc2::IComposerCallback 用于ComposerHAL层回调。其中onHotplug函数第一次的调用确定了主屏幕。onRefresh用于通知重画屏幕,onVsync用于通知同步信号时间(好像已经不是必须的),Android P 在接收到 onRefresh 后会根据上次的描绘重新通知onVsync信号,详细看SurfaceFlinger及MessageQueue实现的事件处理。
Android P SurfaceFlinger的事件线程:
1,SurfaceFlinger为主要线程,用于处理SurfaceFlinger接收到的事件
2,EventControlThread,就像是Vsync信号产生的闸门,当然闸门肯定需要人去打开和关闭,这个人就是SF;即控制Vsync信号的开头
3,DispSyncThread,是Vsync信号的模型,首先触发DispSyncThread,然后DispSyncThread再去驱动其他事件,它就是Vsync在SF中的代表;
4,EventThread,具体的事件线程,由DispSyncThread去驱动。EventThread线程有两个一个是用于SF的,别一个是用于APP。
Android O/P VSYNC及相关:
1、onRefresh函数会调用SurfaceFlinger::signalTransaction-->EventQueue.invalidate()并且SurfaceFlinger::signalLayerUpdate()-->EventQueue.invalidate() 最终会调用SurfaceFlinger::resyncWithRateLimit()此函数会判断上次执行是不是超过ms2ns(500) == 500毫秒,如果达到显示时长则重置同步信号,见SurfaceFlinger::resyncToHardwareVsync()。以主屏幕的同步信号来刷新屏幕,会重置DispSyncThread线程,修正使用更新周期,见DispSyncThread::updateModel() 此时如果DispSyncThread线程卡住时,mCond将会唤醒此线程。
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mReferenceTime = referenceTime;
ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
" mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
ns2us(mPhase), ns2us(mReferenceTime));
mCond.signal();
}
注:在HWC2::Device类在Device::onHotplug()收到HAL层新的设备时会创建HWC2::Display对像用于保存显示相关的信息,主要是使用std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;来保存显示屏幕的配置信息。详见HWC2::Display::Config
Android P 图形显示系统 https://blog.csdn.net/chaojiangluo/article/details/81475607
- 显示周期Vsync
设备显示会按一定速率刷新,在手机和平板电脑上通常为每秒 60 帧。如果显示内容在刷新期间更新,则会出现撕裂现象;因此,请务必只在周期之间更新内容。在可以安全更新内容时,系统便会收到来自显示设备的信号。由于历史原因,我们将该信号称为 VSYNC 信号。
刷新率可能会随时间而变化,例如,一些移动设备的刷新率范围在 58 fps 到 62 fps 之间,具体要视当前条件而定。对于连接了 HDMI 的电视,刷新率在理论上可以下降到 24 Hz 或 48 Hz,以便与视频相匹配。由于每个刷新周期只能更新屏幕一次,因此以 200 fps 的刷新率为显示设备提交缓冲区只是在做无用功,因为大多数帧永远不会被看到。SurfaceFlinger 不会在应用提交缓冲区时执行操作,而是在显示设备准备好接收新的缓冲区时才会唤醒。
当 VSYNC 信号到达时,SurfaceFlinger 会遍历它的层列表,以寻找新的缓冲区。如果找到新的缓冲区,它会获取该缓冲区;否则,它会继续使用以前获取的缓冲区。SurfaceFlinger 总是需要可显示的内容,因此它会保留一个缓冲区。如果在某个层上没有提交缓冲区,则该层会被忽略。
- 合成方式
目前SurfaceFlinger中支持两种合成方式,一种是Device合成,一种是Client合成。SurfaceFlinger 在收集可见层的所有缓冲区之后,便会询问 Hardware Composer 应如何进行合成。
-
Client合成
Client合成方式是相对与硬件合成来说的,其合成方式是,将各个Layer的内容用GPU渲染到暂存缓冲区中,最后将暂存缓冲区传送到显示硬件。这个暂存缓冲区,我们称为FBTarget,每个Display设备有各自的FBTarget。Client合成,之前称为GLES合成,我们也可以称之为GPU合成。Client合成,采用RenderEngine进行合成。 -
Device合成
就是用专门的硬件合成器进行合成HWComposer,所以硬件合成的能力就取决于硬件的实现。其合成方式是将各个Layer的数据全部传给显示硬件,并告知它从不同的缓冲区读取屏幕不同部分的数据。HWComposer是Devicehec的抽象。
SurfaceFlinger与HIDL
HIDl请参考https://source.android.google.cn/devices/architecture/hidl
关于HIDL的修改,可以增加接口但请注意以下事项:
允许的更改 |
|
---|---|
不允许的更改 |
|
......