码迷,mamicode.com
首页 > 其他好文 > 详细

VSYNC信号传递流向

时间:2016-05-07 08:51:08      阅读:697      评论:0      收藏:0      [点我收藏+]

标签:

vsync信号源产生地
1.硬件支持
2.软件模拟

SurfaceFlinger创建的init会初始创建HWComposer
void SurfaceFlinger::init() {
    mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));
}

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& flinger,
        EventHandler& handler)
{
    bool needVSyncThread = true;

    loadHwcModule(); 
    if (mHwc) {//存在加载成功composer硬件抽象层,则用硬件支持的vSync信号
        if (mHwc->registerProcs) {
            mCBContext->hwc = this;
            mCBContext->procs.invalidate = &hook_invalidate;
            mCBContext->procs.vsync = &hook_vsync;//硬件回调的vsync信号处理函数
            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
                mCBContext->procs.hotplug = &hook_hotplug;
            else
                mCBContext->procs.hotplug = NULL;
            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

        //先关闭vsync信号
        needVSyncThread = false;
        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);   
    }

    //软件模拟的vsync信号
    if (needVSyncThread) {       
        mVSyncThread = new VSyncThread(*this);
    }
}


void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,int64_t timestamp) {
    //procs是我们传过去的,根据这个指针我们可以转化成外部的我们自己用的指针
    //硬件层总是用这种技巧  一般procs作为另一个struct结构的第一成员,类似与c++中的继承关系了
    cb_context* ctx = reinterpret_cast<cb_context*>(const_cast<hwc_procs_t*>(procs));
    ctx->hwc->vsync(disp, timestamp);
}


void HWComposer::vsync(int disp, int64_t timestamp) {
    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
       //记录一下最后一次产生的vsync信号的时间值
       if (timestamp == mLastHwVSync[disp]) {
           return;
       }
       mLastHwVSync[disp] = timestamp;
       //通知外面  ,mEventHandler是构造函数初始化的,就是SurfaceFlinger
       //查看一下应用这个函数的地方还会找到bool HWComposer::VSyncThread::threadLoop() 这个就是
       //软件模拟的vsync.
       //所以不管软件还是硬件的vsync信号最后都有mEventHandler.onVSyncReceived进行处理
       mEventHandler.onVSyncReceived(disp, timestamp);
    }
}

HWComposer初始化后,vsync信号的输出地就是mEventHandler.onVSyncReceived  (SurfaceFlinger::onVSyncReceived)


void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
    bool needsHwVsync = false;

    {
        Mutex::Autolock _l(mHWVsyncLock);
        if (type == 0 && mPrimaryHWVsyncEnabled) {
        //添加采样时间点  mPrimaryDispSync通过采样点计算出vsync信号的触发间隔和波动范围
        //然后通过软件模拟出vsync信号,如果不需要采样点了就返回false,这样外部根据返回值
        //开启和关闭硬件(HWComposer中产生的)vsync信号,据说可以省电
            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
        }
    }

    //开启关闭HWComposer的vsync
    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
}


//关闭vsync
void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
    Mutex::Autolock _l(mHWVsyncLock);
    if (mPrimaryHWVsyncEnabled) {
        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
    //又是一个控制线程,线程中会调用eventControl(HWC_DISPLAY_PRIMARY
    //setVsyncEnabled设置变量后激活线程
        mEventControlThread->setVsyncEnabled(false);

    mPrimaryDispSync.endResync();
        mPrimaryHWVsyncEnabled = false;
    }
    if (makeUnavailable) {
        mHWVsyncAvailable = false;
    }
}

//开启vsync
void SurfaceFlinger::enableHardwareVsync() {
    mEventControlThread->setVsyncEnabled(true);
}

//添加采样点
bool DispSync::addResyncSample(nsecs_t timestamp) {
    Mutex::Autolock lock(mMutex);

    //timerstamp添加到一个固定大小的queue中,
    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
    mResyncSamples[idx] = timestamp;
    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
        mNumResyncSamples++;
    } else {
        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
    }

    //通过采样点计算mPeriod
    updateModelLocked();


    //如果计算出的间隔不是0就返回false,外部就关闭了硬件vsync
    return mPeriod == 0 || mError > errorThreshold;
}


void DispSync::updateModelLocked() {
    //采样点大于MIN_RESYNC_SAMPLES_FOR_UPDATE后才能计算mPeriod
    if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
        nsecs_t durationSum = 0;
        for (size_t i = 1; i < mNumResyncSamples; i++) {
            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
            size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
            durationSum += mResyncSamples[idx] - mResyncSamples[prev];
        }

        //计算一下vsync间隔
        mPeriod = durationSum / (mNumResyncSamples - 1);

        //下面这一段搞这么复杂就是计算一个vsync偏差(mPhase相位),我感觉可以简单点处理,没必要sin,cos等
    // 下面意思是 把mPeriod转成弧度(2pi),然后计算每次采样间隔跟mPeriod差出的弧度值
    //根据弧度转成x,y ,累加x,y然后取平局偏差 ,然后计算平均的偏差弧度,然后转成mPeriod对应的长度单位
        double sampleAvgX = 0;
        double sampleAvgY = 0;
        double scale = 2.0 * M_PI / double(mPeriod);
        for (size_t i = 0; i < mNumResyncSamples; i++) {
            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
            nsecs_t sample = mResyncSamples[idx];
            double samplePhase = double(sample % mPeriod) * scale;
            sampleAvgX += cos(samplePhase);
            sampleAvgY += sin(samplePhase);
        }

        sampleAvgX /= double(mNumResyncSamples);
        sampleAvgY /= double(mNumResyncSamples);

        mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);

        if (mPhase < 0) {
            mPhase += mPeriod;
        }

        //更新模拟线程的数据
        mThread->updateModel(mPeriod, mPhase);
    }
  }

  //产生外部用的vsync信号
  virtual bool DispSyncThread::threadLoop() {
        status_t err;
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        nsecs_t nextEventTime = 0;

        while (true) {
            Vector<CallbackInvocation> callbackInvocations;
            nsecs_t targetTime = 0;

            {   //等待设置新的mPeriod
                Mutex::Autolock lock(mMutex);
                if (mPeriod == 0) {
                    err = mCond.wait(mMutex);
                    continue;
                }

                //根据当前时间计算下一次什么时候醒过来
                nextEventTime = computeNextEventTimeLocked(now);
                targetTime = nextEventTime;
                err = mCond.waitRelative(mMutex, targetTime - now);

        //计算需要通知的callback
                now = systemTime(SYSTEM_TIME_MONOTONIC);
                callbackInvocations = gatherCallbackInvocationsLocked(now);
            }

            //通知监听vsync信号的connect
            if (callbackInvocations.size() > 0) {
                fireCallbackInvocations(callbackInvocations);
            }
        }

        return false;
    }

    //添加监听sync信号的callback
    status_t DispSyncThread::addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
        EventListener listener;
        listener.mPhase = phase;
        listener.mCallback = callback;
        listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
        mEventListeners.push(listener);

        mCond.signal();
        return NO_ERROR;
    }

    status_t DispSync::addEventListener(nsecs_t phase,const sp<Callback>& callback) {
        Mutex::Autolock lock(mMutex);
        return mThread->addEventListener(phase, callback);
    }


    SurfaceFlinger::init(){
       // DispSyncSource  ,设置成mPrimaryDispSync的回调,控制mPrimaryDispSync模拟的vsync开启关闭
       sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,vsyncPhaseOffsetNs, true);
       //需要监听vsync,plugin信号的connenct,调用SurfaceFlinger::createDisplayEventConnection就创建一个connect
       mEventThread = new EventThread(vsyncSrc);

       //驱动刷新vsync信号处理,
       sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,sfVsyncPhaseOffsetNs, false);       
       mSFEventThread = new EventThread(sfVsyncSrc);
       //MessageQueue.setEventThread后会监听socketpair的另一端,当有vsync信号后MessageQueue就知道了
       mEventQueue.setEventThread(mSFEventThread);

       //控制HWSComposer中的VSYNC开启关闭
       mEventControlThread = new EventControlThread(this);
       mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
    }


    bool EventThread::threadLoop() {
       DisplayEventReceiver::Event event;
       //等待有事件发生的connect
       Vector< sp<EventThread::Connection> > signalConnections;
       signalConnections = waitForEvent(&event);

       //消息转发出去,postEvent内部通过sockpair传递数据
       const size_t count = signalConnections.size();
       for (size_t i=0 ; i<count ; i++) {
          const sp<Connection>& conn(signalConnections[i]);
          status_t err = conn->postEvent(event);     
       }
    return true;
}


Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
{

    do {
        bool eventPending = false;
        bool waitForVSync = false;

        size_t vsyncCount = 0;
    //是否有vSYNC信号
        nsecs_t timestamp = 0;
        for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
            timestamp = mVSyncEvent[i].header.timestamp;
            if (timestamp) {
                *event = mVSyncEvent[i];
                mVSyncEvent[i].header.timestamp = 0;
                vsyncCount = mVSyncEvent[i].vsync.count;
                break;
            }
        }

        //是否有plugin信号
        if (!timestamp) {
            eventPending = !mPendingEvents.isEmpty();
            if (eventPending) {
                // we have some other event to dispatch
                *event = mPendingEvents[0];
                mPendingEvents.removeAt(0);
            }
        }

        //查找对vSYnc有兴趣的connnect,如果没有找plugin信号,移除无效的connect
        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            if (connection != NULL) {
                bool added = false;
                if (connection->count >= 0) {
                    waitForVSync = true;
                    if (timestamp) {
                        if (connection->count == 0) {
                            connection->count = -1;
                            signalConnections.add(connection);
                            added = true;
                        } else if (connection->count == 1 ||
                                (vsyncCount % connection->count) == 0) {

                            signalConnections.add(connection);
                            added = true;
                        }
                    }
                }

                if (eventPending && !timestamp && !added) {
                    signalConnections.add(connection);
                }
            } else {
                mDisplayEventConnections.removeAt(i);
                --i; --count;
            }
        }

        //是否需要关闭vsync ,如果没有关心vsync的connect
        if (timestamp && !waitForVSync) {
            disableVSyncLocked();
        } else if (!timestamp && waitForVSync) {
            enableVSyncLocked();
        }


    //如果没有了则等待一段时间
        if (!timestamp && !eventPending) {
            if (waitForVSync) {
                bool softwareSync = mUseSoftwareVSync;
                nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
                if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
                    if (!softwareSync) {
                        ALOGW("Timed out waiting for hw vsync; faking it");
                    }
                    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
                    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
                    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncEvent[0].vsync.count++;
                }
            } else {
                mCondition.wait(mLock);
            }
        }
    } while (signalConnections.isEmpty());

    return signalConnections;
}


当有vsync信号后会触发激活线程
void EventThread::onVSyncEvent(nsecs_t timestamp);

当有plugin信号后会触发激活线程
void EventThread::onHotplugReceived(int type, bool connected);

调用connect创建一个对事件感兴趣的connect
sp<Connection> EventThread::createEventConnection();

  class Connection : public BnDisplayEventConnection {
        //触发事件,在 EventThread::threadLoop中
        status_t postEvent(const DisplayEventReceiver::Event& event);

        //内部包装了一个socke_pair的句柄,当postEvent会向里面写数据
    //如果又兴趣则需要取出句柄监听读
        virtual sp<BitTube> getDataChannel() const;
    };



//MessageQueue
class MessageQueue {
}

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();
    mEventTube = mEvents->getDataChannel();
    //监听socketpair的另一端
    mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);
}

//vsync回调
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];

    //socketpair读出消息来
    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
         //如果vsync信号则派发出去
#if INVALIDATE_ON_VSYNC
                mHandler->dispatchInvalidate();
#else
                mHandler->dispatchRefresh();
#endif
                break;
            }
        }
    }
    return 1;
}

//消息派发
void MessageQueue::Handler::dispatchRefresh() {
    if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
    }
}

void MessageQueue::Handler::dispatchInvalidate() {
    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
        //转发到surfaceflinger
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
        //转发到surfaceflinger
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case TRANSACTION:
        //转发到surfaceflinger
            android_atomic_and(~eventMaskTransaction, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

//处理消息把,刷新界面
void SurfaceFlinger::onMessageReceived(int32_t what) {
    ATRACE_CALL();
    switch (what) {
    case MessageQueue::TRANSACTION:
        handleMessageTransaction();
        break;
    case MessageQueue::INVALIDATE:
        handleMessageTransaction();
        handleMessageInvalidate();
        signalRefresh();
        break;
    case MessageQueue::REFRESH:
        handleMessageRefresh();
        break;
    }
}


总结:
   当SurfaceFlinger.init以后,就会定时收到onMessageReceived消息,驱动则刷新界面

   void SurfaceFlinger::init() {
    //硬件抽象层,vsync信号发源地,通过SurfaceFlinger加到mPrimaryDispSync中
    mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));

    // 其他需要vsync信号的,通过mEventThread建立,不影响刷新的
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true);
    mEventThread = new EventThread(vsyncSrc);

    //界面刷新vsync信号,在一个单独线程中转发,可能为了提交刷新效率
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, false);
    mSFEventThread = new EventThread(sfVsyncSrc);
    mEventQueue.setEventThread(mSFEventThread);

    //控制HWComposer 中vsync信号开启关闭
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
}

//处理vsync信号上来的刷新等消息
void SurfaceFlinger::onMessageReceived(int32_t what) {
   ....
}

VSYNC信号传递流向

标签:

原文地址:http://blog.csdn.net/u014409795/article/details/51330642

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!