Android显示系统 vsync机制 01 vsync的产生和分发

学习流程:

先看文章,再看代码,再看文章,再画图

很多文章写的太长,看了后面忘了前面,必须画出来

我只是知识的搬运工和总结者

 

ButterProject,

1,引入Vsync

android 4.1之前,是两个buffer的,

如果CPU和GPU不按照Vsync的节奏执行,比如第二帧vsync马上要到了,CPu和GPU才去执行,就出现Jank,

 

改进是,vsync来的时候,CPU和GPU立刻工作,

但还有问题,如:

GPU画B,Display显示A,

GPU画的太慢,超过了一个vsync,这时只能继续Display A,就连续2个vsync显示A

下一个vysnc去display B,才可以开始画A,仍然因为画太慢,还是会jank

 

以上是因为CPU和GPU没有buffer可以去画,

改进,增加一个buffer

 

2,Triple Buffer

如果GPU画B慢了,有一个vsync还在显示A的内容,连续显示了两帧A,

但是等GPU画完B,可以去画C,不用等待正在显示的A空闲出来,

画C的时间依然超过一个vsync,但这个vysnc可以显示B了,

然后等GPU画完,他们又可以去画A,而不能等正在显示的B

 

 

 

 

3,Vsync虚拟化

分为vsync-APP,vsync-SF,

如果所有单位都在vsync到来时同时工作,也不行,

 

APP构造好数据,发给SF,

SF使用CPU/GPU渲染,

然后给display

 

如果三者都在vsync到来时同时工作,

APP画好的新画面,SF要在下个vsync才能合成画面,下个vsync才能拿去display,

这里韦东山讲错了? 用fence挡就行了,不会每个vysnc只做一件事情

 

给AP加一个offset,再给SF加一个offset,一个vsync内都做完,然后vsync到来时flip出去

 

 

===================

02 vsync框架

4.4对vysnc进行了进化,

vysnc+offset1:APP工作

vsync+offset2:SF工作

 

google公司应该有一个设计文档,然后根据文档写代码,

 

vsync框架:

1,谁产生vsync?

2,谁处理vsync?应该是某个线程,

3,谁来拆分vsync,将它虚拟化?

4,vsync-app和vsync-sf怎么起作用?

 

1,vsync的产生:

hardware vsync,

software vsync,需要一个线程VSyncThread,休眠16ms发信号,唤醒下面的DispSyncThread线程

2,DispSyncThread线程接收vsync信号,硬件还是软件产生的vsync最终都会唤醒DispSyncThread,

接收vsync信号,做vsync虚拟化:

休眠offset1,唤醒等待vsync-app的线程

休眠offset2,唤醒等待vsync-sf的线程,

3,EventThread for Vsync-APP

收到DispSyncThread的信号vsync-app被唤醒,

它与各个APP的联系为connection,唤醒App1,2,3.....

唤醒所有APP太消耗资源了,只唤醒需要更新界面的APP,如何知道哪些AP要更新界面?

只有AP才知道自己要更新界面,所以AP在要更新界面时,向EventThread提出请求:设置connection.count >= 0,

如果没有AP需要被唤醒,它也就没有必要让DispSyncThread给它发信号了,

所有过程按需进行:

1,APP有更新界面的需要时,它需要得到vsync-app

2,于是向EventThread(APP)提出请求,

3,EventThread向DispSyncThread提出请求,

4,DispSyncThread收到vsync信号后,休眠offset1,发出vsync-app信号,唤醒EventThread,。

4,EventThread for SF

收到DispSyncThread的信号vsync-sf被唤醒,

唤醒 connection到它的线程:SurfaceFlinger线程

回顾之前的流程,也是按需进行:

1,AP接收到vsync-app信号,画好buffer,然后queueBuffer,发给SurfaceFlinger,

2,SurfaceFinger的connection.count就会>=0,就有了vsync需求,向EventThread-sf发出请求,

3,EventThread-sf向DispSyncThread发出请求,

4,DispSyncThread收到vsync信号,休眠offset-2,然后发出vsync-sf信号,唤醒EventThread。

 

 

回答问题:

1,谁产生vsync:硬件或者软件vsyncThread

2,谁处理vsync,谁把vsync虚拟化成vsync-app/sf : DispSyncThread,

3,vsync-app/sf怎么起作用:

按需产生:

AP端:APP需要更新界面时发出vsync请求给EventThread,EventThread收到vsync通知APP可以画东西了

SF端:sf请求EventThread-sf,EventThread-sf收到vsync后通知SF可以开始合成

 

 

===============

03,vsync初始化代码

回顾:

vsync产生后通知DispSyncThread,

DispSyncThread休眠offset1后唤醒EventThread-App

休眠offset2后唤醒EventThread-sf

 

