Android SurfaceFlinger服务(六) ----- VSync信号的分发

HWComposer模块产生VSync信号后要经过分发才能送达到关心VSync事件的模块中去。VSync信号分发大致流程为HWComposer->SurfaceFlinger->DispSync->DispSyncSource->各个具体模块。下面具体分析下这个流程。

在上一篇文章中分析到硬件或者软件VSync信号产生时,会回调SurfaceFlinger的onVSyncReceived函数,来看看这个函数:

void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
    bool needsHwVsync = false;

    { // Scope for the lock
        Mutex::Autolock _l(mHWVsyncLock);
        if (type == 0 && mPrimaryHWVsyncEnabled) {
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        }
    }  

    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
}
  • mPrimaryDispSync类型为DispSync,在构造的时候会创建DispSyncThread
DispSync::DispSync() :
        mRefreshSkipCount(0),
        mThread(new DispSyncThread()) {

    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);

    reset();
    beginResync();

    if (kTraceDetailedInfo) {
        // If we‘re not getting present fences then the ZeroPhaseTracer
        // would prevent HW vsync event from ever being turned off.
        // Even if we‘re just ignoring the fences, the zero-phase tracing is
        // not needed because any time there is an event registered we will
        // turn on the HW vsync events.
        if (!kIgnorePresentFences) {
            addEventListener(0, new ZeroPhaseTracer());
        }
    }
}
  • 调用DispSync的addResyncSample方法,最终会去唤醒DispSyncThread线程
bool DispSync::addResyncSample(nsecs_t timestamp) {
    Mutex::Autolock lock(mMutex);

    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
    mResyncSamples[idx] = timestamp;

    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
        mNumResyncSamples++;
    } else {
        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
    }

    updateModelLocked();

    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
        resetErrorLocked();
    }

    if (kIgnorePresentFences) {
        // If we don‘t have the sync framework we will never have
        // addPresentFence called.  This means we have no way to know whether
        // or not we‘re synchronized with the HW vsyncs, so we just request
        // that the HW vsync events be turned on whenever we need to generate
        // SW vsync events.
        return mThread->hasAnyEventListeners();
    }

    return mPeriod == 0 || mError > kErrorThreshold;
}
  • 调用updateModelLocked函数
  • 计算是否需要开启硬件VSync,进行同步
void DispSync::updateModelLocked() {
    if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {

        ......

        mThread->updateModel(mPeriod, mPhase);
    }
}
  • 成员变量mThread为DispSyncThread类的对象
  • 调用DispSyncThread类pdateModel方法
void updateModel(nsecs_t period, nsecs_t phase) {
        Mutex::Autolock lock(mMutex);
        mPeriod = period;
        mPhase = phase;
        mCond.signal();
    }
  • 该方法主要设置成员变量mPeriod、mPhase
  • 然后在唤醒线程循环
virtual bool threadLoop() {
        status_t err;
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        nsecs_t nextEventTime = 0;

        while (true) {
            Vector<CallbackInvocation> callbackInvocations;

            nsecs_t targetTime = 0;

            { // Scope for lock
                Mutex::Autolock lock(mMutex);

                ......

                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }

            if (callbackInvocations.size() > 0) {
                fireCallbackInvocations(callbackInvocations);
            }
        }

        return false;
    }
  • 通过gatherCallbackInvocationsLocked得到监听者集合
  • 通过fireCallbackInvocations调用监听者回调函数

DispSync的回调函数在哪里注册,我们在看看DispSyncSource的setVSyncEnabled函数

virtual void setVSyncEnabled(bool enable) {
        Mutex::Autolock lock(mVsyncMutex);
        if (enable) {
            status_t err = mDispSync->addEventListener(mPhaseOffset,
                    static_cast<DispSync::Callback*>(this));
            if (err != NO_ERROR) {
                ALOGE("error registering vsync callback: %s (%d)",
                        strerror(-err), err);
            }
            //ATRACE_INT(mVsyncOnLabel.string(), 1);
        } else {
            status_t err = mDispSync->removeEventListener(
                    static_cast<DispSync::Callback*>(this));
            if (err != NO_ERROR) {
                ALOGE("error unregistering vsync callback: %s (%d)",
                        strerror(-err), err);
            }
            //ATRACE_INT(mVsyncOnLabel.string(), 0);
        }
        mEnabled = enable;
    }
  • DispSyncSource类继承于DispSync::Callback
  • 调用DispSync->addEventListener注册回调,当DispSyncSource收到DispSync的VSync信号时,会回调整onDispSyncEvent函数
virtual void onDispSyncEvent(nsecs_t when) {
        sp<VSyncSource::Callback> callback;
        {
            Mutex::Autolock lock(mCallbackMutex);
            callback = mCallback;

            if (mTraceVsync) {
                mValue = (mValue + 1) % 2;
                ATRACE_INT(mVsyncEventLabel.string(), mValue);
            }
        }

        if (callback != NULL) {
            callback->onVSyncEvent(when);
        }
    }
  • 这个函数最终还是调用VSyncSource::Callback的onVSyncEvent函数。
  • VSyncSource::Callback函数的注册是通过调用DispSyncSource的setCallback注册。

DispSyncSource的setCallback函数在哪里调用的呢,要解答这个问题,还是得回到SurfaceFlinger的init函数里,以sfVsyncSrc为例。

void SurfaceFlinger::init() {

    ......

    // start the EventThread
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc);
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

    ......
}
  • 以sfVsyncSrc为参数创建EventThread对象
  • 在EventThread的线程循环中会去调用enableVSyncLocked函数
void EventThread::enableVSyncLocked() {
    if (!mUseSoftwareVSync) {
        // never enable h/w VSYNC when screen is off
        if (!mVsyncEnabled) {
            mVsyncEnabled = true;
            mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
            mVSyncSource->setVSyncEnabled(true);
        }
    }
    mDebugVsyncEnabled = true;
    sendVsyncHintOnLocked();
}
  • EventThread继承VSyncSource::Callback接口,实现了onVSyncEvent函数
  • 调用mVSyncSource的setCallback函数设置回调
  • 调用mVSyncSource的setVSyncEnabled函数使能VSync信号的监听
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast();
}
  • EventThread收到VSync信号后,发送广播消息,唤醒相关线程
  • 最终EventThread将VSnc信号传递给MessageQueue

原文地址:https://www.cnblogs.com/qzhang1535/p/9285085.html

时间: 2024-08-07 23:03:47

Android SurfaceFlinger服务(六) ----- VSync信号的分发的相关文章

Android SurfaceFlinger服务(三) ----- 本地图层Layer创建

在上一篇文章中,主要分析了Surface的创建过程,对于Layer图层的创建并没有深入跟踪分析.这篇文章将分析Layer图层的创建,并分析handle gbp这两个变量的来源. 在SurfaceFlinger中会根据flags的值创建不同的layer.这里主要以创建普通layer为例进行分析. status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, const String8& name, uin

Android Surfaceflinger服务(一) ----- BufferQueue分析

生产者和消费者模型是编程中运用比较广泛的模型.在SurfaceFlinger图像绘制.合成.显示也用到了该模型.利用该模型合理的管理图像缓冲区buffer.让整个android系统从绘制到显示的过程有条不紊的进行. BufferQueue图像缓冲管理者.其成员函数createBufferQueue创建一个缓冲区队列. void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraph

Android SurfaceFlinger服务(八) ----- 图像的输出

SurfaceFlinger合成后就进行图像的输出的工作.在图像输出时,存在硬件合成器与不存在的情况有些差别.软件合成时用到图像缓冲区生产者与消费者模型.首先来看看图像缓冲区的初始化. void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); ...... // initialize our n

vsync信号产生与分发

以下分析基于android 4.4代码 vsync信号的产生.分发涉及到以下几个类,先主要了解下他们各自的功能: HWComposer:产生hardware vsync,post fb VSyncThread : 如果没有硬件支持,那么通过软件方式模拟hw vsyncDispSync,DispSyncThread: 接受HWComposer的hw vsync信号作为校准,开始模拟产生vsync信号+偏移,并且会不时地进行校准,如postComposition后.EventControlThrea

Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析 .

引自:http://blog.csdn.net/luoshengyang/article/details/7867340 在前面一篇文章中,我们分析了Android应用程序与SurfaceFlinger服务的连接过程.Android应用程序成功连接上SurfaceFlinger服务之后,还需要一块匿名共享内存来和SurfaceFlinger服务共享它的UI元数据, 以便使得SurfaceFlinger服务可以正确地为它创建以及渲染Surface.在本文中,我们将详细地分析这块用来保存UI元数据的

Android应用程序与SurfaceFlinger服务的连接过程分析

转自:http://blog.csdn.net/luoshengyang/article/details/7857163 前文在描述Android应用程序和SurfaceFlinger服务的关系时提到,每一个有UI的Android应用程序都需要与SurfaceFlinger服务建立一个连接,以便可以通过这个连接来请求SurfaceFlinger服务为它创建和渲染Surface. 在本文中,我们将以Android系统的开机动画应用程序为例,详细描述Android应用程序是如何与SurfaceFli

Android应用程序与SurfaceFlinger服务的关系概述和学习计划 .

转自:http://blog.csdn.net/luoshengyang/article/details/7846923 SurfaceFlinger服务:负责绘制Android应用程序的UI, SurfaceFlinger服务运行在Android系统的System进程中,它负责管理Android系统的帧缓冲区(Frame Buffer).Android系统的帧缓冲区的相关知识, Android应用程序为了能够将自己的UI绘制在系统的帧缓冲区上,它们就必须要与SurfaceFlinger服务进行

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8079456 在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger服务的启动过程.初始化硬件帧缓冲区的过程.线程模型.SurfaceFlinger服务所做的一切都是为了给Android应用程序提服务的,即为Android应用程序渲染它们的UI.在本文中,我们就详细分析Su

Android应用程序请求SurfaceFlinger服务创建Surface的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7884628 前面我们已经学习过Android应用程序与SurfaceFlinger服务的连接过程了.连接上SurfaceFlinger服务之后,Android应用程序就可以请求SurfaceFlinger服务创建Surface.而当有了Surface后,Android应用程序就可以用来渲染自己的UI了.在本文中,我们将详细分析Android应用