Android 14 - 绘制体系 - VSync(1)

news2024/11/17 19:37:44

整体框架

VsyncConfiguration一些基本参数配置比如PhaseOffsetsWorkDuration

Scheduler:作为SF生成和派发VSync的整体调度器,主要面向SurfaceFlinger提供VSync相关接口。Scheduler包含对所有屏幕的VSync的控制。本身MessageQueue子类

RefreshRateSelector每个Display屏幕对应一个RefreshRateSelector用于基于屏幕支持的刷新率范围,选择一个合适Refresh RateFrame Rate传递VSyncSchedule作为软件VSync生成重要因素

VsyncScheduleVsync生成的调度器。每个屏幕对应一个VsyncSchedule。包含一个Tracker(VSyncPredictor)、一个Dispatch(VSyncDispatchTimerQueue)、一个Controller(VSyncReactor)。一方面对接硬件VSync信号开关一方面对接软件VSync计算输出

VSyncPredictor 在VsyncSchedule语境中一个Tracker负责综合各方因素根据算法由硬件VSync计算出软件VSync周期工具类

VSyncDispatchTimerQueue在VsyncSchedule语境中一个Dispather负责VSync分发使用者

VSyncCallbackRegistration代表一个VSync使用者的注册比如常见的针对上层应用的VSYNC-app、针对SurfaceFlinger合成的VSYNC-sf对应一个VSyncCallbackRegistration另外客户端还有一个VSYNC-appSf

EventThread处理客户端应用VSYNC的一个独立线程。期内维护一个不断请求VSYNC的死循环。比如VSYNC-app,一方面通过VSyncCallbackRegistration申请一次VSYNC另一方VSYNC生成通过ConnectionVSYNC发送给DisplayEventReceiver也就是VSYNC的终端接收者。一般情况两个EventThread一个是针对客户端应用侧VSYNC-app另一个客户端使用SF同步信号VSYNC-appSf

DisplayEventReceiver通过socket机制提供了一SF客户端应用传递VSYNC通道服务端EventThread通过DisplayEventReceiver发送VSYNC事件客户端Choreographer通过DisplayEventReceiver接收到VSYNC下发ViewRootImp驱动下一次绘制渲染

Android 13以后VSYNC架构变化之一是给SF使用的VSYNC-sf信号通过EventThread维护而是直接Schedule维护。供客户端应用使用的VSYN-app仍然EventThread维护另外新增一个VSYN-appSf信号也是EventThread维护主要作用如果客户端使用SF同步信号可以切换VSYNC-appSf这个信号Android 13之前这个机制通过VSYNC-sf实现Android 13SF专门使用VSYNC-sfEventThread剥离出来直接Schedule维护VSYN-appSf专门针对客户端

关键参数

探索VSync机制需要一些关键参数概念有所了解dumpsys SurfaceFlinger入手

屏幕刷新率

ColorMode设备支持ColorMode可根据系统设置应用自身设定的颜色模式最终决定使用那个ColorMode

deviceProductInfo: 屏幕设备信息manufacturerPnpId=QCMPlug and Play即插即用设备唯一识别码

activeMode:当前使用帧率模式

displayModes:当前屏幕支持帧率模式打印信息支持60Hz90Hz两种帧率

displayManagerPolicy当前采用帧率管理策略primaryRanges代表选取帧率通常采纳范围,如果用户通过setFrameRate手动指定一个帧率,其可能超出primaryRanges的范围;appRequestRanges代表用户可以指定帧率范围最终帧率可能超过primaryRanges但绝不会超过appRequestRanges

主要组件的初始化

SurfaceFlinger的初始化

SurfaceFlinger启动源于SystemServer执行main_surfaceflinger.cppmain方法

int main(int, char**) {
    ...
    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
    ...
    flinger->init();
    ...
}

surfaceflinger::createSurfaceFlinger()实现platform/frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.cpp

sp<SurfaceFlinger> createSurfaceFlinger() {
    static DefaultFactory factory;

    return sp<SurfaceFlinger>::make(factory);
}

随后调用SurfaceFlingerinit方法