以上是按需进行的,

AP要更新界面,会请求EventThread-APP得到vsync,AP得到vysnc后画完,发给SF线程,

SF线程向EventThread-sf发请求,得到vsync通知后开始合成,然后给display去显示

 

涉及5个线程:

软件vsync产生:vsyncThread

线程虚拟化:DispSyncThread

两个EventThead:App/SF

SurfaceFlinger线程

 

看看源代码,5个线程如何创建出来的,

这5个线程位于同一个进程里面:SurfaceFlinger进程。对于源码Main_surfaceflinger.cpp,

分析下一这个man函数

 

流程图在surface_uml.prj

 

//native/services/surfdaceflinger/main_suirfaceflinger.cpp
int main(int, char**) {
    //1,instantiate surfacelinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();
    //2,initialize before clients can connect
    flinger->init();
    
    //3,run surfaceflinger in this thread
    //这是SF的主线程
    flinger->run();
    return 0;
}

1,new SF时创建的DispSyncThread
创建SF实例化对象成,成员也会被创建,
//native/servvices/surafcelinger/SurfaceFlinger.h
class SurfaceFlinger : public BnSurfaceComposer, private HWComposer::EventHandler
{
    DispSync mPrimaryDispSync;
}

看看DispSYnc的构造函数,它会启动DispSyncThread线程,后面分析
//native/services/surfaceflinger/DispSync.cpp
DispSYnc::DispSYnc(const char* name) : mThread(new DispSYncThread(name)) {
    mThread->run("DispSYnc", RIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

flinger对象是一个strong point指针,看看它的onFirstRef,
void SurfaceFlinger::onFirstRef()
{
    //初始化消息队列
    mEeventQueue.init(this);
}

//natgive/surface/surafcefliner/MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    //创建了loop和handle,后面分析
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

2,这是初始化的最重要的函数
init()时创建的两个EventThread和软件vsyncThread,
void SurfaceFlinger::init() {
    {
        //Autolock
        Mutex::Autolock _l(mStateLock);
        
        //initialize EGL for the default display
        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(mEGLDisplay, NULL, NULL);
        
        //创建了两个EventThread,他们的名字和offset有区别
        //start the EventTHrerad
        sp<VSYncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSYnc, 
            syncPhaseOffsetNs, true, "app");
        mEventThread = new EventTHread(vsyncSrc, *this);
        
        sp<VSYncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDIspSYnc, 
            sfVsyncPhaseOffsetNs, true, "sf");
        mSFEventTHread = new EventTHread(sfVsyncSrc, *this);
        //在这里创建的sf与EventThread之间的connection,
        mEventQueue.setEventTHread(mSFEventThread);    
    }
    mHwc = new HWComposer(this);
    mHwc->setEventThandler(static_cast<HWCOmpsoer::EventHandler*>(this));
    
}

看看hwcomposer的构造函数
//native/serivces/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
HWComposer::HWComposer(
    const sp<SurfaceFLinger>& flinger,
    EventHandler& handler)
    : mFlinger(flinger),mHwc(0),
    mEventHandler(handler)...
{
    loadHwcModule();
    ....
    //这里还设置了DPI之类的东西?
    .....
    if(needVsyncThread) {
        //don't have VSYNC support, fake it
        //这里创建的软件vysnc,它是一个sp<>,在onFirstRef里面运行的线程。以后分析
        mVSyncThread = new VSYncThread(*this);
    }
}    


//load and prepare hwcomposer, sets mHwc,
void HWComposer::loadHwcModule()
{
    hw_module_t const* module;
    if(hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0)  {
        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
        return
    }
    int err = hwc_open_1(module, &mHwc);
}

3,flinger->run()这里面创建的sf线程,
有我们自己的实现
//SurfaceFlinger_hwc1.cpp
void SurfaceFlinger::run() {
    do {
       waitForEvent(); 
    }while(true);
}

//等待AP给它发数据,也等待EventTHread给它发数据,
void SurfaceFlinger::waitForEvent() {
    mEventQueue.waitMessage();
}

SF与EventThread之间有一个COnnection,看看connection是如何创建的
//在SurfaceFLinger::init()里面,
//        mSFEventTHread = new EventTHread(sfVsyncSrc, *this);
//        //在这里创建的sf与EventThread之间的connection,
//        mEventQueue.setEventTHread(mSFEventThread);  

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

 

这节只讲了5个线程的创建流程

 

=================

04 使用vsync流程

这节课讲5个线程的交互作用,

vsync的使用是按需进程的,

比如,当AP把buffer送给SF,SF就请求EventThread,再请求DispSyncThread,

DispSyncThread等到了vsync,再唤醒EventThread,然后唤醒SF线程,

 

这节分析sf使用vsync的代码,

SurfaceFLinger使用vsync过程,

