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

论坛 期权论坛     
选择匿名的用户   2021-5-22 22:12   7   0
<span style="color:#FF6666;">文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。<br>转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/<br><br>GUI系统之SurfaceFlinger章节目录:<br>blog.csdn.net/uiop78uiop78/article/details/8954508</span>
<br>
<p><br></p>
<p></p>
<h2><a name="_Toc356900114">1.1 VSync</a>的产生和处理</h2>
<p></p>
<p>前面小节ProjectButter中我们学习了Android 4.1显示系统中的新特性,其中一个就是加入了VSync同步。我们从理论的角度分析了采用这一机制的必要性和运作机理,那么SurfaceFlinger具体是如何实施的呢?</p>
<p>先来想一下有哪些东西要考虑:</p>
<p>·          VSync信号的产生和分发</p>
<p>如果有硬件主动发出这一信号,那是最好的了;否则就得通过软件定时模拟来产生</p>
<p>·          VSync信号的处理</p>
<p>当信号产生后,SurfaceFlinger如何在最短的时间内响应,具体处理流程是怎么样子的</p>
<h3><a name="_Toc356900115">1.1.1 VSync</a>信号的产生和分发</h3>
<p>在Android源码surfaceflinger目录下有一个displayhardware文件夹,其中HWComposer的主要职责之一,就是用于产生VSync信号。</p>
<div style="background:#BFBFBF;">
<p>/*frameworks/native/services/surfaceflinger/displayhardware/HWComposer.cpp*/</p>
<p>HWComposer::HWComposer(const sp&lt;SurfaceFlinger&gt;&amp; flinger,EventHandler&amp; handler, nsecs_t refreshPeriod)</p>
<p style="background:#BFBFBF;">: mFlinger(flinger), <span style="background:gray;">mModule</span>(0), <span style="background:gray;">mHwc</span>(0), mList(0), mCapacity(0),mNumOVLayers(0),</p>
<p style="background:#BFBFBF;"> mNumFBLayers(0), mDpy(EGL_NO_DISPLAY),mSur(EGL_NO_SURFACE),</p>
<p>      <span style="background:gray;">mEventHandler</span>(handler),mRefreshPeriod(refreshPeriod),</p>
<p>      mVSyncCount(0),mDebugForceFakeVSync(false)</p>
<p>{<!-- --></p>
<p>    charvalue[PROPERTY_VALUE_MAX];</p>
<p>   property_get(&#34;debug.sf.no_hw_vsync&#34;, value, &#34;0&#34;); //系统属性</p>
<p>    mDebugForceFakeVSync &#61;atoi(value);</p>
<p>    bool needVSyncThread &#61;false;//是否需要软件模拟VSync</p>
<p>    int err &#61; <span style="background:gray;">hw_get_module</span>(HWC_HARDWARE_MODULE_ID, &amp;mModule);//加载HAL模块</p>
<p>    if (err &#61;&#61; 0) {<!-- --></p>
<p>        err &#61; <span style="background:gray;">hwc_open</span>(mModule, &amp;mHwc);//打开module</p>
<p>        if (err &#61;&#61; 0) {<!-- --></p>
<p style="background:#BFBFBF;">if(mHwc-&gt;registerProcs) { //注册硬件设备事件回调</p>
<p>                mCBContext.hwc&#61; this;</p>
<p>               mCBContext.procs.invalidate &#61; &amp;hook_invalidate;</p>
<p>               mCBContext.procs.vsync &#61; &amp;hook_vsync;</p>
<p>                mHwc-&gt;<span style="background:gray;">registerProcs</span>(mHwc, &amp;mCBContext.procs);</p>
<p>               memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));</p>
<p>            }</p>
<p>            if(mHwc-&gt;common.version &gt;&#61; HWC_DEVICE_API_VERSION_0_3) {<!-- --></p>
<p>                if(mDebugForceFakeVSync) {//用于调试</p>
<p>                   mHwc-&gt;methods-&gt;eventControl(mHwc, HWC_EVENT_VSYNC, 0);</p>
<p>                }</p>
<p>            } else {//有可能支持VSync的硬件模块是这个版本以后才加入的,老版本仍然需要软件模拟</p>
<p>               needVSyncThread &#61; true;</p>
<p>            }</p>
<p>        }</p>
<p>    } else {<!-- --></p>
<p>        needVSyncThread &#61;true; //硬件模块打开失败,只能用软件模拟</p>
<p>    }</p>
<p>    if (needVSyncThread) {<!-- --></p>
<p>        mVSyncThread &#61; new <span style="background:gray;">VSyncThread</span>(*this);//创建一个产生VSync信号的线程</p>
<p>    }</p>
<p>}</p>
</div>
<p>这个函数的核心就是决定VSync的“信号发生源”——硬件或者软件模拟。</p>
<p>假如当前系统可以成功加载HWC_HARDWARE_MODULE_ID&#61;“hwcomposer”,并且通过这个库模块能顺利打开设备(hwc_composer_device_t),其版本号又大于HWC_DEVICE_API_VERSION_0_3的话,我们就采用“硬件源”(此时needVSyncThread为false),否则需要创建一个新的VSync线程来模拟产生信号。</p>
<p>(1)硬件源</p>
<p>如果mHwc-&gt;registerProcs不为空的话,我们注册硬件回调mCBContext.procs。定义如下:</p>
<p>    struct cb_context{<!-- --></p>
<p>        callbacksprocs;</p>
<p>        HWComposer*hwc;</p>
<p>    };</p>
<p>调用registerProcs()时,传入的参数是&amp;mCBContext.procs。后期当有事件产生时,比如vsync或者invalidate,硬件模块将分别通过procs.vsync和procs.invalidate来通知HWComposer。</p>
<div style="background:#BFBFBF;">
<p>void HWComposer::hook_vsync(struct hwc_procs* procs, int dpy,int64_t timestamp) {<!-- --></p>
<p>   reinterpret_cast&lt;cb_context *&gt;(procs)-&gt;hwc-&gt;vsync(dpy,timestamp);</p>
<p>}</p>
</div>
<p>上面这个函数中,procs即前面的&amp;mCBContext.procs,从指针地址上看它和&amp;mC
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP