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

news/2024/7/22 14:09:48/文章来源:https://blog.csdn.net/temp7695/article/details/139250674

整体框架

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.cppvoid 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.cppVsyncSchedule::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.cppConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {// 根据cycle参数不同选择app还是appSfauto 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.cppConnectionHandle 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.cppsp<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.cppScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {if (!mToken) {return std::nullopt;}return mDispatch->schedule(*mToken, scheduleTiming);
}

mDispatchVSyncDispatchTimerQueue同一个文件

platform/frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cppScheduleResult 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.cppstatus_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.cppvoid 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.cppstd::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.cppvoid 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.cppvoid MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}

最后回调

platform/frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cppvoid 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.luyixian.cn/news_show_1052421.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每天写两道(一):无重复字符的最长子串、反转链表

3. 无重复字符的最长子串 3. 无重复字符的最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串的长度。 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。(1)滑动窗口 双…

Vue3项目练习详细步骤(第一部分:项目构建,登录注册页面)

项目环境准备 工程创建 安装依赖 项目调整 注册功能 页面结构 接口文档 数据绑定和校验 数据接口调用 解决跨域问题 登录功能 接口文档 数据绑定和校验 数据接口调用 项目演示 项目的后端接口参考&#xff1a;https://blog.csdn.net/dafsq/category_12646722.html…

Android studio版本和Android gradle plugin版本对应表

1.Android studio 版本的升级&#xff0c;一个方面上看主要是升级对AGP最高版本的支持 2.那为什么AGP要出高版本呢&#xff0c;主要支持高版本的API&#xff0c;真是一环扣一环

Android数据缓存框架 - 内存数据载体从LiveData到StateFlow

引言&#xff1a;所有成功者的背后&#xff0c;都有一份艰苦的历程&#xff0c;不要只看到了人前的风光&#xff0c;而低估了他们背后所付出的努力。 随着flow到流行度越来越高&#xff0c;有开发者呼吁我使用flow&#xff0c;于是我就如你们所愿&#xff0c;新增了StateFlow作…

STM32学习和实践笔记(30):窗口看门狗(WWDG)实验

1.WWDG介绍 1.1 WWDG简介 上一章我们已经介绍了IWDG&#xff0c;知道它的工作原理就是一个12位递减计数器不断递减计数&#xff0c;当减到0之前还未进行喂狗的话&#xff0c;产生一个MCU复位。 窗口看门狗WWDG其实和独立看门狗类似&#xff0c;它是一个7位递减计数器不断的往…

基于机器学习预测未来的二氧化碳排放量(随机森林和XGBoost)

基于机器学习预测未来的二氧化碳排放量&#xff08;随机森林和XGBoost&#xff09; 简介&#xff1a; CO2排放是当今全球关注的环境问题之一。本文将使用Python对OWID提供的CO2排放数据集进行分析&#xff0c;并尝试构建机器学习模型来预测未来的CO2排放趋势。我们将探索数据…

图形学概述

图形学应用 游戏 游戏的画面好坏如何鉴定呢&#xff1f; 看游戏画面是否够亮&#xff1a;渲染中全局光照的好坏 《只狼》 为什么卡通游戏画面看起来是卡通的呢&#xff1f; 《无主之地3》 这些都是图形学需要着手解决的问题 电影 电影《黑客帝国》的特效也是通过计算机…

一个超级简单的Python UI库:NiceGUI

大家好&#xff0c;图形用户界面&#xff08;GUI&#xff09;的开发往往被看作是一项复杂且繁琐的任务。Python作为一门强大的编程语言&#xff0c;提供了许多优秀的库来帮助开发者实现这一目标。今天&#xff0c;我们将介绍一个名为NiceGUI的库&#xff0c;它能帮助你轻松构建…

大模型PEFT(一)之推理实践学习记录

1. 简介 多种模型: LLaMA、Mistral、Mixtral-MoE、Qwen、Yi、Gemmha、Baichuan、ChatGLM、Phi等等。集成方法:(增量)预训练、指令监督微调、奖励模型训练、PPO训练和DPO训练。多种精度:32比特全参数微调、16比特冻结微调、16比特LORA微调和基于AQLM/AWQ/GPTQ/LLM.int8 的2/4/8…

EtherCAT总线掉线如何自动重启

EtherCAT通信如果是从站掉线我们可以勾选上自动重启功能如下图所示&#xff1a; 1、自动重启从站 待续.....

词法与语法分析器介绍

概述 词法和语法可以使用正则表达式和BNF范式表达&#xff0c;而最终描述文法含义的事状态转换图 Lex与YACC 词法分析器Lex 词法分析词Lex&#xff0c;是一种生成词法分析的工具&#xff0c;描述器是识别文本中词汇模式的程序&#xff0c;这些词汇模式是在特殊的句子结构中…

欧科云链:Web3.0时代 具备链上数据分析能力的公司愈发凸显其价值

在当今激烈的市场竞争中&#xff0c;新兴互联网领域迅速崛起&#xff0c;Web2.0已相对成熟&#xff0c;用户创造数据&#xff0c;但不拥有数据。被视为新的价值互联网的Web3.0&#xff0c;赋予用户真正的数据自主权&#xff0c;它的到来被认为是打破Web2.0垄断的机遇。 在Web3…

【区块链】Postman功能接口测试

需要将完整的合约部署到fisco上以及启动后端的工程项目 启动WeBASE python3 deploy.py startAll 然后通过127.0.0.1&#xff1a;5002/WeBASE-Front启动webase 在工程日录下启动项目,检查配置文件conf.properties中的合约和用户信息足否与webase-front一致 运行trace的jar包项…

Qt 5前后调色板差异变化

Qt 5之前&#xff1a; QPalette palette;//调色板 设置背景颜色 palette.setColor(QPalette::Backgound, color...);Qt 5之后&#xff1a; 由原有的 Background 模式 更新为 Window 模式 QPalette palette;//调色板 设置背景颜色 palette.setColor(QPalette::Window, color..…

AI智能体研发之路-模型篇(四):一文入门pytorch开发

博客导读&#xff1a; 《AI—工程篇》 AI智能体研发之路-工程篇&#xff08;一&#xff09;&#xff1a;Docker助力AI智能体开发提效 AI智能体研发之路-工程篇&#xff08;二&#xff09;&#xff1a;Dify智能体开发平台一键部署 AI智能体研发之路-工程篇&#xff08;三&am…

python web自动化(Pytest实战)

1.UnitTest框架与Pytest框架对⽐ 1&#xff09; unittest框架介绍 Unittest则是Python语⾔的标准单元测试框架。 Unittest⽀持⾃动化测试&#xff0c;测试⽤例的初 始化、关闭和测试⽤例的聚合等功能&#xff0c;它有⼀个很重要的特性&#xff…

嵌入式UI开发-lvgl+wsl2+vscode系列:2、label(标签)+button(按钮)+slider(滑块)控件熟悉及其示例demo运行

文章目录 一、前言二、常见控件示例demo模拟环境运行及接口熟悉&#xff08;重要&#xff09;如何修改示例main函数测试各种示例1、label示例1.1、label示例1&#xff08;标签基础示例&#xff09;1.2、label示例2&#xff08;标签带阴影效果&#xff09;1.3、label示例3&#…

ComfyUI简单介绍

&#x1f353;什么是ComfyUI ComfyUI是一个为Stable Diffusion专门设计的基于节点的图形用户界面&#xff0c;可以通过各种不同的节点快速搭建自己的绘图工作流程。 软件打开之后是长这个样子&#xff1a; 同时软件本身是github上的一个开源项目&#xff0c;开源地址为&#…

编译原理 期末复习笔记整理(上)

资料借鉴&#xff1a; 【编译原理】期末复习 零基础自学_哔哩哔哩_bilibili 编译原理笔记 第一章 引论 1.编译原理逻辑过程&#xff1a; 词法分析 语法分析 语义分析 中间代码生成 编译代码生成 2.词法分析 任务: 输入源程序&#xff0c;对…

通用代码生成器应用场景三,遗留项目反向工程

通用代码生成器应用场景三&#xff0c;遗留项目反向工程 如果您有一个遗留项目&#xff0c;要重新开发&#xff0c;或者源代码遗失&#xff0c;或者需要重新开发&#xff0c;但是希望复用原来的数据&#xff0c;并加快开发。 如果您的项目是通用代码生成器生成的&#xff0c;…