1,App发数据给sf

2,sf发请求给EventThread-sf,

3,EventThread-sf发请求给DispSyncThread,

4,H/S vysnc唤醒DispSyncThread,

5,DispSyncThread发信号给EventThread,EventThread发信号给SF线程,

 

流程在003_sf_use_vsync

先画框图:

sf与EventThread之间有连接:connection,

 

1,AP画好后如何通知sf,

之前讲过,AP是Producer,它通过listener->onFrameAvailable() ->进入消费者 -> mFrameAvailableListener(就是Layer对象) ->

进入SF线程-> mFlinger->signalLayerUpdate() -> mEventQueue.invalidate();

 

//surfaceflinger/MessageQueue.cpp
void MessageQueue::invalidate() {
    //mEvents是sp<IDisplayEventConnection>
    //也就是sf线程使用connection向EventThread线程请求下一个vsync信号
    mEvents->requestNextVsync();
}

//surfaceFlinger/EventThread.cpp
void EventThread::Connection::requestNextVsync() {
    mEventThread->requestrNextVsync(this);
}

void EventTHread::requestNextVysnc(
    const sp<EventTHread::Connection>& connection) {
    if(connection->count < 0){
        //若cnt小于0,则cnt=0,然后发出广播,来唤醒某个线程,
        //当connection的cnt >= 0怎么它需要从EventThread得到vsync
        //这个函数得代码在EventThread,但是它执行在SF线程
        //也就是说,SF线程使用EventThread的函数向EventThread发出广播来唤醒EventThread线程
        connection->count = 0;
        mCondition.boradcast();
    }    
 }

 

//若cnt小于0,则cnt=0,然后发出广播,来唤醒某个线程,

//当connection的cnt >= 0怎么它需要从EventThread得到vsync

//这个函数得代码在EventThread,但是它执行在SF线程

//也就是说,SF线程使用EventThread的函数向EventThread发出广播来唤醒EventThread线程

 

上面把步骤2 : SF线程向EventThread请求vsync也做完了,

下面看步骤3,EventThread-sf请求DispSyncThread,

 

EventThread里面一定有一个threadLoop,

//surafceflinger/EvetnThread.cpp
bool EventThead::threadLoop() {
    DisplayEventReceiver::Event event;
    Vector< sp<EventThread::Connection> >signalConnections;
    //waitForEvent就是步骤3,
    //1,EventThread向DispSyncThread发出vsync请求
    //2,等待vsync
    signalConnections = waitForEvent(&event);
    
    //dispatch events to listeners
    const size_t count = signalConnections.size();
    for(size_t i=0; i<count; i++) {
        const  sp<Connnection>& conn(signalConnections[i]);
        //这里就是步骤6了,
        //当EventThread收到Vsync,把它转交给SF线程
        status_t err = conn->postEvet(event);
    }
}

分析waitForEvent()
//this will return when 
//1, a vsync event has benn recevied
//2,there was as least one connection interested in receiving it when we started waiting
Vector< sp<EventThread::Connection > >EventThread::waitForEvent(
    DisplayEventReceiver::Event* event)
{
    //find out connections waitting for events
    size_t count = mDisplayEventConnections.size();
    ofr(size_t i=0; i<count; i++) {
        if(connection->count >= 0) {
            //we need vsync events because at least 
            //one connnection is waiting for it
            waitForVSync = true;
        }
        
        if(waitFOrVSync){
            enableVSyncLocked();
        }
        
        if(waitForVSync){
            
        } else {
            //在这里休眠,能走进来?
            mCondition.wait(mLock);
        }
        
    }
}    

void EventThread::enableVSyncLocked() {
    if(!mVsyncEnabled) {
        mVsyncEnabled = true;
        mVSyncSource->setCallback(static_cast<VSyncSource::Callback*)(this));
        mVSYncSource->setVSyncEnabled(true);
    }
}

EventThread这边有一个或者多个Connection,

但是对于SF线程只有一个connnection,

AP端可能有多个connection,

 

当EventThread在waitForEvent()判断所有的Connection->count值,

如果>=0,代表需要得到vsync信号,他会enableVSyncLocked(),

里面设置回调函数,给DispSyncThread设置callback,

 

DispSyncThread收到vsync就会调用注册的callback函数,

 

EventThread之后就会等待vsync,就是休眠 mCondition.wait(mLock);

 

步骤4,

DispSyncThread平时也是休眠的,它会被vsync唤醒,

看看软件vsync怎么唤醒DispSyncThread,

//surfaceFlinger/DIsplayHardware/HWComposer_hwc1.cpp
bool HWComposer::VSyncThread::threadLoop() {
    clock_nanosleep();
    //休眠 完成后,调用它,发出vsync信号
    //mEventHanlder就是SurfaceFlinger,
    mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
}

