一、Vsync简介:

  屏幕的刷新过程是每一行从左到右(行刷新,水平刷新,Horizontal Scanning),从上到下(屏幕刷新,垂直刷新,Vertical Scanning)。当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,此时发出 VSync 信号。所以,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。

  Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,VSync是Vertical Synchronization(垂直同步)的缩写,是一种在PC上很早就广泛使用的技术,可以简单的把它认为是一种定时中断。而在Android 4.1(JB)中已经开始引入VSync机制,用来同步渲染,让AppUI和SurfaceFlinger可以按硬件产生的VSync节奏进行工作。

二、黄油计划:三个方法改进显示系统

1.Vsync同步:

  

  可见vsync信号没有提醒CPU/GPU工作的情况下,第二次vsync到来需要显示内容时,CPU和GPU还没有来得及准备好下一帧的数据,所以只能接着显示上一帧的数据,产生Jank!

  CPU/GPU接收vsync信号提前准备下一帧要显示的内容,所以能够及时准备好每一帧的数据,保证画面的流程。

 2.多级缓冲:

  除了Vsync的机制,Android还使用了多级缓冲的手段以优化UI流程度,例如双缓冲(A+B),在显示buffer A的数据时,CPU/GPU就开始在buffer B中准备下一帧数据:

  

  

  但是不能保证每一帧CPU、GPU都运行状态良好,可能由于资源抢占等性能问题导致某一帧GPU掉链子,vsync信号到来时buffer B的数据还没准备好,而此时Display又在显示buffer A的数据,导致后面CPU/GPU没有新的buffer着手准备数据,空白时间无事可做,后面Jank频出:

  

  因此用三级缓冲来提高系统对性能波动的容忍度:

  

  虽然GPU在准备buffer B的数据耗时过长,第二帧Jank,但是新增1个buffer可以减少CPU和GPU在vsync同步间的空白间隙,此时CPU/GPU能够利用buffer C继续工作,所以后面就不会再产生Jank了,当然具体使用多少个buffer要根据实际硬件性能情况调整,最终目的就是解决Display的Jank产生。

 3.Vsync虚拟化(Vsync App + Vsync SurfaceFlinger):

  虽然vsync使得CPU/GPU/Display同步了,但App UI和SurfaceFlinger的工作显然是一个流水线的模型。即对于一帧内容,先等App UI画完了,SurfaceFlinger再出场对其进行合并渲染后放入framebuffer,最后整到屏幕上。而现有的VSync模型是让大家一起开始干活,这样对于同一帧内容,第一个VSync信号时App UI的数据开始准备,第二个VSync信号时SurfaceFlinger工作,第三个VSync信号时用户看到Display内容,这样就两个VSync period(每个16ms)过去了,影响用户体验。
  解决思路:SurfaceFlinger在App UI准备好数据后及时开工做合成。

  Android 4.4(KitKat)引入了VSync的虚拟化,即把硬件的VSync信号先同步到一个本地VSync模型中,再从中一分为二,引出两条VSync时间与之有固定偏移的线程。示意图如下:

  

  这样,大家工作既保持一定的节拍,又可以相互错开,一前一后保持着流水节奏。

  注意其中两个Phase offset参数(即VSYNC_EVENT_PHASE_OFFSET_NS和SF_VSYNC_EVENT_PHASE_OFFSET_NS)是可调的。

  处理流程:

  

  类型DispSync表示了一个基于硬件VSync信号的同步模型,它会根据从HWComposer来的硬件VSync信号的采样来进行同步。其它两个EventThread分别用了两个不同的虚拟VSync信号源(用DispSyncSource表示,其中包含了与真实VSync信号的偏移值),这两个VSync信号源就是被虚拟出来分别用于控制App UI和SurfaceFlinger渲染。在EventThread的线程循环中,如果有需要就会向DispSync注册相应的listener。DispSyncThread就像乐队鼓手一样控制着大家的节奏。它在主循环中会先通过已经向DispSync注册的listener计算下一个要产生的虚拟VSync信号还要多久,等待相应时间后就会调用相应listener的callback函数。这样,对于那些注册了listener的监听者来说,就好像被真实的VSync信号控制着一样。至于EventControlThread是用来向真实的VSync硬件发命令。

三、Vsync框架

 1.硬件或者软件创建vsyncThread产生vsync。
 2.DispSyncThread处理vsync,把vsync虚拟化成vsync-app和vsync-sf。
 3.vsync-app/sf按需产生(如果App和SurfaceFlinger都没有更新请求,则休眠省电):
  APP端:APP需要更新界面时发出vsync请求给EventThread(设置connection.count>=0),DispSyncThread收到vsync信号后休眠offset,然后唤醒EventThread通知APP开始渲染。
  SF端:sf请求EventThread-sf,EventThread-sf收到vsync后通知SF可以开始合成。

                            (vsync框架图)

 4.代码分析:

  4.1 创建五个线程:SurfaceFlingerThread、DispSyncThread、EventThead-App、EventThead-SF、VsyncThread,都属于SurfaceFlinger进程:

 (1)启动SurfaceFlinger主线程:android-8.0.0_r4\frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp

  1. int main(int, char**) {
  2. startHidlServices();
  3.  
  4. signal(SIGPIPE, SIG_IGN);
  5. // When SF is launched in its own process, limit the number of
  6. // binder threads to 4.
  7. ProcessState::self()->setThreadPoolMaxThreadCount();
  8.  
  9. // start the thread pool
  10. sp<ProcessState> ps(ProcessState::self());
  11. ps->startThreadPool();
  12.  
  13. // instantiate surfaceflinger
  14. sp<SurfaceFlinger> flinger = new SurfaceFlinger(); //其中创建了 mPrimaryDispSync 成员变量
  15.  
  16. setpriority(PRIO_PROCESS, , PRIORITY_URGENT_DISPLAY);
  17.  
  18. set_sched_policy(, SP_FOREGROUND);
  19.  
  20. // Put most SurfaceFlinger threads in the system-background cpuset
  21. // Keeps us from unnecessarily using big cores
  22. // Do this after the binder thread pool init
  23. if (cpusets_enabled()) set_cpuset_policy(, SP_SYSTEM);
  24.  
  25. // initialize before clients can connect
  26. flinger->init(); //传入mPrimaryDispSync并创建EventThread(app/sf)、HWComposer
  27.  
  28. // publish surface flinger
  29. sp<IServiceManager> sm(defaultServiceManager());
  30. sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
  31.  
  32. // publish GpuService
  33. sp<GpuService> gpuservice = new GpuService();
  34. sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
  35.  
  36. struct sched_param param = {};
  37. param.sched_priority = ;
  38. if (sched_setscheduler(, SCHED_FIFO, &param) != ) {
  39. ALOGE("Couldn't set SCHED_FIFO");
  40. }
  41.  
  42. // run surface flinger in this thread (SF的主线程)
  43. flinger->run();
  44.  
  45. return ;
  46. }

(2)new SurfaceFlinger() 时创建了成员变量 DispSync mPrimaryDispSync;  android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger.h

  1.   其中 DispSync 的构造函数会启动DispSyncThread线程:
  1. DispSync::DispSync(const char* name) :
  2. mName(name),
  3. mRefreshSkipCount(),
  4. mThread(new DispSyncThread(name)), //创建了DispSyncThread
  5. mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){
  6.  
  7. mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset;
  8. mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
  9. // set DispSync to SCHED_FIFO to minimize jitter
  10. struct sched_param param = {};
  11. param.sched_priority = ;
  12. if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, &param) != ) {
  13. ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
  14. }
  15.  
  16. reset();
  17. beginResync();
  18.  
  19. if (kTraceDetailedInfo) {
  20. // If we're not getting present fences then the ZeroPhaseTracer
  21. // would prevent HW vsync event from ever being turned off.
  22. // Even if we're just ignoring the fences, the zero-phase tracing is
  23. // not needed because any time there is an event registered we will
  24. // turn on the HW vsync events.
  25. if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
  26. addEventListener("ZeroPhaseTracer", , new ZeroPhaseTracer());
  27. }
  28. }
  29. }
  1. 3)接着分析SurfaceFlinger对象,它是一个strong point,在引用时会调用其onFirstRef()方法:
  1. void SurfaceFlinger::onFirstRef()
  2. {
      //初始化消息队列,其中创建了loop和handle
  3. mEventQueue.init(this);
  4. }

  flinger->run()的实现: android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp

  1. void SurfaceFlinger::run() {
  2. do {
  3. waitForEvent(); //其中就是调用mEventQueue.waitMessage()
  4. } while (true);
  5. }

  waitMessage中等待AP和EventTHread给它发数据:

  1. void MessageQueue::waitMessage() {
  2. do {
  3. IPCThreadState::self()->flushCommands();
  4. int32_t ret = mLooper->pollOnce(-);
  5. switch (ret) {
  6. case Looper::POLL_WAKE:
  7. case Looper::POLL_CALLBACK:
  8. continue;
  9. case Looper::POLL_ERROR:
  10. ALOGE("Looper::POLL_ERROR");
  11. continue;
  12. case Looper::POLL_TIMEOUT:
  13. // timeout (should not happen)
  14. continue;
  15. default:
  16. // should not happen
  17. ALOGE("Looper::pollOnce() returned unknown status %d", ret);
  18. continue;
  19. }
  20. } while (true);
  21. }

  SurfaceFlinger初始化最重要的函数是init():

  1. void SurfaceFlinger::init() {
  2. ALOGI( "SurfaceFlinger's main thread ready to run. "
  3. "Initializing graphics H/W...");
  4.  
  5. ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
  6.  
  7. { // Autolock scope
  8. Mutex::Autolock _l(mStateLock);
  9.  
  10. // initialize EGL for the default display
  11. mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  12. eglInitialize(mEGLDisplay, NULL, NULL);
  13.  
  14. // start the EventThread (创建了两个EventThread,他们的名字和offset不同)
  15. sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
  16. vsyncPhaseOffsetNs, true, "app");
  17. mEventThread = new EventThread(vsyncSrc, *this, false);
  18. sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
  19. sfVsyncPhaseOffsetNs, true, "sf");
  20. mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
  21.  
  22.      // 创建sf与EventThread之间的connection
  23. mEventQueue.setEventThread(mSFEventThread);
  24.  
  25. // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
  26. struct sched_param param = {};
  27. param.sched_priority = ;
  28. if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != ) {
  29. ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
  30. }
  31. if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != ) {
  32. ALOGE("Couldn't set SCHED_FIFO for EventThread");
  33. }
  34.  
  35. // Get a RenderEngine for the given display / config (can't fail)
  36. mRenderEngine = RenderEngine::create(mEGLDisplay,
  37. HAL_PIXEL_FORMAT_RGBA_8888);
  38. }

  其中 mEventQueue.setEventThread(mSFEventThread) 的实现:

  1. //sufaceflinger/MessageQueue.cpp
  2. void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
  3. {
  4. mEventThread = eventThread;
  5. //创建连接,从连接获得dataChannel,把它的Fd添加到Looper,
  6. //也就是把EventThread里的一个fd传给了SF线程,
  7. //以后EventThread与SF就可以通过这个fd通信,
  8. mEvents = eventTHread->createEnvetConnection();
  9. mEventTube = mEvents->getDataChannel();
  10. mLooper->addFd(mEventTube->getFd(), , Looper::EVENT_INPUT,
  11. MessageQueue::cb_eventReceiver, this); //这个cb_eventRecevier很重要,它负责处理EventThread发过来的信号
  12. }

 (4)hwcomposer的构造函数:android-8.0.0_r4\frameworks\native\services\surfaceflinger\DisplayHardware\HWComposer_hwc1.cpp

  1. HWComposer::HWComposer(
  2. const sp<SurfaceFlinger>& flinger,
  3. EventHandler& handler)
  4. : mFlinger(flinger),
  5. mFbDev(), mHwc(), mNumDisplays(),
  6. mCBContext(new cb_context),
  7. mEventHandler(handler),
  8. mDebugForceFakeVSync(false)
  9. {
  10. for (size_t i = ; i<MAX_HWC_DISPLAYS ; i++) {
  11. mLists[i] = ;
  12. }
  13.  
  14. for (size_t i= ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
  15. mLastHwVSync[i] = ;
  16. mVSyncCounts[i] = ;
  17. }
  18.  
  19. char value[PROPERTY_VALUE_MAX];
  20. property_get("debug.sf.no_hw_vsync", value, "");
  21. mDebugForceFakeVSync = atoi(value);
  22.  
  23. bool needVSyncThread = true;
  24.  
  25. // Note: some devices may insist that the FB HAL be opened before HWC.
  26. int fberr = loadFbHalModule();
  27. loadHwcModule();
  28.  
  29. if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
  30. // close FB HAL if we don't needed it.
  31. // FIXME: this is temporary until we're not forced to open FB HAL
  32. // before HWC.
  33. framebuffer_close(mFbDev);
  34. mFbDev = NULL;
  35. }
  36.  
  37. // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
  38. if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
  39. && !mFbDev) {
  40. ALOGE("ERROR: failed to open framebuffer (%s), aborting",
  41. strerror(-fberr));
  42. abort();
  43. }
  44.  
  45. // these display IDs are always reserved
  46. for (size_t i= ; i<NUM_BUILTIN_DISPLAYS ; i++) {
  47. mAllocatedDisplayIDs.markBit(i);
  48. }
  49.  
  50. if (mHwc) {
  51. ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
  52. (hwcApiVersion(mHwc) >> ) & 0xff,
  53. (hwcApiVersion(mHwc) >> ) & 0xff);
  54. if (mHwc->registerProcs) {
  55. mCBContext->hwc = this;
  56. mCBContext->procs.invalidate = &hook_invalidate;
  57. mCBContext->procs.vsync = &hook_vsync;
  58. if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
  59. mCBContext->procs.hotplug = &hook_hotplug;
  60. else
  61. mCBContext->procs.hotplug = NULL;
  62. memset(mCBContext->procs.zero, , sizeof(mCBContext->procs.zero));
  63. mHwc->registerProcs(mHwc, &mCBContext->procs);
  64. }
  65.  
  66. // don't need a vsync thread if we have a hardware composer
  67. needVSyncThread = false;
  68. // always turn vsync off when we start
  69. eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, );
  70.  
  71. // the number of displays we actually have depends on the
  72. // hw composer version
  73. if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
  74. // 1.3 adds support for virtual displays
  75. mNumDisplays = MAX_HWC_DISPLAYS;
  76. } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
  77. // 1.1 adds support for multiple displays
  78. mNumDisplays = NUM_BUILTIN_DISPLAYS;
  79. } else {
  80. mNumDisplays = ;
  81. }
  82. }
  83.  
  84. if (mFbDev) {
  85. ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
  86. "should only have fbdev if no hwc or hwc is 1.0");
  87.  
  88. DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
  89. disp.connected = true;
  90. disp.format = mFbDev->format;
  91. DisplayConfig config = DisplayConfig();
  92. config.width = mFbDev->width;
  93. config.height = mFbDev->height;
  94. config.xdpi = mFbDev->xdpi;
  95. config.ydpi = mFbDev->ydpi;
  96. config.refresh = nsecs_t(1e9 / mFbDev->fps);
  97. disp.configs.push_back(config);
  98. disp.currentConfig = ;
  99. } else if (mHwc) {
  100. // here we're guaranteed to have at least HWC 1.1
  101. for (size_t i = ; i<NUM_BUILTIN_DISPLAYS ; i++) {
  102. queryDisplayProperties(i);
  103. }
  104. }
  105.  
  106. if (needVSyncThread) {
  107. // we don't have VSYNC support, we need to fake it
         // 如果不支持硬件Vsync则创建软件vysnc线程,它是一个sp<>,其onFirstRef()真正创建运行这个线程
  108. mVSyncThread = new VSyncThread(*this);
  109. }
  110. }

  加载并准备hw composer模块。Sets mHwc

  1. void HWComposer::loadHwcModule()
  2. {
  3. hw_module_t const* module;
  4.  
  5. if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != ) {
  6. ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
  7. return;
  8. }
  9.  
  10. int err = hwc_open_1(module, &mHwc);
  11. if (err) {
  12. ALOGE("%s device failed to initialize (%s)",
  13. HWC_HARDWARE_COMPOSER, strerror(-err));
  14. return;
  15. }
  16.  
  17. if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
  18. hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
  19. hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
  20. ALOGE("%s device version %#x unsupported, will not be used",
  21. HWC_HARDWARE_COMPOSER, mHwc->common.version);
  22. hwc_close_1(mHwc);
  23. mHwc = NULL;
  24. return;
  25. }
  26. }

 4.2 SurfaceFLinger使用vsync过程

(1)App发数据给sf,sf发请求给EventThread-sf:AP是Producer,它通过listener->onFrameAvailable() ->进入消费者 -> mFrameAvailableListener(就是Layer对象) -> 进入SF线程-> mFlinger->signalLayerUpdate() -> mEventQueue.invalidate();

  1. //surfaceflinger/MessageQueue.cpp
  2. void MessageQueue::invalidate() {
  3. //mEvents是sp<IDisplayEventConnection>
  4. //也就是sf线程使用connection向EventThread线程请求下一个vsync信号
  5. mEvents->requestNextVsync();
  6. }
  7. --->
  8. //surfaceFlinger/EventThread.cpp
  9. void EventThread::Connection::requestNextVsync() {
  10. mEventThread->requestrNextVsync(this);
  11. }
  12. --->
  13. void EventTHread::requestNextVysnc(
  14. const sp<EventTHread::Connection>& connection) {
  15. if(connection->count < ){
  16. //若cnt小于0,则cnt=0,然后发出广播,来唤醒某个线程,
  17. //当connection的cnt >= 0怎么它需要从EventThread得到vsync
  18. //这个函数得代码在EventThread,但是它执行在SF线程
  19. //也就是说,SF线程使用EventThread的函数向EventThread发出广播来唤醒EventThread线程
  20. connection->count = ;
  21. mCondition.boradcast();
  22. }
  23. }

(2)EventThread-sf发请求给DispSyncThread,EventThread里面一定有一个threadLoop: android-8.0.0_r4\frameworks\native\services\surfaceflinger\EventThread.cpp

  1. bool EventThread::threadLoop() {
  2. DisplayEventReceiver::Event event;
  3. Vector< sp<EventThread::Connection> > signalConnections;
  4.  
  5.    //1,EventThread向DispSyncThread发出vsync请求
       //2,等待vsync
  6. signalConnections = waitForEvent(&event);
  7.  
  8. // dispatch events to listeners...
    const size_t count = signalConnections.size();
  9. for (size_t i= ; i<count ; i++) {
  10. const sp<Connection>& conn(signalConnections[i]);
  11. // now see if we still need to report this event
  1.      // 当EventThread收到Vsync,把它转交给SF线程
  2. status_t err = conn->postEvent(event);
  3. if (err == -EAGAIN || err == -EWOULDBLOCK) {
  4. // The destination doesn't accept events anymore, it's probably
  5. // full. For now, we just drop the events on the floor.
  6. // FIXME: Note that some events cannot be dropped and would have
  7. // to be re-sent later.
  8. // Right-now we don't have the ability to do this.
  9. ALOGW("EventThread: dropping event (%08x) for connection %p",
  10. event.header.type, conn.get());
  11. } else if (err < ) {
  12. // handle any other error on the pipe as fatal. the only
  13. // reasonable thing to do is to clean-up this connection.
  14. // The most common error we'll get here is -EPIPE.
  15. removeDisplayEventConnection(signalConnections[i]);
  16. }
  17. }
  18. return true;
  19. }

