Android8.0 图形引擎的心跳 - 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处理,可以说设计得相当精妙。共勉,共勉!
更多相关文章
- C语言函数的递归(上)
- android 实现表格上下滑,左右滑,并且标题也跟着滑
- Android(安卓)动画框架详解
- Android加载动态库不成功处理方法
- 为什么Looper.loop()死循环不会导致ANR
- Android(安卓)JNI概述
- ios开发之ios中控件
- Android技术博文汇总
- 从华为事件,看 Google Android(安卓)的独断专制!