必威体育Betway必威体育官网
当前位置:首页 > IT技术

Android8.0 图形引擎的心跳 - Vsync信号

时间:2019-07-29 00:10:00来源:IT技术作者:seo实验室小编阅读:79次「手机版」
 

vsync

vsyncAndroid4.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)实现原理

VSYNC在显示周期内同步一些确定的事件,APP在VSYNC结束的时间点绘制画面,也是在这个时间点SurfaceFlinger进行画面合成。这种机制消

分享到:

栏目导航

推荐阅读

热门阅读