分析waitForEvent():

  1. //this will return when
  2. //1, a vsync event has benn recevied
  3. //2,there was as least one connection interested in receiving it when we started waiting
  4. Vector< sp<EventThread::Connection > >EventThread::waitForEvent(
  5. DisplayEventReceiver::Event* event)
  6. {
  7. //find out connections waitting for events
  8. size_t count = mDisplayEventConnections.size();
  9. ofr(size_t i=; i<count; i++) {
  10. if(connection->count >= ) {
  11. //we need vsync events because at least
  12. //one connnection is waiting for it
  13. waitForVSync = true;
  14. }
  15. ......
  16. if(waitFOrVSync){
  17. enableVSyncLocked(); //如果上面的count >= 0,代表需要得到vsync信号,然后调用enableVSyncLocked()
  18. }
  19.  
  20. if(waitForVSync){
  21. ......
  22. } else {
  23. //EventThread之后就会休眠等待vsync
  24. mCondition.wait(mLock);
  25. }
  26. }
  27. }

 enableVSyncLocked中给DisplaySyncThread设置回调,在DisplaySyncThread收到vsync信号后就调用这个回调函数:

  1. void EventThread::enableVSyncLocked() {
  2. if(!mVsyncEnabled) {
  3. mVsyncEnabled = true;
  4. mVSyncSource->setCallback(static_cast<VSyncSource::Callback*)(this));
  5. mVSYncSource->setVSyncEnabled(true);
  6. }
  7. }

(3)H/S vsync唤醒DispSyncThread:

  1. //surfaceFlinger/DIsplayHardware/HWComposer_hwc1.cpp
  2. bool HWComposer::VSyncThread::threadLoop() {
  3. clock_nanosleep();
  4. //休眠 完成后,调用它,发出vsync信号
  5. //mEventHanlder就是SurfaceFlinger,
  6. mHwc.mEventHandler.onVSyncReceived(, next_vsync);
  7. }
  8. --->
  9. //surfaceflinger/SurafceFLinger.cpp
  10. void SurfaceFLinger::onVSyncReceived(type, nescs_t timestamp){
  11. if(type == && mPrimaryHWVsyncEnabled) {
  12. //DispSync::addResyncSample => updateModelLocked() =>
  13. //mThread->updateModel => mCond.signal()来唤醒某个线程,
  14. //mCond.signal()在DispSync.cpp,属于DispSYncThread,
  15. //还是之前说的套路,swVsyncThread使用DispSync的函数唤醒DispSYncThread
  16. needsHwVsync = mPrimaryDIspSync.addResyncSample(timestamp);
  17. }
  18.  
  19. if(needsHwVsync) {
  20. enableHardwareVsync();
  21. }
  22. }

