theme: fancy
Vsync信号上报流程
Vsync的注册函数,来临时会回调HWComposer的hook_VSYNC方法,接着调用到vsync方法中
大致流程梳理:
该方法会通知给SurfaceFliger的onVsyncReceived方法,接着调用DispSync的addResyncSample方法。
DispSyncThread线程被唤醒 ,接着EventThread线程唤醒,上面代码中会遍历singalConnections集合调用Connection的postEvent方法
代码语言:javascript复制void HWComposer::vsync(int disp, int64_t timestamp) {
if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
{
Mutex::Autolock _l(mLock);
if (timestamp == mLastHwVSync[disp]) {
return; //忽略重复的VSYNC信号
}
mLastHwVSync[disp] = timestamp;
}
//此处mEventHandler是指SurfaceFlinger对象。
mEventHandler.onVSyncReceived(disp, timestamp);
}
}
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
bool needsHwVsync = false;
{
Mutex::Autolock _l(mHWVsyncLock);
if (type == 0 && mPrimaryHWVsyncEnabled) {
// 此处mPrimaryDispSync为DispSync类
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
由于上面卡到了DispSync类调用addResyncSample方法处,故先来看这个类。
DispSyncThread线程
DisSync类会创建一个DispSyncThread并运行其run方法
DispSync的初始化过程:
- 运行DispSyncThread线程,用于收集等待Vsync信号的对象并回调这些对象的onDispSyncEvent方法
- 这些等待的对象其实就是DispSyncSource对象 , 是在创建两个EventThread接收的参数
- DispSyncSource的onDispSyncEvent方法阻塞于mCond(Condition)的wait等待被唤醒。
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);
if (mStop) {
return false;
}
if (mPeriod == 0) {
//在此处阻塞等待
//稍后被DispSync类的addResyncSample方法唤醒
err = mCond.wait(mMutex);
continue;
}
nextEventTime = computeNextEventTimeLocked(now);
targetTime = nextEventTime;
bool isWakeup = false;
if (now < targetTime) {
err = mCond.waitRelative(mMutex, targetTime - now);
if (err == TIMED_OUT) {
isWakeup = true;
} else if (err != NO_ERROR) {
return false;
}
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63)
(now - targetTime)) / 64;
if (mWakeupLatency > 500000) {
mWakeupLatency = 500000;
}
}
//收集vsync信号的所有回调方法
callbackInvocations = gatherCallbackInvocationsLocked(now);
}
if (callbackInvocations.size() > 0) {
//回调所有对象的onDispSyncEvent方法
//这些对象其实就是DispSyncSource
//下面分析
fireCallbackInvocations(callbackInvocations);
}
}
return false;
}
接着分析addResyncSample方法
DispSync::addResyncSample
代码语言:javascript复制//最后会调用到updateModelLocked方法
void DispSync::updateModelLocked() {
...
//
mThread->updateModel(mPeriod, mPhase);
}
class DispSyncThread: public Thread {
void updateModel(nsecs_t period, nsecs_t phase) {
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
//唤醒目标线程就是上面的那个DispSyncThread线程的Condition
mCond.signal();
}
}
fireCallbackInvocations
调用DispSyncSource的onDisPSyncEvent方法
代码语言:javascript复制void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
for (size_t i = 0; i < callbacks.size(); i ) {
//此处的Callback就是DispSyncSuorce对象
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
//DispSyncSource::onDispSyncEvent
virtual void onDispSyncEvent(nsecs_t when) {
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mCallbackMutex);
callback = mCallback;
}
if (callback != NULL) {
//调用EventThread的onVSyncEvent方法,该方法会唤醒EventThread线程
//回顾上面ET线程阻塞之后的操作调用Connection的postEvent方法
callback->onVSyncEvent(when);
}
}
此时进入到EventThread线程中
Connection::postEvent
像Bittube发送消息,Looper监听到后发送消息切换到SurfaceFlinger主线程去处理
代码语言:javascript复制status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
//调用DES的sendEvents方法
ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
Event const* events, size_t count)
{
//通过BitTube发送消息
//init过程中初始化了EventThread后添加到MQ中时就监听了这个BitTube,因此
//会调用到MQ.cb_eventReceiver
return BitTube::sendObjects(dataChannel, events, count);
}
,MQ::cb_eventReceiver
init初始化过程中MQ会监听BitTube,从而调用到cb_eventReceiver方法
大致流程:
发送消息(REFRESH消息),接着就是图形渲染的过程了。
发送消息代码:
代码语言:javascript复制int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
return queue->eventReceiver(fd, events);
}
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i ) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
#if INVALIDATE_ON_VSYNC
mHandler->dispatchInvalidate();
#else
//分发Refresh消息
mHandler->dispatchRefresh();
#endif
break;
}
}
}
return 1;
}
void MessageQueue::Handler::dispatchRefresh() {
if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
//发送Refresh消息,则进入handleMessage过程
mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
}
}
//MQ中接收到进行处理消息
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
//回调SurfaceFliger的onMessageReceived方法
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case TRANSACTION:
android_atomic_and(~eventMaskTransaction, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
SurfaceFlinger处理消息
代码语言:javascript复制void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::TRANSACTION: {
handleMessageTransaction();
break;
}
case MessageQueue::INVALIDATE: {
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
signalRefresh();
}
break;
}
case MessageQueue::REFRESH: {
//该方法处理渲染流程
handleMessageRefresh();
break;
}
}
}
//处理渲染流程
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition();
}
流程梳理
- HWComposer接受Vsync信号,
- 唤醒DispSyncThread线程(用于接受Vsync信号),
- 唤醒EventThread线程,调用到DisplayEventReceiver的sendEvent方法再通过BitTube来发送数据
- EventThread创建好后会调用MQ的setEventThread方法监听Bittube,调用MQ的方法因此回调到SurfaceFlinger的主线程中处理
- 进入到渲染流程下篇文章分析