学习流程:
先看文章,再看代码,再看文章,再画图
很多文章写的太长,看了后面忘了前面,必须画出来
我只是知识的搬运工和总结者
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 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& 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 vsyncSrc = new DispSyncSource(&mPrimaryDispSYnc,
syncPhaseOffsetNs, true, "app");
mEventThread = new EventTHread(vsyncSrc, *this);
sp 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(this));
}
看看hwcomposer的构造函数
//native/serivces/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
HWComposer::HWComposer(
const sp& 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)
{
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
//也就是sf线程使用connection向EventThread线程请求下一个vsync信号
mEvents->requestNextVsync();
}
//surfaceFlinger/EventThread.cpp
void EventThread::Connection::requestNextVsync() {
mEventThread->requestrNextVsync(this);
}
void EventTHread::requestNextVysnc(
const sp& 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 >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& 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::waitForEvent(
DisplayEventReceiver::Event* event)
{
//find out connections waitting for events
size_t count = mDisplayEventConnections.size();
ofr(size_t i=0; icount >= 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_castsetVSyncEnabled(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来处理:合成画面然后显示。