(4)DispSyncThread发信号给EventThread,EventThread发信号给SF线程。

  1. //surfaceflinger/DispSync.cpp
  2. class DispSyncThread : public Thread {
  3. virtual bool threadLoop() {
  4. //计算最近的eventThread的时间,EventThread是Listener,
  5. // =>computeListenerNextEventTimeLocked
  6. targetTime = computeNextEventTimeLocked(now);
  7.  
  8. //休眠
  9. if(now < targetTime) {
  10. mCond.waitRelative(mMutex, targetrTime-now);
  11. }
  12.  
  13. //之后被vsync信号唤醒,获取callback
  14. callbackInvacations = gatherCallbackInvocationsLocked(now);
  15.  
  16. if(callbackInvocations.size() > ) {
  17. //执行callback,导致EventThread的onVsyncEvent函数被调用
  18. fireCallbackInvocations(callbackInvovcations);
  19. }
  20. }
  21. }

  如果EventThread发现Connection的cnt >= 0,就会向DispSyncThread注册回调函数,最后会通过callback构造出Listener,而且EventThread运行时间是收到vsync之后加一个offset,fireCallbackInvocations()调用EventThread类的onVSyncEvent来唤醒EventThread线程:

  1. //surfaceFlinger/EventThread.cpp
  2. void EventThread::onVSyncEvent(nsecs_t timestamp) {
  3. Mutex::Autolock _l(mLock);
  4. mVSyncEvent[].header.id = ;
  5. mVsyncEvent[].vsync.count++;
  6. //发出广播,唤醒EvenThread::threadLoop()向app或sf发出信号
  7. mCondition.broadcast();
  8. }

  EventThread::threadLoop()在waitForEvent里面休眠(mCondition.wait),收到广播后被唤醒,然后调用conn->postEvent(event)向SF线程或者AP发出信号,并通过connection的fd把数据写到SF线程,同样SF线程通过fd获得数据,然后调用SF线程的处理函数。

  1. status_t EventThread::Connection::postEvent(
  2. const DisplayEventReceiver::Event& event) {
  3. ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, );
  4. return size < ? status_t(size) : status_t(NO_ERROR);
  5. }

 (5)sf线程对vsync的处理:在flinger->init()创建connection时,得到了一个fd,然后会检测fd。

   flinger->init() => MessageQueue::setEventThread:

  1. mEventTube = mEvent->getDataChannel();
  2. //检测fd,从fd得到数据,会调用MessageQueue::cb_eventRecevier函数
  3. mLooper->addFd(mEventTube0>getFd(),....,MessageQueue::cb_eventRecevier, this);

  4. --->
  5. //surfaceflinger/MessageQueue.cpp
  6. int MessageQueue::cb_eventRecevier(int fd, int event, void* data) {
  7. return queue->eventRecevier(fd, events);
  8. }
    --->
  9. int MessageQueue::eventReceiver(int fd, int events) {
  10. mHanlder->displatchInvalidate();
  11. }
  12. --->
  13. void MessageQueue::Handler::displayInvaliadate() {
  14. mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
  15. }
  1. SurfaceFlinger中接收并处理消息:
  1. void MessageQueue::Handler::handleMessage(const Message& message) {
  2. switch(message.what) {
  3.      ...
  4. case INVALIDATE:
  5. mQueue.mFlinger->onMessageReceived(message.what);
  6. }
  7. }
  8.  
  9. --->
  10.  
  11. // android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp
  12. void SurfaceFlinger::onMessageReceived(int32_t what) {
  13. ATRACE_CALL();
  14. switch (what) {
  15. case MessageQueue::INVALIDATE: {
  16. bool refreshNeeded = handleMessageTransaction(); //处理事务(设置flag,并未实际操作各个buffer):
                                         //①在handleTransactionLocked()中遍历每个Layer,执行layer->doTransaction(0)
                                         //②处理Display事务(add/remove)
                                         //③Layer角度发生了变化
                                         //④处理sf本身事务: Layer的增加或者删除
                                        
  17. refreshNeeded |= handleMessageInvalidate(); //处理各Layer的buffer更换,使原来的界面无效,并准备好新数据用来更新:
                                      //①accquire next buffer
                                      //②release previous buffer
                                      //③bindTextureImageLocked() ---> glEGLImageTargetTexture2DOES()
       
  18. refreshNeeded |= mRepaintEverything;
  19. if (refreshNeeded) {
  20. // Signal a refresh if a transaction modified the window state,
  21. // a new buffer was latched, or if HWC has requested a full
  22. // repaint
  23. signalRefresh(); //发出Refresh信号,导致下面的 handleMessageRefresh()函数被调用
  24. }
  25. break;
  26. }
  27. case MessageQueue::REFRESH: {
  28. handleMessageRefresh();  //①计算各Layer的可视区域
                           //②合成显示:a.调用opengl把各个Layer的可视区域在一个内存上描绘出来
                           //      b.使用hw composer硬件合成
  1. break; } } }

                            (Vsync时序图)

Android 显示系统:Vsync机制的更多相关文章

  1. 11.5 Android显示系统框架_Vsync机制_黄油计划_三个方法改进显示系统

    5. Vsync机制5.1 黄油计划_三个方法改进显示系统vsync, triple buffering, vsync虚拟化 参考文档:林学森 <深入理解Android内核设计思想>第2版 ...

  2. Android 显示系统:SurfaceFlinger详解

    一.Android系统启动 Android设备从按下开机键到桌面显示画面,大致过程如下图流程: 开机显示桌面.从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍And ...

  3. 11.1 Android显示系统框架_framebuffer原理及改进

    1. Android显示系统框架Android Graphic UI with GPU Hardware Accelerationhttps://community.nxp.com/docs/DOC- ...

  4. Android 显示系统:OpenGL简介和Gralloc代码分析

    一.OpenGL ES与EGL Android的GUI系统是基于OpenGL/EGL来实现的. 由于OpenGL是通用函数库,在不同平台系统上需要被“本土化”——把它与具体平台的窗口系统建立起关联,F ...

  5. 11.5 Android显示系统框架_Vsync机制_代码分析

    5.5 surfaceflinger对vsync的处理buffer状态图画得不错:http://ju.outofmemory.cn/entry/146313 android设备可能连有多个显示器,AP ...

  6. 11.4 Android显示系统框架_APP与SurfaceFlinger内部机制分析

    4.1 APP跟SurfaceFlinger之间的重要数据结构 一个应用程序有一个或者多个surface(一般只有一个),一个surface有一个或者多个buffer,这些buffer需要应用向sur ...

  7. Android 显示系统:飞思卡尔平台图形界面与GPU硬件加速

    图形是Android平台中的一个大主题,包含java/jni图形框架和2d/3d图形引擎(skia.OpenGL-ES.renderscript). 本文档描述了飞思卡尔设备上的一般Android图形 ...

  8. 11.2 Android显示系统框架_android源码禁用hwc和GPU

    2. 修改tiny4412_Android源码禁用hwc和gpu(厂家不会提供hwc和gpu的源代码,没有源代码就没法分析了,因此在这里禁用该功能并用软件库实现)最终源码: git clone htt ...

  9. 11.3 Android显示系统框架_最简单的surface测试程序

    APP有一个surface(界面),其有多个buffer用来存放界面数据,这些buffer是向surfaceflinger申请的: 因此我们编写的surface测试程序步骤: (1)获得surface ...

随机推荐

  1. ln -s vs mount --bind

    First ,Symlinks and bind mounts are a whole different ballgame. ln -s you create a symbolic link,whi ...

  2. CentOS7.X 搭建LAMP

    第一部分搭建LAMP基础环境 1.检查CentOS是否为7.x版本 2.安装LAMP中的apache,采用yum源方法安装 yum  install httpd httpd-devel       A ...

  3. java - day010 - 基本类型包装,自动装箱和拆箱,日期,集合

    基本类型的包装类 byte Byte short Short int Integer long Long float Float double Double char Character boolea ...

  4. 模拟一个http 请求的json格式报文,带 rsa 签名操作

    一.对需要加密的字符串,定义RsaSignUnsign 类,代码如下: 实现了: 1.实现了生成新的pubkey.pri_key方法: 2.将新生成的keys 写入文件: 3.从文件获取pubkey. ...

  5. python3 random

    一.random 1.生成伪随机数 2.伪随机数是可预测的,严格意义上不具有随机性质,通常用数学公式的方法(比如统计分布,平方取中等)获得 3.正如数列需要有首项,产生伪随机数需要一个初值用来计算整个 ...

  6. validatebox自定义验证规则以及使用

    //===============jsp======state==== //开启验证 <script  type="text/javascript"> ​​​​​​​y ...

  7. 使用Django 测试客户端一起测试视图,模板和URL

    Django 测试客户端 self.client.get(url)  测试客户端是Django中TestCase类的一个属性名. 至此已经在网站中可以创建一个清单了. 那么,现在是可以在unit te ...

  8. 冒泡排序之javascript

    冒泡排序是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字 ...

  9. Educational Codeforces Round 67 (Rated for Div. 2) B题【前缀+二分】【补题ING系列】

    题意:给出一个字符串s, 可以从左往右拿走s的字符, 至少要到s的第几个位置才能拼成t 思路:用二维数组记录前缀,然后二分即可. #include<bits/stdc++.h> using ...

  10. 005_STM32程序移植之_RC522读卡模块

    1. 测试环境:STM32C8T6 2. 测试模块:RC522读卡模块 3. 测试接口: RC522读卡模块: VCC------------------3.3V GND--------------- ...