//surfaceflinger/SurafceFLinger.cpp
void SurfaceFLinger::onVSyncReceived(type, nescs_t timestamp){
    if(type == 0 && mPrimaryHWVsyncEnabled) {
        //DispSync::addResyncSample => updateModelLocked() => 
        //mThread->updateModel => mCond.signal()来唤醒某个线程,
        //mCond.signal()在DispSync.cpp,属于DispSYncThread,
        //还是之前说的套路,swVsyncThread使用DispSync的函数唤醒DispSYncThread
        needsHwVsync = mPrimaryDIspSync.addResyncSample(timestamp);
    }
    
    if(needsHwVsync) {
        enableHardwareVsync();
    }
}

 

//DispSync::addResyncSample => updateModelLocked() =>

//mThread->updateModel => mCond.signal()来唤醒某个线程,

//mCond.signal()在DispSync.cpp,属于DispSYncThread,

//还是之前说的套路,swVsyncThread使用DispSync的函数唤醒DispSYncThread

分析完了步骤4,通过SF::onVsyncRecevied()唤醒DispVsyncThread,

 

分析step5,DispSyncThread发信号给EventThread,EventThread发信号给SF线程,

看看DispSyncThread的threadLoop做什么事情,

//surfaceflinger/DispSync.cpp
class DispSyncThread : public Thread {
    virtual bool threadLoop() {
        //计算最近的eventThread的时间,EventThread是Listener,
        // =>computeListenerNextEventTimeLocked 
        targetTime = computeNextEventTimeLocked(now);
        
        //休眠
        if(now < targetTime) {
            mCond.waitRelative(mMutex, targetrTime-now);
        }
        
        //之后被vsync信号唤醒,
        //获取callback
        callbackInvacations = gatherCallbackInvocationsLocked(now);
        
        if(callbackInvocations.size() > 0) {
            //执行callback,导致EventThread的onVsyncEvent函数被调用,
            fireCallbackInvocations(callbackInvovcations);
        }
    }
}

细节就不看了,看了也会忘掉

如果EventThread发现Connection的cnt >= 0,就会向DispSyncThread注册回调函数,

最后会通过callback构造出Listener,

而且EventThread运行时间是收到vsync之后加一个offset,

fireCallbackInvocations()调用EventThread类的onVSyncEvent来唤醒EventThread线程

//surfaceFlinger/EventThread.cpp
void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.id = 0;
    mVsyncEvent[0].vsync.count++;
    //发出关顾广播,唤醒EvenThread::threadLoop()
    mCondition.broadcast();
}

 

EventThread::threadLoop()在waitForEvent里面休眠:mCondition.wait

现在被唤醒,然后调用conn->postEvent(event);来像SF线程或者AP发出信号,

 

postEvent =》 sendEvents(mChannel, &event, 1) => sendObjects(BitTube, events ,...) => tube->write();

 

postEvent通过connection的fd把数据写到SF线程,

sf线程通过它的fd获得数据,调用sf线程的处理函数,

 

step7,sf线程对vsync的处理

在flinger->init()创建connection时,得到了一个fd,然后会检测fd,

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

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

//surfaceflinger/MessageQueue.cpp
int MessageQueue::cb_eventRecevier(int fd, int event, void* data) {
    return queue->eventRecevier(fd, events);
}

int MessageQueue::eventReceiver(int fd, int events) {
    mHanlder->displatchInvalidate();
}

void MessageQueue::Handler::displayInvaliadate() {
    mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}

//handleMessage处理它
void MessageQueue::Handler::handleMessage(const Message& message) {
    switch(message.what) {
        case INVALIDATE:
            mQueue.mFlinger->onMessageReceived(message.what);
    }
}

走到SurfaceFlinger::onMessageReceived()
//surfaceflinger/SurefaceFlinger.cpp
void SurefaceFlinger::onMessageRecevied(int32_t what) {
    switch(what) {
        case MessageQueue::INVALIDATE: {
            handleMessageTransaction();
            handleMessageInvalidate();
            signalRefresh();
        }
    }
}

总结:

AP通过sureface->postAndUnlock导致queueBuffer向SF传buffer,

SF端通过signalLayerUpdate向EventThread请求得到Vsync信号,

EventThread通过waitForEvent向DispSyncThread发出vsync请求然后休眠等待被唤醒,

硬件软件vsync调用SurfaceFlinger::onVysncRecevied来唤醒DispSyncThread,

DispSyncThread调用EventThread::onVSyncEvent来唤醒EventThread,

EventThread调用EventThread::Connection::postEvent唤醒SurfaceFlinger线程,

SurfaceFlinger调用MessageQueue::cb_eventRecevier来处理:合成画面然后显示。

 

 

 

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值