博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android SurfaceFlinger服务(五) ----- VSync信号的产生
阅读量:4963 次
发布时间:2019-06-12

本文共 6309 字,大约阅读时间需要 21 分钟。

Android为了增强界面流畅度引入了VSync机制。VSync信号一般由硬件产生,为了兼容一些老的机器,也可以软件产生。因些,就可以分为硬件VSync和软件VSync。VSync的生成逻辑主要在HWComposer里面。相关文件如下:

  • frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
  • frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.h

HWComposer在SurfaceFlinger的init函数里创建:

void SurfaceFlinger::init() {    ALOGI(  "SurfaceFlinger's main thread ready to run. "            "Initializing graphics H/W...");    ......    // Initialize the H/W composer object.  There may or may not be an    // actual hardware composer underneath.    mHwc = new HWComposer(this,            *static_cast
(this)); ...... }
  • SurfaceFlinger成员变量保存了HWComposer对象指针
  • 创建HWComposer时,使用SurfaceFlinger作为参数传入
HWComposer::HWComposer(        const sp
& flinger, EventHandler& handler) : mFlinger(flinger), mFbDev(0), mHwc(0), mNumDisplays(1), mCBContext(new cb_context), mEventHandler(handler), mDebugForceFakeVSync(false){ ...... bool needVSyncThread = true; // Note: some devices may insist that the FB HAL be opened before HWC. int fberr = loadFbHalModule(); loadHwcModule(); ....... if (mHwc) { ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER, (hwcApiVersion(mHwc) >> 24) & 0xff, (hwcApiVersion(mHwc) >> 16) & 0xff); if (mHwc->registerProcs) { mCBContext->hwc = this; mCBContext->procs.invalidate = &hook_invalidate; mCBContext->procs.vsync = &hook_vsync; if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) mCBContext->procs.hotplug = &hook_hotplug; else mCBContext->procs.hotplug = NULL; memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero)); mHwc->registerProcs(mHwc, &mCBContext->procs); } // don't need a vsync thread if we have a hardware composer needVSyncThread = false; // always turn vsync off when we start eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); ...... } ...... if (needVSyncThread) { // we don't have VSYNC support, we need to fake it mVSyncThread = new VSyncThread(*this); }}
  • 在构造函数里把SurfaceFlinger对象指针赋值给成员变量mFlinger和mEventHandler
  • 首先尝试加载HWC模块,如果加载成功就使用硬件vsync,加载失败就使用软件模拟vsync

在加载HWC硬件模块时,会注册vsync回调函数HWComposer::hook_vsync。当硬件vsync到来时会调用些函数。代码如下:

void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,        int64_t timestamp) {    cb_context* ctx = reinterpret_cast
( const_cast
(procs)); ctx->hwc->vsync(disp, timestamp);}
  • 调用hwc对象的vsync函数
void HWComposer::vsync(int disp, int64_t timestamp) {     if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {                                                                                                                                           {            Mutex::Autolock _l(mLock);                                                                                                                                                                   // There have been reports of HWCs that signal several vsync events            // with the same timestamp when turning the display off and on. This            // is a bug in the HWC implementation, but filter the extra events            // out here so they don't cause havoc downstream.            if (timestamp == mLastHwVSync[disp]) {                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",                                                                                                                                     timestamp);                            return;            }            mLastHwVSync[disp] = timestamp;                                                                                                                                                          }        char tag[16];        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);                                                                                                                                                   mEventHandler.onVSyncReceived(disp, timestamp);                                                                                                                                          }  }
  • 最终调用mEventHandler的onVSyncReceived函数,也既SurfaceFlinger的onVSyncReceived

软件vsync在VSyncThread线程中实现,看看线程循环函数:

bool HWComposer::VSyncThread::threadLoop() {    { // scope for lock        Mutex::Autolock _l(mLock);             while (!mEnabled) {            mCondition.wait(mLock);            }    }      const nsecs_t period = mRefreshPeriod;    const nsecs_t now = systemTime(CLOCK_MONOTONIC);    nsecs_t next_vsync = mNextFakeVSync;    nsecs_t sleep = next_vsync - now;     if (sleep < 0) {        // we missed, find where the next vsync should be        sleep = (period - ((now - next_vsync) % period));         next_vsync = now + sleep;      }      mNextFakeVSync = next_vsync + period;                                                                                                                                                        struct timespec spec;    spec.tv_sec  = next_vsync / 1000000000;    spec.tv_nsec = next_vsync % 1000000000;                                                                                                                                                      int err;    do {        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);                                                                                                                      } while (err<0 && errno == EINTR);                                                                                                                                                           if (err == 0) {        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);                                                                                                                                       }      return true;}
  • 以固定的时间间隔发送vsync信号
  • 调用mEventHandler的onVSyncReceived函数,最终调用SurfaceFlinger的onVSyncReceived函数。
  • 这样不管是硬件vsync还是软件vsync都达成了统一。当VSync信号产生时调用SurfaceFlinger的回调函数onVSyncReceived。

转载于:https://www.cnblogs.com/qzhang1535/p/9228434.html

你可能感兴趣的文章
synchronized的原理,以及其中的偏向锁
查看>>
数组笔记
查看>>
根据枚举获取枚举的Description特性值
查看>>
26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展
查看>>
5. javascript OOP编程:封装、继承--从零起步实现基于Html5的WEB设计器Jquery插件(含源码)...
查看>>
不断更新的 ToDo-List
查看>>
catalan数
查看>>
二叉树的深度优先遍历与广度优先遍历
查看>>
2016工作计划
查看>>
python利用socket传输文件
查看>>
JavaEEMybatis基础整理
查看>>
剑指offer(41)和为S的连续正数序列
查看>>
IOS-UI-UILable
查看>>
bzoj1345
查看>>
对员工宽容的公司 都死掉了
查看>>
python基础五
查看>>
BZOJ 1013: [JSOI2008]球形空间产生器sphere
查看>>
DevExpress TreeList添加右键菜单问题
查看>>
AEAI Portal V3.5.2门户集成平台发版说明
查看>>
[转]我们这么努力,也不过是为了成为一个普通人。
查看>>