Loading services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +5 −7 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <compositionengine/LayerFE.h> #include <compositionengine/LayerFE.h> #include <compositionengine/OutputColorSetting.h> #include <compositionengine/OutputColorSetting.h> #include <math/mat4.h> #include <math/mat4.h> #include <scheduler/interface/ICompositor.h> #include <ui/FenceTime.h> #include <ui/FenceTime.h> #include <ui/Transform.h> #include <ui/Transform.h> Loading Loading @@ -89,17 +90,14 @@ struct CompositionRefreshArgs { // If set, causes the dirty regions to flash with the delay // If set, causes the dirty regions to flash with the delay std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay; std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay; // Optional. scheduler::FrameTargets frameTargets; // The earliest time to send the present command to the HAL. std::optional<std::chrono::steady_clock::time_point> earliestPresentTime; // The expected time for the next present nsecs_t expectedPresentTime{0}; // The frameInterval for the next present // The frameInterval for the next present Fps frameInterval{}; // TODO (b/315371484): Calculate per display and store on `FrameTarget`. Fps frameInterval; // If set, a frame has been scheduled for that time. // If set, a frame has been scheduled for that time. // TODO (b/255601557): Calculate per display. std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime; std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime; std::vector<BorderRenderInfo> borderInfoList; std::vector<BorderRenderInfo> borderInfoList; Loading services/surfaceflinger/CompositionEngine/src/Output.cpp +33 −3 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,11 @@ #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/planner/Planner.h> #include <compositionengine/impl/planner/Planner.h> #include <ftl/algorithm.h> #include <ftl/future.h> #include <ftl/future.h> #include <gui/TraceUtils.h> #include <gui/TraceUtils.h> #include <scheduler/FrameTargeter.h> #include <scheduler/Time.h> #include <optional> #include <optional> #include <thread> #include <thread> Loading Loading @@ -429,7 +432,28 @@ void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArg ftl::Future<std::monostate> Output::present( ftl::Future<std::monostate> Output::present( const compositionengine::CompositionRefreshArgs& refreshArgs) { const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str()); const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string { return ftl::Optional(getDisplayId()) .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); }) .transform([](const auto& frameTargetPtr) { return frameTargetPtr.get()->expectedPresentTime(); }) .transform([](TimePoint expectedPresentTime) { return base::StringPrintf(" vsyncIn %.2fms", ticks<std::milli, float>(expectedPresentTime - TimePoint::now())); }) .or_else([] { // There is no vsync for this output. return std::make_optional(std::string()); }) .value(); }; ATRACE_FORMAT("%s for %s%s", __func__, mNamePlusId.c_str(), stringifyExpectedPresentTime().c_str()); ALOGV(__FUNCTION__); ALOGV(__FUNCTION__); updateColorProfile(refreshArgs); updateColorProfile(refreshArgs); Loading Loading @@ -853,8 +877,14 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr return; return; } } editState().earliestPresentTime = refreshArgs.earliestPresentTime; if (auto frameTargetPtrOpt = ftl::Optional(getDisplayId()) editState().expectedPresentTime = refreshArgs.expectedPresentTime; .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); })) { editState().earliestPresentTime = frameTargetPtrOpt->get()->earliestPresentTime(); editState().expectedPresentTime = frameTargetPtrOpt->get()->expectedPresentTime().ns(); } editState().frameInterval = refreshArgs.frameInterval; editState().frameInterval = refreshArgs.frameInterval; editState().powerCallback = refreshArgs.powerCallback; editState().powerCallback = refreshArgs.powerCallback; Loading services/surfaceflinger/Scheduler/Scheduler.cpp +10 −2 Original line number Original line Diff line number Diff line Loading @@ -190,7 +190,6 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, const FrameTargeter::BeginFrameArgs beginFrameArgs = const FrameTargeter::BeginFrameArgs beginFrameArgs = {.frameBeginTime = SchedulerClock::now(), {.frameBeginTime = SchedulerClock::now(), .vsyncId = vsyncId, .vsyncId = vsyncId, // TODO(b/255601557): Calculate per display. .expectedVsyncTime = expectedVsyncTime, .expectedVsyncTime = expectedVsyncTime, .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration, .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration, .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration}; .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration}; Loading @@ -202,11 +201,20 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, FrameTargets targets; FrameTargets targets; targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target()); targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target()); // TODO (b/256196556): Followers should use the next VSYNC after the frontrunner, not the // pacesetter. // Update expectedVsyncTime, which may have been adjusted by beginFrame. expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime(); for (const auto& [id, display] : mDisplays) { for (const auto& [id, display] : mDisplays) { if (id == pacesetterPtr->displayId) continue; if (id == pacesetterPtr->displayId) continue; auto followerBeginFrameArgs = beginFrameArgs; followerBeginFrameArgs.expectedVsyncTime = display.schedulePtr->vsyncDeadlineAfter(expectedVsyncTime); FrameTargeter& targeter = *display.targeterPtr; FrameTargeter& targeter = *display.targeterPtr; targeter.beginFrame(beginFrameArgs, *display.schedulePtr); targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr); targets.try_emplace(id, &targeter.target()); targets.try_emplace(id, &targeter.target()); } } Loading services/surfaceflinger/SurfaceFlinger.cpp +2 −3 Original line number Original line Diff line number Diff line Loading @@ -2681,6 +2681,8 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( if (const auto display = getCompositionDisplayLocked(id)) { if (const auto display = getCompositionDisplayLocked(id)) { refreshArgs.outputs.push_back(display); refreshArgs.outputs.push_back(display); } } refreshArgs.frameTargets.try_emplace(id, &targeter->target()); } } std::vector<DisplayId> displayIds; std::vector<DisplayId> displayIds; Loading Loading @@ -2753,9 +2755,6 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( // TODO(b/255601557) Update frameInterval per display // TODO(b/255601557) Update frameInterval per display refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, expectedPresentTime); refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, expectedPresentTime); refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); refreshArgs.expectedPresentTime = expectedPresentTime.ns(); // TODO(b/255601557): Calculate and pass per-display values for each FrameTarget. refreshArgs.earliestPresentTime = pacesetterTarget.earliestPresentTime(); refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; { { auto& notifyExpectedPresentData = mNotifyExpectedPresentMap[pacesetterId]; auto& notifyExpectedPresentData = mNotifyExpectedPresentMap[pacesetterId]; Loading Loading
services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +5 −7 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <compositionengine/LayerFE.h> #include <compositionengine/LayerFE.h> #include <compositionengine/OutputColorSetting.h> #include <compositionengine/OutputColorSetting.h> #include <math/mat4.h> #include <math/mat4.h> #include <scheduler/interface/ICompositor.h> #include <ui/FenceTime.h> #include <ui/FenceTime.h> #include <ui/Transform.h> #include <ui/Transform.h> Loading Loading @@ -89,17 +90,14 @@ struct CompositionRefreshArgs { // If set, causes the dirty regions to flash with the delay // If set, causes the dirty regions to flash with the delay std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay; std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay; // Optional. scheduler::FrameTargets frameTargets; // The earliest time to send the present command to the HAL. std::optional<std::chrono::steady_clock::time_point> earliestPresentTime; // The expected time for the next present nsecs_t expectedPresentTime{0}; // The frameInterval for the next present // The frameInterval for the next present Fps frameInterval{}; // TODO (b/315371484): Calculate per display and store on `FrameTarget`. Fps frameInterval; // If set, a frame has been scheduled for that time. // If set, a frame has been scheduled for that time. // TODO (b/255601557): Calculate per display. std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime; std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime; std::vector<BorderRenderInfo> borderInfoList; std::vector<BorderRenderInfo> borderInfoList; Loading
services/surfaceflinger/CompositionEngine/src/Output.cpp +33 −3 Original line number Original line Diff line number Diff line Loading @@ -28,8 +28,11 @@ #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/impl/planner/Planner.h> #include <compositionengine/impl/planner/Planner.h> #include <ftl/algorithm.h> #include <ftl/future.h> #include <ftl/future.h> #include <gui/TraceUtils.h> #include <gui/TraceUtils.h> #include <scheduler/FrameTargeter.h> #include <scheduler/Time.h> #include <optional> #include <optional> #include <thread> #include <thread> Loading Loading @@ -429,7 +432,28 @@ void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArg ftl::Future<std::monostate> Output::present( ftl::Future<std::monostate> Output::present( const compositionengine::CompositionRefreshArgs& refreshArgs) { const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str()); const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string { return ftl::Optional(getDisplayId()) .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); }) .transform([](const auto& frameTargetPtr) { return frameTargetPtr.get()->expectedPresentTime(); }) .transform([](TimePoint expectedPresentTime) { return base::StringPrintf(" vsyncIn %.2fms", ticks<std::milli, float>(expectedPresentTime - TimePoint::now())); }) .or_else([] { // There is no vsync for this output. return std::make_optional(std::string()); }) .value(); }; ATRACE_FORMAT("%s for %s%s", __func__, mNamePlusId.c_str(), stringifyExpectedPresentTime().c_str()); ALOGV(__FUNCTION__); ALOGV(__FUNCTION__); updateColorProfile(refreshArgs); updateColorProfile(refreshArgs); Loading Loading @@ -853,8 +877,14 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr return; return; } } editState().earliestPresentTime = refreshArgs.earliestPresentTime; if (auto frameTargetPtrOpt = ftl::Optional(getDisplayId()) editState().expectedPresentTime = refreshArgs.expectedPresentTime; .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); })) { editState().earliestPresentTime = frameTargetPtrOpt->get()->earliestPresentTime(); editState().expectedPresentTime = frameTargetPtrOpt->get()->expectedPresentTime().ns(); } editState().frameInterval = refreshArgs.frameInterval; editState().frameInterval = refreshArgs.frameInterval; editState().powerCallback = refreshArgs.powerCallback; editState().powerCallback = refreshArgs.powerCallback; Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +10 −2 Original line number Original line Diff line number Diff line Loading @@ -190,7 +190,6 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, const FrameTargeter::BeginFrameArgs beginFrameArgs = const FrameTargeter::BeginFrameArgs beginFrameArgs = {.frameBeginTime = SchedulerClock::now(), {.frameBeginTime = SchedulerClock::now(), .vsyncId = vsyncId, .vsyncId = vsyncId, // TODO(b/255601557): Calculate per display. .expectedVsyncTime = expectedVsyncTime, .expectedVsyncTime = expectedVsyncTime, .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration, .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration, .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration}; .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration}; Loading @@ -202,11 +201,20 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, FrameTargets targets; FrameTargets targets; targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target()); targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target()); // TODO (b/256196556): Followers should use the next VSYNC after the frontrunner, not the // pacesetter. // Update expectedVsyncTime, which may have been adjusted by beginFrame. expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime(); for (const auto& [id, display] : mDisplays) { for (const auto& [id, display] : mDisplays) { if (id == pacesetterPtr->displayId) continue; if (id == pacesetterPtr->displayId) continue; auto followerBeginFrameArgs = beginFrameArgs; followerBeginFrameArgs.expectedVsyncTime = display.schedulePtr->vsyncDeadlineAfter(expectedVsyncTime); FrameTargeter& targeter = *display.targeterPtr; FrameTargeter& targeter = *display.targeterPtr; targeter.beginFrame(beginFrameArgs, *display.schedulePtr); targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr); targets.try_emplace(id, &targeter.target()); targets.try_emplace(id, &targeter.target()); } } Loading
services/surfaceflinger/SurfaceFlinger.cpp +2 −3 Original line number Original line Diff line number Diff line Loading @@ -2681,6 +2681,8 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( if (const auto display = getCompositionDisplayLocked(id)) { if (const auto display = getCompositionDisplayLocked(id)) { refreshArgs.outputs.push_back(display); refreshArgs.outputs.push_back(display); } } refreshArgs.frameTargets.try_emplace(id, &targeter->target()); } } std::vector<DisplayId> displayIds; std::vector<DisplayId> displayIds; Loading Loading @@ -2753,9 +2755,6 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( // TODO(b/255601557) Update frameInterval per display // TODO(b/255601557) Update frameInterval per display refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, expectedPresentTime); refreshArgs.frameInterval = mScheduler->getNextFrameInterval(pacesetterId, expectedPresentTime); refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); refreshArgs.expectedPresentTime = expectedPresentTime.ns(); // TODO(b/255601557): Calculate and pass per-display values for each FrameTarget. refreshArgs.earliestPresentTime = pacesetterTarget.earliestPresentTime(); refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; { { auto& notifyExpectedPresentData = mNotifyExpectedPresentMap[pacesetterId]; auto& notifyExpectedPresentData = mNotifyExpectedPresentMap[pacesetterId]; Loading