一、app 请求Vsync
app vsync关键的类是EventThread.cpp,在其构造函数里面会开启一个线程在threadMain()函数里面进行循环。当app进程通过binder跨进程请求vsync信号的时候会调EventThread::requestNextVsync()函数。
1、app vsync 的请求
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
。。。。。
if (connection->vsyncRequest == VSyncRequest::None) {
connection->vsyncRequest = VSyncRequest::Single;
mCondition.notify_all();
}
。。。。。
}
这里会将connection->vsyncRequest设置为 VSyncRequest::Single,并唤醒threadMain里面的等待。
VSyncRequest分为三中类型,分别为
None:表示不在进行vsync的定时。
Single:app有vsync请求的时候是这个状态,接下来需要想app返回两次vsync信号。
SingleSuppressCallback:返回一次vsync之后就是这个状态。
接下来我们看一下 threadMain 函数里面:
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
。。。。。。
bool vsyncRequested = false;
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin();
//对所有的connection进行遍历
while (it != mDisplayEventConnections.end()) {
if (const auto connection = it->promote()) {
//因为前面 request 的时候赋值为 Single, 所以为 true
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
。。。。。。
}
。。。。。。
}
。。。。。。
State nextState;
if (mVSyncState && vsyncRequested) {
//将 nextState 设置为 State::VSync
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
}
。。。。。。
if (mState != nextState) {
if (mState == State::VSync) {
mVSyncSource->setVSyncEnabled(false);
} else if (nextState == State::VSync) {
// 1、这里开始计算等待时间、并进行定时
mVSyncSource->setVSyncEnabled(true);
}
mState = nextState;
}
。。。。。。
}
}
因为前面将 nextState 设置为 State::VSync,而且 mState 初始化不为 State::VSync,所以会执行到 1 的位置开始进行vsync等待时间,并进行定时。
2、计算 app vsync 的等待时长和定时
void start(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) {
// 这个参数决定了是否停止定时
mStarted = true;
mWorkDuration = workDuration;
mReadyDuration = readyDuration;
//计算并定时
auto const scheduleResult =
mRegistration.schedule({.workDuration = mWorkDuration.count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = mLastCallTime.count()});
}
这里将mStarted赋值为true表示开始循环定时,当停止定时就会将mStarted设置为false。
mRegistration.schedule最终会调用到VSyncDispatchTimerQueue::schedule(),在sf vsync文章里面我们说到了VSyncDispatchTimerQueue主要是负责vsync的定时和回调事件。
ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
ScheduleTiming scheduleTiming) {
ScheduleResult result;
{
std::lock_guard lock(mMutex);
auto it = mCallbacks.find(token);
if (it == mCallbacks.end()) {
return result;
}
auto& callback = it->second;
auto const now = mTimeKeeper->now();
/* If the timer thread will run soon, we'll apply this work update via the callback
* timer recalculation to avoid cancelling a callback that is about to fire. */
auto const rearmImminent = now > mIntendedWakeupTime;
if (CC_UNLIKELY(rearmImminent)) {
callback->addPendingWorkloadUpdate(scheduleTiming);
return getExpectedCallbackTime(mTracker, now, scheduleTiming);
}
//1、计算出定时时长
result = callback->schedule(scheduleTiming, mTracker, now);
if (!result.has_value()) {
return result;
}
// mIntendedWakeupTime 默认是无穷大, 所以这里肯定会通过
if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
//2、真正开始定时
rearmTimerSkippingUpdateFor(now, it);
}
}
return result;
}
(1)计算定时时长
VSyncDispatchTimerQueue.cpp
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
VSyncTracker& tracker, nsecs_t now) {
//通过 VsyncTracker 计算出下一次软件Vsync的时间,在sf vsync 文章中我们讲到VsyncTracker是负责通过 hwVsync 计算出软件vsync的模型
auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
// 计算出下次唤醒的时间
auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
//将计算出的唤醒时间放到 mArmedInfo
mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
return getExpectedCallbackTime(nextVsyncTime, timing);
}
这里的 VSyncDispatchTimerQueueEntry 就是 VSyncDispatchTimerQueue 里面的 mCallbacks (这是一个map)的 value 的类型,map的可以是Token。VSyncDispatchTimerQueueEntry 和app进程的Connection是一一对应的,里面记录了WakeupTime 和 VSyncDispatch::Callback(在定时到的时候会用到)。
关于软件vsync模型的计算我们后面在介绍。
(2)进行定时
void Timer::alarmAt(std::function<void()> callback, nsecs_t time) {
std::lock_guard lock(mMutex);
。。。。。。
if (timerfd_settime(mTimerFd, TFD_TIMER_ABSTIME, &new_timer, &old_timer)) {
ALOGW("Failed to set timerfd %s (%i)", strerror(errno), errno);
}
}
这里就是通过mTimerFd来进行定时的,当时间到了,监听了mTimerFd的就会被唤醒。我们来看一下具体在哪监听的:
bool Timer::dispatch() {
。。。。。。
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mTimerFd, &timerEvent) == -1) {
ALOGE("Error adding timer fd to epoll dispatch loop");
return true;
}
。。。。。。
while (true) {
。。。。。。
int nfds = epoll_wait(mEpollFd, events, DispatchType::MAX_DISPATCH_TYPE, -1);
。。。。。
for (auto i = 0; i < nfds; i++) {
if (events[i].data.u32 == DispatchType::TIMER) {
。。。。。
{
cb = mCallback;
}
if (cb) {
setDebugState(DebugState::InCallback);
//执行
cb();
setDebugState(DebugState::Running);
}
}
。。。。。。
}
}
}
从代码我们可以看出是通过epoll来监听mTimerFd的变化,当定时时间到就会往下执行,然后执行cb(),也就是mCallback进行回调。
二、事件的回调
接下来我们看一下事件的回调流程具体是怎么样的。
mCallback是在Timer::alarmAt()函数被调用的时候传递过来的,那么它具体是什么呢?
所以执行mCallBack就是执行VSyncDispatchTimerQueue::timerCallback 函数:
void VSyncDispatchTimerQueue::timerCallback() {
struct Invocation {
std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
nsecs_t vsyncTimestamp;
nsecs_t wakeupTimestamp;
nsecs_t deadlineTimestamp;
};
。。。。。。
for (auto const& invocation : invocations) {
//这里执行的是 VSyncDispatchTimerQueueEntry 的 callback 函数
invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
invocation.deadlineTimestamp);
}
}
我们追寻溯源看一下 VSyncDispatchTimerQueueEntry 的 callback 具体是在哪被赋值的。
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard lock(mMutex);
return CallbackToken{
mCallbacks
.emplace(++mCallbackToken,
std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
std::move(callback),
mMinVsyncDistance))
.first->first};
}
那么registerCallback又是在哪调用的呢。
VSyncCallbackRegistration::VSyncCallbackRegistration(VSyncDispatch& dispatch,
VSyncDispatch::Callback callback,
std::string callbackName)
: mDispatch(dispatch),
mToken(dispatch.registerCallback(std::move(callback), std::move(callbackName))),
mValidToken(true) {}
是在VSyncCallbackRegistration构造函数里面调用了registerCallback。我们接着往下寻找:
从这我们知道了 VSyncDispatchTimerQueueEntry 的 callback是CallbackRepeater::callback函数,我们看一下这个函数:
void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
。。。。。。
// 1
mCallback(vsyncTime, wakeupTime, readyTime);
{
std::lock_guard lock(mMutex);
// 2
if (!mStarted) {
return;
}
// 3
auto const scheduleResult =
mRegistration.schedule({.workDuration = mWorkDuration.count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = vsyncTime});
LOG_ALWAYS_FATAL_IF(!scheduleResult.has_value(), "Error rescheduling callback");
}
}
我们可以看到又执行了mCallback(vsyncTime, wakeupTime, readyTime),而且 2 处有一个判断使用了 mStarted, 如果mStarted为false则不会继续下一次的定时,这样就停止了 vsync 的申请。反之则会在注释 3处继续调用mRegistration.schedule进行下一次的定时。
从前面我们可以知道 mCallback 是在 CallbackRepeater 创建的时候传过来的,我们找一下:
mCallbackRepeater =
std::make_unique<CallbackRepeater>(vSyncDispatch,
std::bind(&DispSyncSource::onVsyncCallback, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3),
name, workDuration, readyDuration,
std::chrono::steady_clock::now().time_since_epoch());
所有CallbackRepeater 的 mCallback 是 DispSyncSource::onVsyncCallback:
void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
nsecs_t readyTime) {
VSyncSource::Callback* callback;
{
std::lock_guard lock(mCallbackMutex);
callback = mCallback;
}
。。。。。。
if (callback != nullptr) {
callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
}
}
会执行到callback->onVSyncEvent函数, 因为 EventThread 继承了 VSyncSource::Callback, 所以我们知道最后执行的是EventThread::onVSyncEvent
void EventThread::onVSyncEvent(nsecs_t timestamp, VSyncSource::VSyncData vsyncData) {
。。。。。。
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count,
vsyncData.expectedPresentationTime,
vsyncData.deadlineTimestamp));
mCondition.notify_all();
}
EventThread::onVSyncEvent就是往mPendingEvents添加一个Event,然后进行线程唤醒,那么我们接下来回到 EventThread 的 threadMain 函数:
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
// Determine next event to dispatch.
// onVSyncEvent 函数里添加了 Event,所以mPendingEvents有元素
if (!mPendingEvents.empty()) {
// 获取到event,并将这个event从mPendingEvents里面移除
event = mPendingEvents.front();
mPendingEvents.pop_front();
。。。。。。
}
bool vsyncRequested = false;
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
if (const auto connection = it->promote()) {
//connection->vsyncRequest 还是 Single
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
// shouldConsumeEvent 判断 connection->vsyncRequest 的值,并将其置为下一阶段
if (event && shouldConsumeEvent(*event, connection)) {
// 将请求了 vsync 的connection 放到 consumers
consumers.push_back(connection);
}
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
// 前面已经往consumers添加了需要vsync信号的connection,所以不为空
if (!consumers.empty()) {
// 2、开始事件派发
dispatchEvent(*event, consumers);
consumers.clear();
}
State nextState;
if (mVSyncState && vsyncRequested) {
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
......
}
// mState 和 nextState 都是 State::VSync
if (mState != nextState) {
......
}
// 因为 event 不为空所以继续下一次循环
if (event) {
continue;
}
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
。。。。。。
// 1
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
。。。。。。
}
}
}
}
前面我们说了 nextState 被赋值了 State::VSync, 所以在完成定时之后会接着往下执行 1 处的等待,而 EventThread::onVSyncEvent 里面唤醒的等待就是这个,那么就会接着执行下一个循环。注释 2 处开始往app端派发vsync事件,使用的是本地socket方式进行跨进程通信。
三、app 再次请求 vsync
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
。。。。。。
if (connection->vsyncRequest == VSyncRequest::None) {
connection->vsyncRequest = VSyncRequest::Single;
mCondition.notify_all();
} else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
connection->vsyncRequest = VSyncRequest::Single;
}
}
当app端再次请求vysnc信号时,如果 connection->vsyncRequest == VSyncRequest::SingleSuppressCallback,则只会将connection->vsyncRequest 设置为Single,不用唤醒线程。
四、vsync请求停止
要探寻vsync请求的停止,我们要从 EventThread::threadMain 开始。
// 当定时到了,进行事件派发的时候,如果connection->vsyncRequest == SingleSuppressCallback,
//shouldConsumeEvent函数里面会将 shouldConsumeEvent 设置为 None。
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
。。。。。。
bool vsyncRequested = false;
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
if (const auto connection = it->promote()) {
// 3
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
// 1
if (event && shouldConsumeEvent(*event, connection)) {
consumers.push_back(connection);
}
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
if (!consumers.empty()) {
dispatchEvent(*event, consumers);
consumers.clear();
}
State nextState;
// 4
if (mVSyncState && vsyncRequested) {
nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
nextState = State::Idle;
}
// 5
if (mState != nextState) {
if (mState == State::VSync) {
mVSyncSource->setVSyncEnabled(false);
} else if (nextState == State::VSync) {
mVSyncSource->setVSyncEnabled(true);
}
mState = nextState;
}
// 2
if (event) {
continue;
}
// Wait for event or client registration/request.
// 6
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
......
}
}
}
注释 1 : 当定时到了,进行事件派发的时候,如果connection->vsyncRequest == SingleSuppressCallback,shouldConsumeEvent函数里面会将 shouldConsumeEvent 设置为 None。
注释 2 : 会进行下一个循环。
注释3 :是下一个循环的逻辑,因为connection->vsyncRequest == None,所以vsyncRequested 为赋值为false。
注释 4:vsyncRequested 为 false,所以 nextState = State::Idle。
注释 5:nextState 已经在前面被置为 Idle,但是mState还没有改变依然是State::VSync,所以会执行 mVSyncSource->setVSyncEnabled(false)。
注释 6:mState 在前面被赋值为 idle,线程进行等待。
void stop() {
std::lock_guard lock(mMutex);
LOG_ALWAYS_FATAL_IF(!mStarted, "DispSyncInterface misuse: callback already stopped");
mStarted = false;
//取消上一次的定时
mRegistration.cancel();
}
mVSyncSource->setVSyncEnabled(false)最终会调用到CallbackRepeater->stop(),将重要的参数mStarted 置为false,并且取消掉上一次的定时。
而在CallbackRepeater的callback回调函数里面,通过mStarted来判断是否进行下一次的定时,这时候mStarted为false,所以停止了定时。
DispSyncSource.cpp文件里面。
void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
。。。。。。
{
std::lock_guard lock(mMutex);
if (!mStarted) {
return;
}
。。。。。。
}
}