platform/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    ...
    sp<const DisplayDevice> display;
    if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
        const auto& displays = mCurrentState.displays;

        const auto& token = displays.keyAt(*indexOpt);
        const auto& state = displays.valueAt(*indexOpt);

        processDisplayAdded(token, state);
        mDrawingState.displays.add(token, state);

        display = getDefaultDisplayDeviceLocked();
    }
    ...
    initScheduler(display);
    ...
}

构建RefreshRateSelector

上面的代码中调用了processDisplayAdded添加主屏幕,后续挂载一个新屏幕也会走此流程:

void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                         const DisplayDeviceState& state) {
     ...
     auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,
                                                 displaySurface, producer);
     ...
 }
 
 sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
        const wp<IBinder>& displayToken,
        std::shared_ptr<compositionengine::Display> compositionDisplay,
        const DisplayDeviceState& state,
        const sp<compositionengine::DisplaySurface>& displaySurface,
        const sp<IGraphicBufferProducer>& producer) {
        ...
         creationArgs.refreshRateSelector =
                mPhysicalDisplays.get(physical->id)
                        .transform(&PhysicalDisplay::snapshotRef)
                        .transform([&](const display::DisplaySnapshot& snapshot) {
                            return std::make_shared<
                                    scheduler::RefreshRateSelector>(snapshot.displayModes(),
                                                                    creationArgs.activeModeId,
                                                                    config);
                        })
                        .value_or(nullptr);
        ...
        sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
 
 }
                                             

上面每个Display构建一个refreshRateSelectorRefreshRateSelector

初始化Scheduler

VSync相关初始化都在initScheduler

void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
    const auto activeMode = display->refreshRateSelector().getActiveMode();
    const Fps activeRefreshRate = activeMode.fps;
    // 创建配置
    mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
    // 创建Scheduler
    mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
                                             static_cast<ISchedulerCallback&>(*this), features,
                                             std::move(modulatorPtr));
    // 注册屏幕每个屏幕构建一个VsyncSchedule对象
    mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
    mScheduler->startTimers();
    // 创建VSYNC-app对应EventThread
    mAppConnectionHandle =
		mScheduler->createEventThread(Scheduler::Cycle::Render,
									  mFrameTimeline->getTokenManager(),
									  /* workDuration */ configs.late.appWorkDuration,
									  /* readyDuration */ configs.late.sfWorkDuration);
    // 创建VSYNC-appSf对应的EventThread
mSfConnectionHandle =
		mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
									  mFrameTimeline->getTokenManager(),
									  /* workDuration */ activeRefreshRate.getPeriod(),
									  /* readyDuration */ configs.late.sfWorkDuration);
    // 创建VSYNC-sf对应调度器
    mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
                          *mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
      ...
}

VsyncSchedule创建Scheduler::registerDisplay

platform/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures,
                                                       [this](PhysicalDisplayId id, bool enable) {
                                                           onHardwareVsyncRequest(id, enable);
                                                       });

    registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}

VsyncSchedule构造函数初始化

platform/frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp

VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
                             RequestHardwareVsync requestHardwareVsync)
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}

VsyncSchedule构造几个重要组件

VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
                             RequestHardwareVsync requestHardwareVsync)
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                        : nullptr) {}

其中mTracker本质上VSyncPredictor

VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
    // TODO(b/144707443): Tune constants.
    constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
    constexpr size_t kHistorySize = 20;
    constexpr size_t kMinSamplesForPrediction = 6;
    constexpr uint32_t kDiscardOutlierPercent = 20;

    return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
                                            kMinSamplesForPrediction, kDiscardOutlierPercent);
}

mDispatch本质上VSyncDispatchTimerQueue

VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
    using namespace std::chrono_literals;

    // TODO(b/144707443): Tune constants.
    constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
    constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;

    return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), std::move(tracker),
                                                     kGroupDispatchWithin.count(),
                                                     kSnapToSameVsyncWithin.count());
}

mController本质上VSyncReactor

VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId id,
                                                             VsyncTracker& tracker,
                                                             FeatureFlags features) {
    // TODO(b/144707443): Tune constants.
    constexpr size_t kMaxPendingFences = 20;
    const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);

    auto reactor = std::make_unique<VSyncReactor>(id, std::make_unique<SystemClock>(), tracker,
                                                  kMaxPendingFences, hasKernelIdleTimer);

    reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
    return reactor;
}

VSYNC-appVSYNC-appSf这两个信号是在EventThread维护看下createEventThread

platform/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {
  // 根据cycle参数不同选择app还是appSf
    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           getVsyncSchedule(), tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    // 创建Connection
    handle = createConnection(std::move(eventThread));
    return handle;
}

EventThread构造函数

EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
                         std::chrono::nanoseconds workDuration,
                         std::chrono::nanoseconds readyDuration)
      : mThreadName(name),
      // ATRACE名称
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        // VSYNC计算时使用的偏移量
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        // VSYNC计算时使用的偏移量
        mReadyDuration(readyDuration),
        mVsyncSchedule(std::move(vsyncSchedule)),
        // 一个VSYNC请求者的具体处理
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback()/*VSync生成后的回调函数*/, name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
    LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
            "getVsyncPeriodFunction must not be null");

    mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
        std::unique_lock<std::mutex> lock(mMutex);
        threadMain(lock);
    });

上面方法通过createConnection创建VSync事件派发通道

platform/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
    const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
    ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);

    auto connection = createConnectionInternal(eventThread.get());

    std::lock_guard<std::mutex> lock(mConnectionsLock);
    mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
    return handle;
}

sp<EventThreadConnection> Scheduler::createConnectionInternal(
        EventThread* eventThread, EventRegistrationFlags eventRegistration,
        const sp<IBinder>& layerHandle) {
    int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
    auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
    mLayerHistory.attachChoreographer(layerId, connection);
    return connection;
}

最终是由EventThread创建Connection:

platform/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

sp<EventThreadConnection> EventThread::createEventConnection(
        ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
    return sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
                                           IPCThreadState::self()->getCallingUid(),
                                           std::move(resyncCallback), eventRegistration);
}

VSYNC-app的请求流程

VSYNC-appEventThread维护VSYNC-app触发多种因素包括新屏幕挂载客户端主动请求EVentThread线程内部自发

EventThread内部自发为例

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.
        if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
                if (event->hotplug.connected && !mVSyncState) {
                    mVSyncState.emplace(event->header.displayId);
                } else if (!event->hotplug.connected && mVSyncState &&
                           mVSyncState->displayId == event->header.displayId) {
                    mVSyncState.reset();
                }
            }
        }

        bool vsyncRequested = false;

        // Find connections that should consume this event.
        auto it = mDisplayEventConnections.begin();
        while (it != mDisplayEventConnections.end()) {
            if (const auto connection = it->promote()) {
                if (event && shouldConsumeEvent(*event, connection)) {
                    consumers.push_back(connection);
                }

                vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;

                ++it;
            } else {
                it = mDisplayEventConnections.erase(it);
            }
        }

        if (!consumers.empty()) {
            dispatchEvent(*event, consumers);
            consumers.clear();
        }

        if (mVSyncState && vsyncRequested) {
            mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
        } else {
            ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
            mState = State::Idle;
        }

        if (mState == State::VSync) {
            const auto scheduleResult =
                    mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                                 .readyDuration = mReadyDuration.count(),
                                                 .earliestVsync = mLastVsyncCallbackTime.ns()});
            LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
        } else {
            mVsyncRegistration.cancel();
        }

        if (!mPendingEvents.empty()) {
            continue;
        }

        // Wait for event or client registration/request.
        if (mState == State::Idle) {
            mCondition.wait(lock);
        } else {
            // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
            // display is off, keep feeding clients at 60 Hz.
            const std::chrono::nanoseconds timeout =
                    mState == State::SyntheticVSync ? 16ms : 1000ms;
            if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
                if (mState == State::VSync) {
                    ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
                }

                LOG_FATAL_IF(!mVSyncState);
                const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
                const auto deadlineTimestamp = now + timeout.count();
                const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
                mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
                                                   ++mVSyncState->count, expectedVSyncTime,
                                                   deadlineTimestamp));
            }
        }
    }
    // cancel any pending vsync event before exiting
    mVsyncRegistration.cancel();
}

触发VSYNC请求

const auto scheduleResult =

mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),

.readyDuration = mReadyDuration.count(),

.earliestVsync = mLastVsyncCallbackTime.ns()});

LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");

platform/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp

ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
    if (!mToken) {
        return std::nullopt;
    }
    return mDispatch->schedule(*mToken, scheduleTiming);
}

mDispatchVSyncDispatchTimerQueue同一个文件

platform/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp

ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
                                                 ScheduleTiming scheduleTiming) {
    std::lock_guard lock(mMutex);
    return scheduleLocked(token, scheduleTiming);
}

ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
                                                       ScheduleTiming scheduleTiming) {
    auto it = mCallbacks.find(token);
    if (it == mCallbacks.end()) {
        return {};
    }
    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);
    }

    const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
    if (!result.has_value()) {
        return {};
    }

    if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
        rearmTimerSkippingUpdateFor(now, it);
    }

    return result;
}

这里callbackVSyncDispatchTimerQueueEntry具体实现VSyncDispatchTimerQueue.cpp文件

ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
                                                      VSyncTracker& tracker, nsecs_t now) {
    auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
            std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
    auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    bool const wouldSkipAVsyncTarget =
            mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
    bool const wouldSkipAWakeup =
            mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
    if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
        return getExpectedCallbackTime(nextVsyncTime, timing);
    }

    nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
    nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;

    auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
    mScheduleTiming = timing;
    mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
    return getExpectedCallbackTime(nextVsyncTime, timing);
}

这里就是计算下一次VSync的地方了。tracker就是VSyncPredictor计算VSync核心

上面VSyncDispatchTimerQueue::scheduleLockedschedule计算时间调用

rearmTimerSkippingUpdateForrearmTimerSkippingUpdateFor设置一个Alarm定时执行VSync回调

void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
        nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
        ...
        setTimer(*min, now);
        ...
}

void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
    mIntendedWakeupTime = targetTime;
    mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
                         mIntendedWakeupTime);
    mLastTimerSchedule = mTimeKeeper->now();
}

这里timerCallbackEventThread这个方法

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
    std::lock_guard<std::mutex> lock(mMutex);
    mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);

    LOG_FATAL_IF(!mVSyncState);
    mVsyncTracer = (mVsyncTracer + 1) % 2;
    mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
                                       vsyncTime, readyTime));
    mCondition.notify_all();
}

Vsync信号将会封装Event放入mPendingEvents

VSYNC-app的分发过程

之前threadMain方法代码

if (!mPendingEvents.empty()) {
            event = mPendingEvents.front();
            mPendingEvents.pop_front();

            if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
                if (event->hotplug.connected && !mVSyncState) {
                    mVSyncState.emplace(event->header.displayId);
                } else if (!event->hotplug.connected && mVSyncState &&
                           mVSyncState->displayId == event->header.displayId) {
                    mVSyncState.reset();
                }
            }
        }
...
if (!consumers.empty()) {
    dispatchEvent(*event, consumers);
    consumers.clear();
}

void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                const DisplayEventConsumers& consumers) {
    for (const auto& consumer : consumers) {
        DisplayEventReceiver::Event copy = event;
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
            const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
            copy.vsync.vsyncData.frameInterval = frameInterval;
            generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
                                  event.vsync.vsyncData.preferredExpectedPresentationTime(),
                                  event.vsync.vsyncData.preferredDeadlineTimestamp());
        }
        switch (consumer->postEvent(copy)) {
            case NO_ERROR:
                break;

            case -EAGAIN:
                // TODO: Try again if pipe is full.
                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
                      toString(*consumer).c_str());
                break;

            default:
                // Treat EPIPE and other errors as fatal.
                removeDisplayEventConnectionLocked(consumer);
        }
    }
}

这里consumerEventThreadConnection

platform/frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    constexpr auto toStatus = [](ssize_t size) {
        return size < 0 ? status_t(size) : status_t(NO_ERROR);
    };

    if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
        event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
        mPendingEvents.emplace_back(event);
        if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
            return status_t(NO_ERROR);
        }

        auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
                                                     mPendingEvents.size());
        mPendingEvents.clear();
        return toStatus(size);
    }

    auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return toStatus(size);
}

