|
25 | 25 | #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> |
26 | 26 | #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h> |
27 | 27 | #include <configstore/Utils.h> |
| 28 | +#include <ftl/concat.h> |
28 | 29 | #include <ftl/enum.h> |
29 | 30 | #include <ftl/fake_guard.h> |
30 | 31 | #include <ftl/small_map.h> |
@@ -130,8 +131,8 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, |
130 | 131 | auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) { |
131 | 132 | std::scoped_lock lock(mDisplayLock); |
132 | 133 | const bool isNew = mDisplays |
133 | | - .emplace_or_replace(displayId, std::move(selectorPtr), |
134 | | - std::move(schedulePtr)) |
| 134 | + .emplace_or_replace(displayId, displayId, std::move(selectorPtr), |
| 135 | + std::move(schedulePtr), mFeatures) |
135 | 136 | .second; |
136 | 137 |
|
137 | 138 | return std::make_pair(promotePacesetterDisplayLocked(), isNew); |
@@ -171,21 +172,43 @@ void Scheduler::run() { |
171 | 172 |
|
172 | 173 | void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, |
173 | 174 | TimePoint expectedVsyncTime) { |
174 | | - mPacesetterFrameTargeter.beginFrame({.frameBeginTime = SchedulerClock::now(), |
175 | | - .vsyncId = vsyncId, |
176 | | - .expectedVsyncTime = expectedVsyncTime, |
177 | | - .sfWorkDuration = |
178 | | - mVsyncModulator->getVsyncConfig().sfWorkDuration}, |
179 | | - *getVsyncSchedule()); |
180 | | - |
181 | | - if (!compositor.commit(mPacesetterFrameTargeter.target())) { |
182 | | - return; |
| 175 | + const FrameTargeter::BeginFrameArgs beginFrameArgs = |
| 176 | + {.frameBeginTime = SchedulerClock::now(), |
| 177 | + .vsyncId = vsyncId, |
| 178 | + // TODO(b/255601557): Calculate per display. |
| 179 | + .expectedVsyncTime = expectedVsyncTime, |
| 180 | + .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration}; |
| 181 | + |
| 182 | + LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId); |
| 183 | + const auto pacesetterId = *mPacesetterDisplayId; |
| 184 | + const auto pacesetterOpt = mDisplays.get(pacesetterId); |
| 185 | + |
| 186 | + FrameTargeter& pacesetterTargeter = *pacesetterOpt->get().targeterPtr; |
| 187 | + pacesetterTargeter.beginFrame(beginFrameArgs, *pacesetterOpt->get().schedulePtr); |
| 188 | + |
| 189 | + if (!compositor.commit(pacesetterTargeter.target())) return; |
| 190 | + |
| 191 | + // TODO(b/256196556): Choose the frontrunner display. |
| 192 | + FrameTargeters targeters; |
| 193 | + targeters.try_emplace(pacesetterId, &pacesetterTargeter); |
| 194 | + |
| 195 | + for (auto& [id, display] : mDisplays) { |
| 196 | + if (id == pacesetterId) continue; |
| 197 | + |
| 198 | + FrameTargeter& targeter = *display.targeterPtr; |
| 199 | + targeter.beginFrame(beginFrameArgs, *display.schedulePtr); |
| 200 | + |
| 201 | + targeters.try_emplace(id, &targeter); |
183 | 202 | } |
184 | 203 |
|
185 | | - const auto compositeResult = compositor.composite(mPacesetterFrameTargeter); |
| 204 | + const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters); |
186 | 205 | compositor.sample(); |
187 | 206 |
|
188 | | - mPacesetterFrameTargeter.endFrame(compositeResult); |
| 207 | + for (const auto& [id, targeter] : targeters) { |
| 208 | + const auto resultOpt = resultsPerDisplay.get(id); |
| 209 | + LOG_ALWAYS_FATAL_IF(!resultOpt); |
| 210 | + targeter->endFrame(*resultOpt); |
| 211 | + } |
189 | 212 | } |
190 | 213 |
|
191 | 214 | std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { |
@@ -539,8 +562,16 @@ bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp, |
539 | 562 | } |
540 | 563 |
|
541 | 564 | void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) { |
542 | | - auto schedule = getVsyncSchedule(id); |
543 | | - LOG_ALWAYS_FATAL_IF(!schedule); |
| 565 | + const auto scheduleOpt = |
| 566 | + (ftl::FakeGuard(mDisplayLock), mDisplays.get(id)).and_then([](const Display& display) { |
| 567 | + return display.powerMode == hal::PowerMode::OFF |
| 568 | + ? std::nullopt |
| 569 | + : std::make_optional(display.schedulePtr); |
| 570 | + }); |
| 571 | + |
| 572 | + if (!scheduleOpt) return; |
| 573 | + const auto& schedule = scheduleOpt->get(); |
| 574 | + |
544 | 575 | if (const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence))) { |
545 | 576 | schedule->enableHardwareVsync(); |
546 | 577 | } else { |
@@ -750,7 +781,23 @@ void Scheduler::dump(utils::Dumper& dumper) const { |
750 | 781 | mFrameRateOverrideMappings.dump(dumper); |
751 | 782 | dumper.eol(); |
752 | 783 |
|
753 | | - mPacesetterFrameTargeter.dump(dumper); |
| 784 | + { |
| 785 | + utils::Dumper::Section section(dumper, "Frame Targeting"sv); |
| 786 | + |
| 787 | + std::scoped_lock lock(mDisplayLock); |
| 788 | + ftl::FakeGuard guard(kMainThreadContext); |
| 789 | + |
| 790 | + for (const auto& [id, display] : mDisplays) { |
| 791 | + utils::Dumper::Section |
| 792 | + section(dumper, |
| 793 | + id == mPacesetterDisplayId |
| 794 | + ? ftl::Concat("Pacesetter Display ", id.value).c_str() |
| 795 | + : ftl::Concat("Follower Display ", id.value).c_str()); |
| 796 | + |
| 797 | + display.targeterPtr->dump(dumper); |
| 798 | + dumper.eol(); |
| 799 | + } |
| 800 | + } |
754 | 801 | } |
755 | 802 |
|
756 | 803 | void Scheduler::dumpVsync(std::string& out) const { |
|
0 commit comments