Loading services/surfaceflinger/Scheduler/ISchedulerCallback.h 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <vector> #include "Display/DisplayModeRequest.h" namespace android::scheduler { struct ISchedulerCallback { virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; protected: ~ISchedulerCallback() = default; }; } // namespace android::scheduler services/surfaceflinger/Scheduler/Scheduler.cpp +15 −68 Original line number Diff line number Diff line Loading @@ -28,10 +28,10 @@ #include <ftl/enum.h> #include <ftl/fake_guard.h> #include <ftl/small_map.h> #include <gui/TraceUtils.h> #include <gui/WindowInfo.h> #include <system/window.h> #include <utils/Timers.h> #include <utils/Trace.h> #include <FrameTimeline/FrameTimeline.h> #include <scheduler/interface/ICompositor.h> Loading Loading @@ -155,7 +155,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, } void Scheduler::createVsyncSchedule(FeatureFlags features) { mVsyncSchedule.emplace(features); mVsyncSchedule = std::make_unique<VsyncSchedule>(features); } std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { Loading @@ -171,6 +171,7 @@ bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const return true; } ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str()); return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate); } Loading Loading @@ -393,38 +394,17 @@ void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) { } void Scheduler::enableHardwareVsync() { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) { mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } mVsyncSchedule->enableHardwareVsync(mSchedulerCallback); } void Scheduler::disableHardwareVsync(bool makeUnavailable) { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { mSchedulerCallback.setVsyncEnabled(false); mPrimaryHWVsyncEnabled = false; } if (makeUnavailable) { mHWVsyncAvailable = false; } void Scheduler::disableHardwareVsync(bool disallow) { mVsyncSchedule->disableHardwareVsync(mSchedulerCallback, disallow); } void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) { { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (makeAvailable) { mHWVsyncAvailable = makeAvailable; } else if (!mHWVsyncAvailable) { // Hardware vsync is not currently available, so abort the resync // attempt for now return; } void Scheduler::resyncToHardwareVsync(bool allowToEnable, Fps refreshRate) { if (mVsyncSchedule->isHardwareVsyncAllowed(allowToEnable) && refreshRate.isValid()) { mVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod()); } setVsyncPeriod(refreshRate.getPeriodNsecs()); } void Scheduler::setRenderRate(Fps renderFrameRate) { Loading Loading @@ -457,37 +437,12 @@ void Scheduler::resync() { } } void Scheduler::setVsyncPeriod(nsecs_t period) { if (period <= 0) return; std::lock_guard<std::mutex> lock(mHWVsyncLock); mVsyncSchedule->getController().startPeriodTransition(period); if (!mPrimaryHWVsyncEnabled) { mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } } void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, bool* periodFlushed) { bool needsHwVsync = false; *periodFlushed = false; { // Scope for the lock std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { needsHwVsync = mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, periodFlushed); } } if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); } bool Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriodIn) { const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) { return Period::fromNs(nanos); }); return mVsyncSchedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp), hwcVsyncPeriod); } void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) { Loading Loading @@ -635,14 +590,6 @@ void Scheduler::dump(utils::Dumper& dumper) const { mFrameRateOverrideMappings.dump(dumper); dumper.eol(); { utils::Dumper::Section section(dumper, "Hardware VSYNC"sv); std::lock_guard lock(mHWVsyncLock); dumper.dump("hwVsyncAvailable"sv, mHWVsyncAvailable); dumper.dump("hwVsyncEnabled"sv, mPrimaryHWVsyncEnabled); } } void Scheduler::dumpVsync(std::string& out) const { Loading services/surfaceflinger/Scheduler/Scheduler.h +9 −23 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include "Display/DisplayModeRequest.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "ISchedulerCallback.h" #include "LayerHistory.h" #include "MessageQueue.h" #include "OneShotTimer.h" Loading Loading @@ -92,16 +93,6 @@ namespace scheduler { using GlobalSignals = RefreshRateSelector::GlobalSignals; struct ISchedulerCallback { virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; protected: ~ISchedulerCallback() = default; }; class Scheduler : android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -192,20 +183,20 @@ public: void setRenderRate(Fps); void enableHardwareVsync(); void disableHardwareVsync(bool makeUnavailable); void disableHardwareVsync(bool disallow); // Resyncs the scheduler to hardware vsync. // If makeAvailable is true, then hardware vsync will be turned on. // If allowToEnable is true, then hardware vsync will be turned on. // Otherwise, if hardware vsync is not already enabled then this method will // no-op. void resyncToHardwareVsync(bool makeAvailable, Fps refreshRate); void resyncToHardwareVsync(bool allowToEnable, Fps refreshRate); void resync() EXCLUDES(mDisplayLock); void forceNextResync() { mLastResyncTime = 0; } // Passes a vsync sample to VsyncController. periodFlushed will be true if // VsyncController detected that the vsync period changed, and false otherwise. void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, bool* periodFlushed); // Passes a vsync sample to VsyncController. Returns true if // VsyncController detected that the vsync period changed and false // otherwise. bool addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod); void addPresentFence(std::shared_ptr<FenceTime>); // Layers are registered on creation, and unregistered when the weak reference expires. Loading Loading @@ -297,7 +288,6 @@ private: void touchTimerCallback(TimerState); void displayPowerTimerCallback(TimerState); void setVsyncPeriod(nsecs_t period); void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod); // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new Loading Loading @@ -362,14 +352,10 @@ private: ConnectionHandle mAppConnectionHandle; ConnectionHandle mSfConnectionHandle; mutable std::mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false; bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false; std::atomic<nsecs_t> mLastResyncTime = 0; const FeatureFlags mFeatures; std::optional<VsyncSchedule> mVsyncSchedule; std::unique_ptr<VsyncSchedule> mVsyncSchedule; // Shifts the VSYNC phase during certain transactions and refresh rate changes. const sp<VsyncModulator> mVsyncModulator; Loading services/surfaceflinger/Scheduler/VSyncPredictor.cpp +11 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ #include <android-base/stringprintf.h> #include <cutils/compiler.h> #include <cutils/properties.h> #include <gui/TraceUtils.h> #include <utils/Log.h> #include <utils/Trace.h> #include "RefreshRateSelector.h" #include "VSyncPredictor.h" Loading Loading @@ -282,6 +282,13 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const { } bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const { const TimePoint now = TimePoint::now(); const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float { return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now); }; ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint), divisor); struct VsyncError { nsecs_t vsyncTimestamp; float error; Loading @@ -304,6 +311,7 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) { const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint); mRateDivisorKnownTimestampMap[dividedPeriod] = vsync; ATRACE_FORMAT_INSTANT("(first) knownVsync in: %.2f", getTimePointIn(now, vsync)); return true; } Loading @@ -323,6 +331,8 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end()); mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp; ATRACE_FORMAT_INSTANT("knownVsync in: %.2f", getTimePointIn(now, minVsyncError->vsyncTimestamp)); return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2; } Loading services/surfaceflinger/Scheduler/VsyncSchedule.cpp +80 −6 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <ftl/fake_guard.h> #include <scheduler/Fps.h> #include <scheduler/Timer.h> #include "VsyncSchedule.h" #include "ISchedulerCallback.h" #include "Utils/Dumper.h" #include "VSyncDispatchTimerQueue.h" #include "VSyncPredictor.h" #include "VSyncReactor.h" Loading Loading @@ -54,18 +57,16 @@ private: VsyncSchedule::VsyncSchedule(FeatureFlags features) : mTracker(createTracker()), mDispatch(createDispatch(*mTracker)), mController(createController(*mTracker, features)) { if (features.test(Feature::kTracePredictedVsync)) { mTracer = std::make_unique<PredictedVsyncTracer>(*mDispatch); } } mController(createController(*mTracker, features)), mTracer(features.test(Feature::kTracePredictedVsync) ? std::make_unique<PredictedVsyncTracer>(*mDispatch) : nullptr) {} VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller) : mTracker(std::move(tracker)), mDispatch(std::move(dispatch)), mController(std::move(controller)) {} VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default; VsyncSchedule::~VsyncSchedule() = default; Period VsyncSchedule::period() const { Loading @@ -77,6 +78,16 @@ TimePoint VsyncSchedule::vsyncDeadlineAfter(TimePoint timePoint) const { } void VsyncSchedule::dump(std::string& out) const { utils::Dumper dumper(out); { std::lock_guard<std::mutex> lock(mHwVsyncLock); dumper.dump("hwVsyncState", ftl::enum_string(mHwVsyncState)); ftl::FakeGuard guard(kMainThreadContext); dumper.dump("pendingHwVsyncState", ftl::enum_string(mPendingHwVsyncState)); dumper.eol(); } out.append("VsyncController:\n"); mController->dump(out); Loading Loading @@ -120,4 +131,67 @@ VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& track return reactor; } void VsyncSchedule::startPeriodTransition(ISchedulerCallback& callback, Period period) { std::lock_guard<std::mutex> lock(mHwVsyncLock); mController->startPeriodTransition(period.ns()); enableHardwareVsyncLocked(callback); } bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod) { bool needsHwVsync = false; bool periodFlushed = false; { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (mHwVsyncState == HwVsyncState::Enabled) { needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(), hwcVsyncPeriod.transform(&Period::ns), &periodFlushed); } } if (needsHwVsync) { enableHardwareVsync(callback); } else { disableHardwareVsync(callback, false /* disallow */); } return periodFlushed; } void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) { std::lock_guard<std::mutex> lock(mHwVsyncLock); enableHardwareVsyncLocked(callback); } void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) { if (mHwVsyncState == HwVsyncState::Disabled) { getTracker().resetModel(); callback.setVsyncEnabled(true); mHwVsyncState = HwVsyncState::Enabled; } } void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (mHwVsyncState == HwVsyncState::Enabled) { callback.setVsyncEnabled(false); } mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled; } bool VsyncSchedule::isHardwareVsyncAllowed(bool makeAllowed) { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (makeAllowed && mHwVsyncState == HwVsyncState::Disallowed) { mHwVsyncState = HwVsyncState::Disabled; } return mHwVsyncState != HwVsyncState::Disallowed; } void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) { mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled; } bool VsyncSchedule::getPendingHardwareVsyncState() const { return mPendingHwVsyncState == HwVsyncState::Enabled; } } // namespace android::scheduler Loading
services/surfaceflinger/Scheduler/ISchedulerCallback.h 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <vector> #include "Display/DisplayModeRequest.h" namespace android::scheduler { struct ISchedulerCallback { virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; protected: ~ISchedulerCallback() = default; }; } // namespace android::scheduler
services/surfaceflinger/Scheduler/Scheduler.cpp +15 −68 Original line number Diff line number Diff line Loading @@ -28,10 +28,10 @@ #include <ftl/enum.h> #include <ftl/fake_guard.h> #include <ftl/small_map.h> #include <gui/TraceUtils.h> #include <gui/WindowInfo.h> #include <system/window.h> #include <utils/Timers.h> #include <utils/Trace.h> #include <FrameTimeline/FrameTimeline.h> #include <scheduler/interface/ICompositor.h> Loading Loading @@ -155,7 +155,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, } void Scheduler::createVsyncSchedule(FeatureFlags features) { mVsyncSchedule.emplace(features); mVsyncSchedule = std::make_unique<VsyncSchedule>(features); } std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { Loading @@ -171,6 +171,7 @@ bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const return true; } ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str()); return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate); } Loading Loading @@ -393,38 +394,17 @@ void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) { } void Scheduler::enableHardwareVsync() { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) { mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } mVsyncSchedule->enableHardwareVsync(mSchedulerCallback); } void Scheduler::disableHardwareVsync(bool makeUnavailable) { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { mSchedulerCallback.setVsyncEnabled(false); mPrimaryHWVsyncEnabled = false; } if (makeUnavailable) { mHWVsyncAvailable = false; } void Scheduler::disableHardwareVsync(bool disallow) { mVsyncSchedule->disableHardwareVsync(mSchedulerCallback, disallow); } void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) { { std::lock_guard<std::mutex> lock(mHWVsyncLock); if (makeAvailable) { mHWVsyncAvailable = makeAvailable; } else if (!mHWVsyncAvailable) { // Hardware vsync is not currently available, so abort the resync // attempt for now return; } void Scheduler::resyncToHardwareVsync(bool allowToEnable, Fps refreshRate) { if (mVsyncSchedule->isHardwareVsyncAllowed(allowToEnable) && refreshRate.isValid()) { mVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod()); } setVsyncPeriod(refreshRate.getPeriodNsecs()); } void Scheduler::setRenderRate(Fps renderFrameRate) { Loading Loading @@ -457,37 +437,12 @@ void Scheduler::resync() { } } void Scheduler::setVsyncPeriod(nsecs_t period) { if (period <= 0) return; std::lock_guard<std::mutex> lock(mHWVsyncLock); mVsyncSchedule->getController().startPeriodTransition(period); if (!mPrimaryHWVsyncEnabled) { mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } } void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, bool* periodFlushed) { bool needsHwVsync = false; *periodFlushed = false; { // Scope for the lock std::lock_guard<std::mutex> lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { needsHwVsync = mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, periodFlushed); } } if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); } bool Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriodIn) { const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) { return Period::fromNs(nanos); }); return mVsyncSchedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp), hwcVsyncPeriod); } void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) { Loading Loading @@ -635,14 +590,6 @@ void Scheduler::dump(utils::Dumper& dumper) const { mFrameRateOverrideMappings.dump(dumper); dumper.eol(); { utils::Dumper::Section section(dumper, "Hardware VSYNC"sv); std::lock_guard lock(mHWVsyncLock); dumper.dump("hwVsyncAvailable"sv, mHWVsyncAvailable); dumper.dump("hwVsyncEnabled"sv, mPrimaryHWVsyncEnabled); } } void Scheduler::dumpVsync(std::string& out) const { Loading
services/surfaceflinger/Scheduler/Scheduler.h +9 −23 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include "Display/DisplayModeRequest.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "ISchedulerCallback.h" #include "LayerHistory.h" #include "MessageQueue.h" #include "OneShotTimer.h" Loading Loading @@ -92,16 +93,6 @@ namespace scheduler { using GlobalSignals = RefreshRateSelector::GlobalSignals; struct ISchedulerCallback { virtual void setVsyncEnabled(bool) = 0; virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; protected: ~ISchedulerCallback() = default; }; class Scheduler : android::impl::MessageQueue { using Impl = android::impl::MessageQueue; Loading Loading @@ -192,20 +183,20 @@ public: void setRenderRate(Fps); void enableHardwareVsync(); void disableHardwareVsync(bool makeUnavailable); void disableHardwareVsync(bool disallow); // Resyncs the scheduler to hardware vsync. // If makeAvailable is true, then hardware vsync will be turned on. // If allowToEnable is true, then hardware vsync will be turned on. // Otherwise, if hardware vsync is not already enabled then this method will // no-op. void resyncToHardwareVsync(bool makeAvailable, Fps refreshRate); void resyncToHardwareVsync(bool allowToEnable, Fps refreshRate); void resync() EXCLUDES(mDisplayLock); void forceNextResync() { mLastResyncTime = 0; } // Passes a vsync sample to VsyncController. periodFlushed will be true if // VsyncController detected that the vsync period changed, and false otherwise. void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, bool* periodFlushed); // Passes a vsync sample to VsyncController. Returns true if // VsyncController detected that the vsync period changed and false // otherwise. bool addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod); void addPresentFence(std::shared_ptr<FenceTime>); // Layers are registered on creation, and unregistered when the weak reference expires. Loading Loading @@ -297,7 +288,6 @@ private: void touchTimerCallback(TimerState); void displayPowerTimerCallback(TimerState); void setVsyncPeriod(nsecs_t period); void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod); // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new Loading Loading @@ -362,14 +352,10 @@ private: ConnectionHandle mAppConnectionHandle; ConnectionHandle mSfConnectionHandle; mutable std::mutex mHWVsyncLock; bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false; bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false; std::atomic<nsecs_t> mLastResyncTime = 0; const FeatureFlags mFeatures; std::optional<VsyncSchedule> mVsyncSchedule; std::unique_ptr<VsyncSchedule> mVsyncSchedule; // Shifts the VSYNC phase during certain transactions and refresh rate changes. const sp<VsyncModulator> mVsyncModulator; Loading
services/surfaceflinger/Scheduler/VSyncPredictor.cpp +11 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ #include <android-base/stringprintf.h> #include <cutils/compiler.h> #include <cutils/properties.h> #include <gui/TraceUtils.h> #include <utils/Log.h> #include <utils/Trace.h> #include "RefreshRateSelector.h" #include "VSyncPredictor.h" Loading Loading @@ -282,6 +282,13 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const { } bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const { const TimePoint now = TimePoint::now(); const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float { return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now); }; ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint), divisor); struct VsyncError { nsecs_t vsyncTimestamp; float error; Loading @@ -304,6 +311,7 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) { const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint); mRateDivisorKnownTimestampMap[dividedPeriod] = vsync; ATRACE_FORMAT_INSTANT("(first) knownVsync in: %.2f", getTimePointIn(now, vsync)); return true; } Loading @@ -323,6 +331,8 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end()); mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp; ATRACE_FORMAT_INSTANT("knownVsync in: %.2f", getTimePointIn(now, minVsyncError->vsyncTimestamp)); return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2; } Loading
services/surfaceflinger/Scheduler/VsyncSchedule.cpp +80 −6 Original line number Diff line number Diff line Loading @@ -16,11 +16,14 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <ftl/fake_guard.h> #include <scheduler/Fps.h> #include <scheduler/Timer.h> #include "VsyncSchedule.h" #include "ISchedulerCallback.h" #include "Utils/Dumper.h" #include "VSyncDispatchTimerQueue.h" #include "VSyncPredictor.h" #include "VSyncReactor.h" Loading Loading @@ -54,18 +57,16 @@ private: VsyncSchedule::VsyncSchedule(FeatureFlags features) : mTracker(createTracker()), mDispatch(createDispatch(*mTracker)), mController(createController(*mTracker, features)) { if (features.test(Feature::kTracePredictedVsync)) { mTracer = std::make_unique<PredictedVsyncTracer>(*mDispatch); } } mController(createController(*mTracker, features)), mTracer(features.test(Feature::kTracePredictedVsync) ? std::make_unique<PredictedVsyncTracer>(*mDispatch) : nullptr) {} VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller) : mTracker(std::move(tracker)), mDispatch(std::move(dispatch)), mController(std::move(controller)) {} VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default; VsyncSchedule::~VsyncSchedule() = default; Period VsyncSchedule::period() const { Loading @@ -77,6 +78,16 @@ TimePoint VsyncSchedule::vsyncDeadlineAfter(TimePoint timePoint) const { } void VsyncSchedule::dump(std::string& out) const { utils::Dumper dumper(out); { std::lock_guard<std::mutex> lock(mHwVsyncLock); dumper.dump("hwVsyncState", ftl::enum_string(mHwVsyncState)); ftl::FakeGuard guard(kMainThreadContext); dumper.dump("pendingHwVsyncState", ftl::enum_string(mPendingHwVsyncState)); dumper.eol(); } out.append("VsyncController:\n"); mController->dump(out); Loading Loading @@ -120,4 +131,67 @@ VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& track return reactor; } void VsyncSchedule::startPeriodTransition(ISchedulerCallback& callback, Period period) { std::lock_guard<std::mutex> lock(mHwVsyncLock); mController->startPeriodTransition(period.ns()); enableHardwareVsyncLocked(callback); } bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod) { bool needsHwVsync = false; bool periodFlushed = false; { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (mHwVsyncState == HwVsyncState::Enabled) { needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(), hwcVsyncPeriod.transform(&Period::ns), &periodFlushed); } } if (needsHwVsync) { enableHardwareVsync(callback); } else { disableHardwareVsync(callback, false /* disallow */); } return periodFlushed; } void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) { std::lock_guard<std::mutex> lock(mHwVsyncLock); enableHardwareVsyncLocked(callback); } void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) { if (mHwVsyncState == HwVsyncState::Disabled) { getTracker().resetModel(); callback.setVsyncEnabled(true); mHwVsyncState = HwVsyncState::Enabled; } } void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (mHwVsyncState == HwVsyncState::Enabled) { callback.setVsyncEnabled(false); } mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled; } bool VsyncSchedule::isHardwareVsyncAllowed(bool makeAllowed) { std::lock_guard<std::mutex> lock(mHwVsyncLock); if (makeAllowed && mHwVsyncState == HwVsyncState::Disallowed) { mHwVsyncState = HwVsyncState::Disabled; } return mHwVsyncState != HwVsyncState::Disallowed; } void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) { mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled; } bool VsyncSchedule::getPendingHardwareVsyncState() const { return mPendingHwVsyncState == HwVsyncState::Enabled; } } // namespace android::scheduler