DisplayEventReceiver::sendEvents最终客户端

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

BitTube通过socket事件分发客户端的Choreographer

VSYNC-sf的请求和分发

VSYNC-sf触发SurfaceFlinger::initScheduler调用MessageQueue::initVsync

platform/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp

void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.workDuration = workDuration;
        mVsync.tokenManager = &tokenManager;
        oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
    }

    // See comments in onNewVsyncSchedule. Today, oldRegistration should be
    // empty, but nothing prevents us from calling initVsync multiple times, so
    // go ahead and destruct it outside the lock for safety.
    oldRegistration.reset();
}

platform/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp

std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
        std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    auto oldRegistration = std::move(mVsync.registration);
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
    return oldRegistration;
}

可以看到这里VSYNC信号命名“sf”mVsync.registration->schedule此处调用VSync生成过程前面VSync-app相同。但这里回调函数vsyncCallback

platform/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp

void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
    ATRACE_CALL();
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;

    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }

    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};

    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}

MessageQueue本身一个消息队列实现这里看到收到VSync回调,通过mHandler->dispatchFrame抛到队列最终执行

platform/frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp

void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}

最后回调

platform/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp

void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
          ...
          if (!compositor.commit(pacesetterId, targets)) return;
          ...
          const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
  }

这里的compositor是SurfaceFlinger。接下来就是由SF进行合成工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1704688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI智能体|扣子Coze文生图功能接入微信公众号

大家好&#xff0c;我是无界生长。 AI智能体&#xff5c;扣子Coze文生图功能接入微信公众号本文分享了如何将Coze平台的文生图功能接入微信公众号的详细操作流程&#xff0c;包括创建图像流、创建并配置Bot、设置提示词和开场白、调试、发布等步骤。如果看完还没学会的话&…

【设计模式】创建型-工厂方法模式

前言 工厂方法模式是一种经典的创建型设计模式&#xff0c;它提供了一种灵活的方式来创建对象实例。通过本文&#xff0c;我们将深入探讨工厂方法模式的概念、结构和应用。 一、什么是工厂方法模式 工厂方法模式是一种创建型设计模式&#xff0c;旨在解决对象的创建过程和客…

B站尚硅谷git学习记录

文章目录 一、Git概述1.何为版本控制2.为什么需要版本控制3.版本控制工具 二、Git常用命令1.设置用户签名1.1 基本语法1.2 案例实操 2.初始化本地库2.1 基本语法2.2 案例实操 3.查看本地库状态3.1基本语法3.2 案例实操&#xff08;1&#xff09;首次查看&#xff08;工作区没有…

解决“nothing added to commit but untracked files present“

在执行git commit 命令时错误信息显示系统无法打开指定的设备或文件 &#xff0c;说明项目的文件没有“add”&#xff0c;需要先执行git add 文件名&#xff0c;然后再执行git commit -m “xxx” 直接先git add 文件名添加到缓冲区&#xff0c;再git commit -m “xxx”提交 gi…

[docker] docker 安全知识 - 镜像,port registry

[docker] docker 安全知识 - 镜像&#xff0c;port & registry 这是第一篇&#xff0c;安全部分还有一篇笔记就记完了 说实话&#xff0c;看完了要学的这些东西&#xff0c;感觉大多数安全问题都可以通过验证登录的合法性去解决 镜像 镜像的问题还是比较多的&#xff0…

数学建模--LaTeX的基本使用

目录 1.回顾 2.设置这个页眉和页脚 3.对于字体的相关设置 4.对于这个分级标题的设置 5.列表的使用 6.插入图片 1.回顾 &#xff08;1&#xff09;昨天我们了解到了这个latex的使用基本常识&#xff0c;以及这个宏包的概念&#xff0c;区域的划分&#xff0c;不同的代码代…

05.配置tomcat管理功能

