GUI系统之SurfaceFlinger(12)VSync信号的产生和处理

文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。转载请注明:From LXS. GUI系统之SurfaceFlinger章节目录:blog.csdn.net/uiop78uiop78/article/details/8954508

1.1 VSync的产生和处理

前面小节ProjectButter中我们学习了Android 4.1显示系统中的新特性,其中一个就是加入了VSync同步。我们从理论的角度分析了采用这一机制的必要性和运作机理,那么SurfaceFlinger具体是如何实施的呢?

先来想一下有哪些东西要考虑:

·VSync信号的产生和分发

如果有硬件主动发出这一信号,那是最好的了;否则就得通过软件定时模拟来产生

·VSync信号的处理

当信号产生后,SurfaceFlinger如何在最短的时间内响应,具体处理流程是怎么样子的

1.1.1 VSync信号的产生和分发

在Android源码surfaceflinger目录下有一个displayhardware文件夹,其中HWComposer的主要职责之一,就是用于产生VSync信号。

/*frameworks/native/services/surfaceflinger/displayhardware/HWComposer.cpp*/

HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger,EventHandler& handler, nsecs_t refreshPeriod)

: mFlinger(flinger), mModule(0), mHwc(0), mList(0), mCapacity(0),mNumOVLayers(0),

mNumFBLayers(0), mDpy(EGL_NO_DISPLAY),mSur(EGL_NO_SURFACE),

mEventHandler(handler),mRefreshPeriod(refreshPeriod),

mVSyncCount(0),mDebugForceFakeVSync(false)

{

charvalue[PROPERTY_VALUE_MAX];

property_get("debug.sf.no_hw_vsync", value, "0"); //系统属性

mDebugForceFakeVSync =atoi(value);

bool needVSyncThread =false;//是否需要软件模拟VSync

int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);//加载HAL模块

if (err == 0) {

err = hwc_open(mModule, &mHwc);//打开module

if (err == 0) {

if(mHwc->registerProcs) { //注册硬件设备事件回调

mCBContext.hwc= this;

mCBContext.procs.invalidate = &hook_invalidate;

mCBContext.procs.vsync = &hook_vsync;

mHwc->registerProcs(mHwc, &mCBContext.procs);

memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));

}

if(mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {

if(mDebugForceFakeVSync) {//用于调试

mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);

}

} else {//有可能支持VSync的硬件模块是这个版本以后才加入的,老版本仍然需要软件模拟

needVSyncThread = true;

}

}

} else {

needVSyncThread =true; //硬件模块打开失败,只能用软件模拟

}

if (needVSyncThread) {

mVSyncThread = new VSyncThread(*this);//创建一个产生VSync信号的线程

}

}

这个函数的核心就是决定VSync的“信号发生源”——硬件或者软件模拟。

假如当前系统可以成功加载HWC_HARDWARE_MODULE_ID=“hwcomposer”,并且通过这个库模块能顺利打开设备(hwc_composer_device_t),其版本号又大于HWC_DEVICE_API_VERSION_0_3的话,我们就采用“硬件源”(此时needVSyncThread为false),否则需要创建一个新的VSync线程来模拟产生信号。

(1)硬件源

如果mHwc->registerProcs不为空的话,我们注册硬件回调mCBContext.procs。定义如下:

struct cb_context{

callbacksprocs;

HWComposer*hwc;

};

调用registerProcs()时,传入的参数是&mCBContext.procs。后期当有事件产生时,比如vsync或者invalidate,硬件模块将分别通过procs.vsync和procs.invalidate来通知HWComposer。

void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy,int64_t timestamp) {

reinterpret_cast<cb_context *>(procs)->hwc->vsync(dpy,timestamp);

}

上面这个函数中,procs即前面的&mCBContext.procs,从指针地址上看它和&mCBContext是一致的,因而我们可以强制类型转换为cb_context来进行操作,并由此访问到hwc中的vsync实现:

void HWComposer::vsync(int dpy, int64_t timestamp) {

mEventHandler.onVSyncReceived(dpy, timestamp);

}

HWComposer将VSync信号直接通知给mEventHandler,这个Handler由HWComposer构造时传入,换句话说,我们需要看下是谁创建了HWComposer。

/*frameworks/native/services/surfaceflinger/displayhardware/DisplayHardware.cpp*/

void DisplayHardware::init(uint32_t dpy)

{…

mHwc = newHWComposer(mFlinger, *this, mRefreshPeriod);

从这里可以看出来,HWComposer中的mEventHandler就是DisplayHardware对象,所以后者必须要继承自HWComposer::EventHandler,以此处理产生的onVSyncReceived事件。

(2)软件源

青春气贯长虹,勇敢盖过怯懦,进取压倒苟安。

GUI系统之SurfaceFlinger(12)VSync信号的产生和处理

相关文章:

你感兴趣的文章:

标签云: