vsync
vsync是Android4.1黄油计划引入的三大核心元素之一,主要为解决用户交互体验差的问题。Android通过VSync机制来提高显示效果,通常这个信号是由显示驱动产生,这样才能达到最佳效果。但是Android为了能运行在不支持VSync机制的设备上,也提供了软件模拟产生VSync信号的手段。vsync信号主要由闸刀控制线程EventControlThread,事件线程EventThread,控制线程VsyncThread,BitTube , messagequeue来实现。
1. VSYNC信号的传递
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
在SurfaceFlinger的init()函数
sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
vsyncPhaseoffsetNs, true, "APP"); //app同步源
mEventThread = new EventThread(vsyncSrc, *this, false);//事件线程
sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
sfVsyncPhaseOffsetNs, true, "sf");
mSFEventThread = new EventThread(sfVsyncSrc, *this, true); //
mEventQueue.setEventThread(mSFEventThread); //绑定事件队列
frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
mEvents = eventThread->createeventConnection(); //创建连接
mEvents->stealReceiveChannel(&mEventTube);//事件tunnel, mEventTube是BitTube
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, //向消息循环注册事件
MessageQueue::cb_eventReceiver, this); //cb_eventReceiver处理BitTunnel来的事件
}
frameworks/native/services/surfaceflinger/EventThread.cpp
创建Connection与BitTube通讯
sp<EventThread::Connection> EventThread::createEventConnection() const {
return new Connection(const_cast<EventThread*>(this));
}
frameworks/native/services/surfaceflinger/EventThread.cpp
初始化
EventThread::Connection::Connection(
const sp<EventThread>& eventThread)
: count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
{
}
frameworks/native/services/surfaceflinger/MessageQueue.cpp
//设置文件描述符
status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
outChannel->setReceiveFd(mChannel.moveReceiveFd());
return NO_ERROR;
}
frameworks/native/libs/gui/BitTube.cpp
void BitTube::setReceiveFd(base::unique_fd&& receiveFd) {
mReceiveFd = std::move(receiveFd);
}
frameworks/native/services/surfaceflinger/EventThread.h
Connection是EventThread的内部类
class EventThread : public Thread, private VSyncSource::Callback {
class Connection : public BndisplayEventConnection { //事件连接的Binder服务端
public:
explicit Connection(const sp<EventThread>& eventThread);
status_t postEvent(const DisplayEventReceiver::Event& event);
// count >= 1 : continuous event. count is the vsync rate
// count == 0 : one-shot event that has not fired
// count ==-1 : one-shot event that fired this round / disabled
int32_t count;
private:
virtual ~Connection();
virtual void onFirstRef();
status_t stealReceiveChannel(gui::BitTube* outChannel) override;
status_t setVsyncRate(uint32_t count) override;
void requestNextVsync() override; // asynchronous
sp<EventThread> const mEventThread;
gui::BitTube mChannel;
};
......
}
system/core/libutils/Looper.cpp
这部分属于消息循环,借助epoll的多路IO复用,阻塞机制;详细以后再讲,最终会执行Looper_callbackFunc callback回调函数也就是上文所描述的MessageQueue::cb_eventReceiver函数
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
}
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
.......
if (!callback.get()) {
if (! mAllowNonCallbacks) {
ALOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
return -1;
}
if (ident < 0) {
ALOGE("Invalid attempt to set NULL callback with ident < 0.");
return -1;
}
} else {
ident = POLL_CALLBACK;
}
{ // acquire lock
Automutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;
if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
struct epoll_event eventItem; //linux系统多路IO复用epoll
request.initEventItem(&eventItem);
ssize_t requestIndex = mRequests.indexofKey(fd); //查找requestIndex
if (requestIndex < 0) { //未找到则新建
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));
return -1;
}
mRequests.add(fd, request); //加入请求队列
} else { //找到则更新修改
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) { /如果/修改失败,新建
if (errno == ENOENT) {
// Tolerate ENOENT because it means that an older file descriptor was
// closed before its callback was unregistered and meanwhile a new
// file descriptor with the same number has been created and is now
// being registered for the first time. This error may occur naturally
// when a callback has the side-effect of closing the file descriptor
// before returning and unregistering itself. Callback sequence number
// checks further ensure that the race is benign.
//
// Unfortunately due to kernel limitations we need to rebuild the epoll
// set from scratch because it may contain an old file handle that we are
// now unable to remove since its file descriptor is no longer valid.
// No such problem would have occurred if we were using the poll system
// call instead, but that approach carries others disadvantages.
#if DEBUG_CALLBACKS
ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor "
"being recycled, falling back on EPOLL_CTL_ADD: %s",
this, strerror(errno));
#endif
epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); //新建
if (epollResult < 0) {
ALOGE("Error modifying or adding epoll events for fd %d: %s",
fd, strerror(errno));
return -1;
}
scheduleEpollRebuildLocked();
} else { //修改成功
ALOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));
return -1;
}
}
mRequests.replaceValueAt(requestIndex, request); //替换request
}
} // release lock
return 1;
}
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger启动时会对消息队列初始化
void SurfaceFlinger::onFirstRef()
{
mEventQueue.init(this);
}
frameworks/native/services/surfaceflinger/MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
mFlinger = flinger;
mLooper = new Looper(true);
mhandler = new Handler(*this);
}
frameworks/native/services/surfaceflinger/EventThread.cpp
EventThread开始处理队列事件
bool EventThread::threadLoop() {
DisplayEventReceiver::Event event;
vector< sp<EventThread::Connection> > signalConnections; //连接队列
signalConnections = waitforEvent(&event); //等待
// dispatch events to listeners...
const size_t count = signalConnections.size(); //连接数量
for (size_t i=0 ; i<count ; i++) {
const sp<Connection>& conn(signalConnections[i]); //取
// now see if we still need to report this event
status_t err = conn->postEvent(event); //提交事件
if (err == -EAGAIN || err == -EWOULDBLOCK) {
// The destination doesn't accept events anymore, it's probably
// full. For now, we just drop the events on the floor.
// FIXME: Note that some events cannot be dropped and would have
// to be re-sent later.
// Right-now we don't have the ability to do this.
ALOGW("EventThread: dropping event (%08x) for connection %p",
event.header.type, conn.get());
} else if (err < 0) {
// handle any other error on the pipe as fatal. the only
// reasonable thing to do is to clean-up this connection.
// The most common error we'll get here is -EPIPE.
removeDisplayEventConnection(signalConnections[i]);
}
}
return true;
}
frameworks/native/services/surfaceflinger/EventThread.cpp
向BitTube发送事件
status_t EventThread::Connection::postEvent(
const DisplayEventReceiver::Event& event) {
ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
return gui::BitTube::sendObjects(dataChannel, events, count);
}
frameworks/native/libs/gui/BitTube.cpp
ssize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) {
const char* vaddr = reinterpret_cast<const char*>(events);
ssize_t size = tube->write(vaddr, count * objSize); //写数据
// should never happen because of SOCK_SEQPACKET
LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
"BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were "
"sent!)",
count, objSize, size);
// ALOGE_IF(size<0, "error %d sending %d events", size, count);
return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
frameworks/native/libs/gui/BitTube.cpp
ssize_t BitTube::write(void const* vaddr, size_t size) {
ssize_t err, len;
do {
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); //往套接发送信号
// cannot return less than size, since we're using SOCK_SEQPACKET
err = len < 0 ? errno : 0;
} while (err == EINTR);
return err == 0 ? len : -err;
}
rameworks/native/libs/gui/BitTube.cpp
从BitTube的初始化函数可以看出使用了套接来通讯
void BitTube::init(size_t rcvbuf, size_t sndbuf) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
// since we don't use the "return channel", we keep it small...
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
mReceiveFd.reset(sockets[0]);
mSendFd.reset(sockets[1]);
} else {
mReceiveFd.reset();
ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
}
}
frameworks/native/services/surfaceflinger/MessageQueue.cpp
消息循环的回调函数cb_eventReceiver主动读取BitTube端的数据
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) {
mHandler->dispatchinvalidate(); //派发事件
break;
}
}
}
return 1;
}
那么为什么消息循环会知道Event何时被发送到BitTube,然后从BitTube的socket接收端读取呢,我们不得不回到setEventThread函数,设计得相当精妙
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
//mEventTube是 gui::BitTube,也就是mEventTube.getFd() 是消息队列与BitTube共用的文件描述符
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
MessageQueue::cb_eventReceiver, this);
}
frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel,
Event* events, size_t count)
{
return gui::BitTube::recvObjects(dataChannel, events, count);
}
frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) {
char* vaddr = reinterpret_cast<char*>(events);
ssize_t size = tube->read(vaddr, count * objSize);
// should never happen because of SOCK_SEQPACKET
LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
"BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were "
"received!)",
count, objSize, size);
// ALOGE_IF(size<0, "error %d receiving %d events", size, count);
return size < 0 ? size : size / static_cast<ssize_t>(objSize);
}
frameworks/native/libs/gui/DisplayEventReceiver.cpp
ssize_t BitTube::read(void* vaddr, size_t size) {
ssize_t err, len;
do {
len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
err = len < 0 ? errno : 0;
} while (err == EINTR);
if (err == EAGAIN || err == EWOULDBLOCK) {
// EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the
// client should care about.
return 0;
}
return err == 0 ? len : -err;
}
frameworks/native/services/surfaceflinger/MessageQueue.cpp
cb_eventReceiver函数读取到BitTube的数据后调用:Handler::dispatchInvalidate函数,最终由Handler::handleMessage处理
void MessageQueue::Handler::dispatchInvalidate() {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
}
//处理来自消息对列的消息,调用SurfaceFlinger来处理
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:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
处理同步事件,对应于Hardwarecomposer调用册是onVSyncReceived
void SurfaceFlinger::onMessageReceived(int32_t what) {
...... 在此处理同步事件
}
2. vsync信号的控制
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
SurfaceFlinger构造函数中初始化DispSync
......
mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset); //初始化DispSync
......
frameworks/native/services/surfaceflinger/DispSync.cpp
主要启动显示同步线程
void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
mignorePresentfences = !hasSyncFramework;
mPresentTimeOffset = dispSyncPresentTimeOffset;
mThread->run("DispSync", priority_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); //启动线程
}
frameworks/native/services/surfaceflinger/DispSync.cpp
线程循环
virtual bool threadLoop() {
status_t err;
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
while (true) {
Vector<CallbackInvocation> callbackInvocations; //回调向量
nsecs_t targetTime = 0;
{ // Scope for lock
Mutex::Autolock lock(mMutex);
if (kTraceDetailedInfo) {
ATRACE_INT64("DispSync:Frame", mFrameNumber);
}
ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
++mFrameNumber;
if (mStop) {
return false;
}
if (mPeriod == 0) {
err = mCond.wait(mMutex); //事件等待signal
if (err != NO_ERROR) {
ALOGE("error waiting for new events: %s (%d)",
strerror(-err), err);
return false;
}
continue;
}
targetTime = computeNextEventTimeLocked(now); //计算下一次执行时间
bool isWakeup = false;
if (now < targetTime) { //事件还没到
if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
if (targetTime == INT64_MAX) {
ALOGV("[%s] Waiting forever", mName);
err = mCond.wait(mMutex); //等待
} else {
ALOGV("[%s] Waiting until %" PRId64, mName,
ns2us(targetTime));
err = mCond.waitRelative(mMutex, targetTime - now); //设定等待时间
}
if (err == TIMED_OUT) {
isWakeup = true; //超时唤醒
} else if (err != NO_ERROR) {
ALOGE("error waiting for next event: %s (%d)",
strerror(-err), err);
return false;
}
}
now = systemTime(SYSTEM_TIME_MONOTONIC);
// Don't correct by more than 1.5 ms
static const nsecs_t kMaxWakeupLatency = us2ns(1500);
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) +
(now - targetTime)) / 64;
mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
if (kTraceDetailedInfo) {
ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
}
}
callbackInvocations = gatherCallbackInvocationsLocked(now); //回调转换
}
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations); //调用回调
}
}
return false;
}
frameworks/native/services/surfaceflinger/DispSync.cpp
将mEventListeners回调队列转到callbackInvocations
Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
if (kTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
ns2us(now));
Vector<CallbackInvocation> callbackInvocations;
nsecs_t onePeriodAgo = now - mPeriod;
for (size_t i = 0; i < mEventListeners.size(); i++) {
nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
onePeriodAgo);
if (t < now) {
CallbackInvocation ci;
ci.mCallback = mEventListeners[i].mCallback;
ci.mEventTime = t;
ALOGV("[%s] [%s] Preparing to fire", mName,
mEventListeners[i].mName);
callbackInvocations.push(ci);
mEventListeners.editItemAt(i).mLastEventTime = t;
}
}
return callbackInvocations;
}
frameworks/native/services/surfaceflinger/DispSync.cpp
执行回调,此回调类型为DispSync::Callback,再SurfaceFlinger我们向EventThread传入了DispSyncSource对象
void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
if (kTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
}
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
DispSyncSource是SyncSource,DispSync::Callback子类,DispSyncSource 通过addeventlistener向DispSync注册监听
class DispSyncSource : public VSyncSource, private DispSync::Callback {
public:
DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
const char* name) :
mName(name),
mValue(0),
mTraceVsync(traceVsync),
mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
mVsyncEventLabel(String8::format("VSYNC-%s", name)),
mDispSync(dispSync),
mCallbackMutex(),
mCallback(),
mVsyncMutex(),
mPhaseOffset(phaseOffset),
mEnabled(false) {}
virtual ~DispSyncSource() {}
virtual void setVSyncEnabled(bool enable) { //注册DispSync::Callback回调事件
Mutex::Autolock lock(mVsyncMutex);
if (enable) {
status_t err = mDispSync->addEventListener(mName, 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;
}
virtual void setCallback(const sp<VSyncSource::Callback>& callback) { //绑定 VSyncSource::Callback
Mutex::Autolock lock(mCallbackMutex);
mCallback = callback;
}
......
private:
virtual void onDispSyncEvent(nsecs_t when) { //执行VSyncSource::Callback->onVSyncEvent
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); //回调
}
}
......
};
frameworks/native/services/surfaceflinger/EventThread.cpp
回调函数VSyncSource::Callback在EventThread被执行
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(); //发出同步广播
}
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
闸刀控制线程将通过signal控制同步事件
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
bool EventControlThread::threadLoop() {
enum class VsyncState {Unset, On, Off};
auto currentVsyncState = VsyncState::Unset;
while (true) {
auto requestedVsyncState = VsyncState::On;
{
Mutex::Autolock lock(mMutex);
requestedVsyncState =
mVsyncEnabled ? VsyncState::On : VsyncState::Off;
while (currentVsyncState == requestedVsyncState) {
status_t err = mCond.wait(mMutex);
if (err != NO_ERROR) {
ALOGE("error waiting for new events: %s (%d)",
strerror(-err), err);
return false;
}
requestedVsyncState =
mVsyncEnabled ? VsyncState::On : VsyncState::Off;
}
}
bool enable = requestedVsyncState == VsyncState::On;
#ifdef USE_HWC2
mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
#else
mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
SurfaceFlinger::EVENT_VSYNC, enable);
#endif
currentVsyncState = requestedVsyncState;
}
return false;
}
使用了Hardware同步
void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
ATRACE_CALL();
Mutex::Autolock lock(mStateLock);
getHwComposer().setVsyncEnabled(disp,
enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
}
来自Hardware的同步回调
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
hwc2_display_t displayId, int64_t timestamp) {
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); //计算是否需要硬件同步
}
}
if (needsHwVsync) {
enableHardwareVsync(); //使能硬件同步
} else {
disableHardwareVsync(false);
}
}
计算是否需要硬件同步
bool DispSync::addResyncSample(nsecs_t timestamp) {
Mutex::Autolock lock(mMutex);
ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
mResyncSamples[idx] = timestamp;
if (mNumResyncSamples == 0) { //如果重采样数为0
mPhase = 0;
mReferenceTime = timestamp;
ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
"mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
ns2us(mReferenceTime));
mThread->updateModel(mPeriod, mPhase, mReferenceTime); //更新
}
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
mNumResyncSamples++;
} else {
mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
}
updateModelLocked();
......
return !modelLocked;
}
将会触发同步事件信号,通知DispSyncThread执行回调函数
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
mReferenceTime = referenceTime;
ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
" mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
ns2us(mPhase), ns2us(mReferenceTime));
mCond.signal(); //执行
}
使能硬件同步也会放出signal信号,触发同步
void SurfaceFlinger::enableHardwareVsync() {
Mutex::Autolock _l(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
mPrimaryDispSync.beginResync();
//eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mEventControlThread->setVsyncEnabled(true); //开闸
mPrimaryHWVsyncEnabled = true;
}
}
至此,我们从vsync信号的产生传递,vsync切换两个角度来看整个同步过程,vsync信号主要通过EventThread处理vsync事件,消息循环和BitTube来进行通讯,EventControlThread进行软硬件信号的切换,DispSync处理vsync切换事件并把切换事件回调给EventThread处理,可以说设计得相当精妙。共勉,共勉!
相关阅读
VSYNC在显示周期内同步一些确定的事件,APP在VSYNC结束的时间点绘制画面,也是在这个时间点SurfaceFlinger进行画面合成。这种机制消