认证失败&#xff0c;需要配置tomcat-users.xml文件 配置用户信息 [rootweb01 /application/tomcat/conf\]# tail tomcat-users.xml <role rolename"admin-gui"/> <role rolename"host-gui"/><role rolename"mana…

图解 Transformer

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

React(4): 使用 unocss + react-ts + vite 开发

React(4): 使用 unocss react ts 开发 之前一直使用 css-module 开发页面&#xff0c;觉得太过繁琐&#xff0c;看到 unocss , 眼前一亮&#xff0c;觉得可以拿来快速开发页面&#xff08;偷懒&#xff09; vite官网 unocss tailwindcss 说明 该方法需要对 tailwindcss 有一…

多态(难的起飞)

注意 virtual关键字&#xff1a; 1、可以修饰原函数&#xff0c;为了完成虚函数的重写&#xff0c;满足多态的条件之一 2、可以菱形继承中&#xff0c;去完成虚继承&#xff0c;解决数据冗余和二义性 两个地方使用了同一个关键字&#xff0c;但是它们互相一点关系都没有 虚函…

c++ 将指针转换为 void* 后,转换为怎么判断原指针类型?

当将指针转换为void后&#xff0c;擦除了指针所指向对象的类型信息&#xff0c;因此无法通过void指针来判断原始指针的类型。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个…

每日一题 <leetcode--2326.螺旋矩阵>

https://leetcode.cn/problems/spiral-matrix-iv/ 函数中给出的int* returnSize和int** returnColumnSizes是需要我们返回数值的&#xff0c;这点需要注意。其中int** returnColumnSizes 是需要额外开辟一块空间。 这道题我们首先需要malloc出一快空间来把链表存放在数组中&…

指纹识别经典图书、开源算法库、开源数据库

目录 1. 指纹识别书籍 1.1《精通Visual C指纹模式识别系统算法及实现》 1.2《Handbook of Fingerprint Recognition》 2. 指纹识别开源算法库 2.1 Hands on Fingerprint Recognition with OpenCV and Python 2.2 NIST Biometric Image Software (NBIS) 3. 指纹识别开源数…

QQ名片满级会员装x助手HTML源码

源码介绍 QQ名片满级会员展示生成HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;保存素材去选择QQ个性名片-选择大图模板-把图上传照片墙即可 源码效果 源码下载 蓝奏云&#xff1a;http…

Golang | Leetcode Golang题解之第116题填充每个节点的下一个右侧节点指针

题目&#xff1a; 题解&#xff1a; func connect(root *Node) *Node {if root nil {return root}// 每次循环从该层的最左侧节点开始for leftmost : root; leftmost.Left ! nil; leftmost leftmost.Left {// 通过 Next 遍历这一层节点&#xff0c;为下一层的节点更新 Next …

VS Code开发Python配置和使用教程

在Visual Studio Code (VSCode) 中配置和使用Python进行开发是一个相对直接的过程&#xff0c;下面是一份简明的指南&#xff0c;帮助你从零开始设置环境&#xff1a; 1. 安装Visual Studio Code 首先&#xff0c;确保你已经安装了Visual Studio Code。如果还没有安装&#x…

入门编程,一定要从C语言开始吗?

入门编程并不一定非得从C语言开始。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 C语言在过去是一种常见的入门语…

《python编程从入门到实践》day40

# 昨日知识点回顾 编辑条目及创建用户账户 暂没能解决bug&#xff1a; The view learning_logs.views.edit_entry didnt return an HttpResponse object. It returned None instead.# 今日知识点学习 19.2.5 注销 提供让用户注销的途径 1.在base.html中添加注销链接 …

基于OrangePi AIpro的后端服务器构建

一. OrangePi AIpro简介 1.1 OrangePi AIpro外观 1.2 OrangePi AIpro配置 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB…

边境牧羊犬优化算法,原理详解,MATLAB代码免费获取

边境牧羊犬优化算法&#xff08;Border Collie Optimization&#xff0c;BCO&#xff09;是一种受自然启发的群智能优化算法。该算法是通过模仿边境牧羊犬的放牧风格来开发的。本文成功地采用了边境牧羊犬从正面和侧面的独特放牧风格。在这个算法中&#xff0c;整个种群被分成两…