diff options
23 files changed, 491 insertions, 179 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 70ccaf883e..252ba8e753 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -208,12 +208,12 @@ bool DisplayDevice::isPoweredOn() const { return mPowerMode && *mPowerMode != hal::PowerMode::OFF; } -void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps displayFps, Fps renderFps) { - ATRACE_INT(mActiveModeFPSTrace.c_str(), displayFps.getIntValue()); +void DisplayDevice::setActiveMode(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) { + ATRACE_INT(mActiveModeFPSTrace.c_str(), vsyncRate.getIntValue()); ATRACE_INT(mRenderFrameRateFPSTrace.c_str(), renderFps.getIntValue()); mRefreshRateSelector->setActiveMode(modeId, renderFps); - updateRefreshRateOverlayRate(displayFps, renderFps); + updateRefreshRateOverlayRate(vsyncRate, renderFps); } status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info, @@ -230,14 +230,14 @@ status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info, mIsModeSetPending = true; const auto& pendingMode = *info.modeOpt->modePtr; - ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), pendingMode.getFps().getIntValue()); + ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), pendingMode.getVsyncRate().getIntValue()); return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), pendingMode.getHwcId(), constraints, outTimeline); } -void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps displayFps, Fps renderFps) { - setActiveMode(modeId, displayFps, renderFps); +void DisplayDevice::finalizeModeChange(DisplayModeId modeId, Fps vsyncRate, Fps renderFps) { + setActiveMode(modeId, vsyncRate, renderFps); mIsModeSetPending = false; } @@ -253,7 +253,7 @@ nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const { return vsyncPeriod; } - return refreshRateSelector().getActiveMode().modePtr->getVsyncPeriod(); + return refreshRateSelector().getActiveMode().modePtr->getVsyncRate().getPeriodNsecs(); } ui::Dataspace DisplayDevice::getCompositionDataSpace() const { @@ -466,17 +466,19 @@ void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, bool sh features |= RefreshRateOverlay::Features::SetByHwc; } + // TODO(b/296636258) Update to use the render rate range in VRR mode. const auto fpsRange = mRefreshRateSelector->getSupportedRefreshRateRange(); mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, features); mRefreshRateOverlay->setLayerStack(getLayerStack()); mRefreshRateOverlay->setViewport(getSize()); - updateRefreshRateOverlayRate(getActiveMode().modePtr->getFps(), getActiveMode().fps, setByHwc); + updateRefreshRateOverlayRate(getActiveMode().modePtr->getVsyncRate(), getActiveMode().fps, + setByHwc); } -void DisplayDevice::updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc) { +void DisplayDevice::updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc) { ATRACE_CALL(); if (mRefreshRateOverlay && (!mRefreshRateOverlay->isSetByHwc() || setByHwc)) { - mRefreshRateOverlay->changeRefreshRate(displayFps, renderFps); + mRefreshRateOverlay->changeRefreshRate(vsyncRate, renderFps); } } @@ -486,7 +488,7 @@ bool DisplayDevice::onKernelTimerChanged(std::optional<DisplayModeId> desiredMod const auto newMode = mRefreshRateSelector->onKernelTimerChanged(desiredModeId, timerExpired); if (newMode) { - updateRefreshRateOverlayRate(newMode->modePtr->getFps(), newMode->fps); + updateRefreshRateOverlayRate(newMode->modePtr->getVsyncRate(), newMode->fps); return true; } } @@ -541,14 +543,14 @@ auto DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info, bool force) return DesiredActiveModeAction::None; } - setActiveMode(desiredMode.getId(), desiredMode.getFps(), info.modeOpt->fps); + setActiveMode(desiredMode.getId(), desiredMode.getVsyncRate(), info.modeOpt->fps); return DesiredActiveModeAction::InitiateRenderRateSwitch; } // Set the render frame rate to the current physical refresh rate to schedule the next // frame as soon as possible. - setActiveMode(currentMode.modePtr->getId(), currentMode.modePtr->getFps(), - currentMode.modePtr->getFps()); + setActiveMode(currentMode.modePtr->getId(), currentMode.modePtr->getVsyncRate(), + currentMode.modePtr->getVsyncRate()); // Initiate a mode change. mDesiredActiveModeChanged = true; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index a3fa701be2..a044534964 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -224,14 +224,14 @@ public: return mRefreshRateSelector->getActiveMode(); } - void setActiveMode(DisplayModeId, Fps displayFps, Fps renderFps); + void setActiveMode(DisplayModeId, Fps vsyncRate, Fps renderFps); status_t initiateModeChange(const ActiveModeInfo&, const hal::VsyncPeriodChangeConstraints& constraints, hal::VsyncPeriodChangeTimeline* outTimeline) REQUIRES(kMainThreadContext); - void finalizeModeChange(DisplayModeId, Fps displayFps, Fps renderFps) + void finalizeModeChange(DisplayModeId, Fps vsyncRate, Fps renderFps) REQUIRES(kMainThreadContext); scheduler::RefreshRateSelector& refreshRateSelector() const { return *mRefreshRateSelector; } @@ -246,7 +246,7 @@ public: // Enables an overlay to be displayed with the current refresh rate void enableRefreshRateOverlay(bool enable, bool setByHwc, bool showSpinner, bool showRenderRate, bool showInMiddle) REQUIRES(kMainThreadContext); - void updateRefreshRateOverlayRate(Fps displayFps, Fps renderFps, bool setByHwc = false); + void updateRefreshRateOverlayRate(Fps vsyncRate, Fps renderFps, bool setByHwc = false); bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; } bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired); diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h index 1810925c8e..422513be9b 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayMode.h +++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h @@ -32,6 +32,8 @@ #include "DisplayHardware/Hal.h" #include "Scheduler/StrongTyping.h" +#include <com_android_graphics_surfaceflinger_flags.h> + namespace android { namespace hal = android::hardware::graphics::composer::hal; @@ -49,6 +51,7 @@ using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, C using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>; using DisplayModeIterator = DisplayModes::const_iterator; +using namespace com::android::graphics::surfaceflinger; class DisplayMode { public: @@ -76,7 +79,12 @@ public: } Builder& setVsyncPeriod(nsecs_t vsyncPeriod) { - mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod); + mDisplayMode->mVsyncRate = Fps::fromPeriodNsecs(vsyncPeriod); + return *this; + } + + Builder& setVrrConfig(std::optional<hal::VrrConfig> vrrConfig) { + mDisplayMode->mVrrConfig = std::move(vrrConfig); return *this; } @@ -130,8 +138,17 @@ public: int32_t getWidth() const { return mResolution.getWidth(); } int32_t getHeight() const { return mResolution.getHeight(); } - Fps getFps() const { return mFps; } - nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); } + // Peak refresh rate represents the highest refresh rate that can be used + // for the presentation. + Fps getPeakFps() const { + return flags::vrr_config() && mVrrConfig + ? Fps::fromPeriodNsecs(mVrrConfig->minFrameIntervalNs) + : mVsyncRate; + } + + Fps getVsyncRate() const { return mVsyncRate; } + + std::optional<hal::VrrConfig> getVrrConfig() const { return mVrrConfig; } struct Dpi { float x = -1; @@ -155,23 +172,25 @@ private: PhysicalDisplayId mPhysicalDisplayId; ui::Size mResolution; - Fps mFps; + Fps mVsyncRate; Dpi mDpi; int32_t mGroup = -1; + std::optional<hal::VrrConfig> mVrrConfig; }; inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) { return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() && - lhs.getVsyncPeriod() == rhs.getVsyncPeriod() && lhs.getDpi() == rhs.getDpi() && - lhs.getGroup() == rhs.getGroup(); + lhs.getVsyncRate().getPeriodNsecs() == rhs.getVsyncRate().getPeriodNsecs() && + lhs.getDpi() == rhs.getDpi() && lhs.getGroup() == rhs.getGroup(); } inline std::string to_string(const DisplayMode& mode) { - return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, refreshRate=%s, " - "dpi=%.2fx%.2f, group=%d}", + return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, vsyncRate=%s, " + "dpi=%.2fx%.2f, group=%d, vrrConfig=%s}", mode.getId().value(), mode.getHwcId(), mode.getWidth(), - mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpi().x, - mode.getDpi().y, mode.getGroup()); + mode.getHeight(), to_string(mode.getVsyncRate()).c_str(), + mode.getDpi().x, mode.getDpi().y, mode.getGroup(), + to_string(mode.getVrrConfig()).c_str()); } template <typename... DisplayModePtrs> diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index a9bb928f59..812621f40a 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -285,13 +285,12 @@ std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigura std::vector<HWCDisplayMode> modes; modes.reserve(configs.size()); for (auto config : configs) { - auto hwcMode = HWCDisplayMode{ - .hwcId = static_cast<hal::HWConfigId>(config.configId), - .width = config.width, - .height = config.height, - .vsyncPeriod = config.vsyncPeriod, - .configGroup = config.configGroup, - }; + auto hwcMode = HWCDisplayMode{.hwcId = static_cast<hal::HWConfigId>(config.configId), + .width = config.width, + .height = config.height, + .vsyncPeriod = config.vsyncPeriod, + .configGroup = config.configGroup, + .vrrConfig = config.vrrConfig}; if (config.dpi) { hwcMode.dpiX = config.dpi->x; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 86f382596a..b4d3d28a35 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -102,11 +102,13 @@ public: float dpiX = -1.f; float dpiY = -1.f; int32_t configGroup = -1; + std::optional<hal::VrrConfig> vrrConfig; friend std::ostream& operator<<(std::ostream& os, const HWCDisplayMode& mode) { return os << "id=" << mode.hwcId << " res=" << mode.width << "x" << mode.height << " vsyncPeriod=" << mode.vsyncPeriod << " dpi=" << mode.dpiX << "x" - << mode.dpiY << " group=" << mode.configGroup; + << mode.dpiY << " group=" << mode.configGroup + << " vrrConfig=" << to_string(mode.vrrConfig).c_str(); } }; diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h index e95ae8934d..20f7548bea 100644 --- a/services/surfaceflinger/DisplayHardware/Hal.h +++ b/services/surfaceflinger/DisplayHardware/Hal.h @@ -24,6 +24,7 @@ #include <aidl/android/hardware/graphics/composer3/Composition.h> #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h> #include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h> +#include <aidl/android/hardware/graphics/composer3/VrrConfig.h> #define ERROR_HAS_CHANGES 5 @@ -73,6 +74,7 @@ using Vsync = IComposerClient::Vsync; using VsyncPeriodChangeConstraints = IComposerClient::VsyncPeriodChangeConstraints; using Hdr = aidl::android::hardware::graphics::common::Hdr; using DisplayConfiguration = V3_0::DisplayConfiguration; +using VrrConfig = V3_0::VrrConfig; } // namespace hardware::graphics::composer::hal @@ -148,6 +150,34 @@ inline std::string to_string( } } +inline std::string to_string( + const std::optional<aidl::android::hardware::graphics::composer3::VrrConfig>& vrrConfig) { + if (vrrConfig) { + std::ostringstream out; + out << "{minFrameIntervalNs=" << vrrConfig->minFrameIntervalNs << ", "; + out << "frameIntervalPowerHints={"; + if (vrrConfig->frameIntervalPowerHints) { + const auto& powerHint = *vrrConfig->frameIntervalPowerHints; + for (size_t i = 0; i < powerHint.size(); i++) { + if (i > 0) out << ", "; + out << "[frameIntervalNs=" << powerHint[i]->frameIntervalNs + << ", averageRefreshPeriodNs=" << powerHint[i]->averageRefreshPeriodNs << "]"; + } + } + out << "}, "; + out << "notifyExpectedPresentConfig={"; + if (vrrConfig->notifyExpectedPresentConfig) { + out << "notifyExpectedPresentHeadsUpNs=" + << vrrConfig->notifyExpectedPresentConfig->notifyExpectedPresentHeadsUpNs + << ", notifyExpectedPresentTimeoutNs=" + << vrrConfig->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs; + } + out << "}}"; + return out.str(); + } + return "N/A"; +} + inline std::string to_string(hardware::graphics::composer::hal::V2_4::Error error) { // 5 is reserved for historical reason, during validation 5 means has changes. if (ERROR_HAS_CHANGES == static_cast<int32_t>(error)) { diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 577211f461..e918dc9045 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -27,7 +27,7 @@ namespace android { -auto RefreshRateOverlay::draw(int displayFps, int renderFps, SkColor color, +auto RefreshRateOverlay::draw(int vsyncRate, int renderFps, SkColor color, ui::Transform::RotationFlags rotation, ftl::Flags<Features> features) -> Buffers { const size_t loopCount = features.test(Features::Spinner) ? 6 : 1; @@ -70,7 +70,7 @@ auto RefreshRateOverlay::draw(int displayFps, int renderFps, SkColor color, canvas->setMatrix(canvasTransform); int left = 0; - drawNumber(displayFps, left, color, *canvas); + drawNumber(vsyncRate, left, color, *canvas); left += 3 * (kDigitWidth + kDigitSpace); if (features.test(Features::Spinner)) { switch (i) { @@ -153,7 +153,7 @@ RefreshRateOverlay::RefreshRateOverlay(FpsRange fpsRange, ftl::Flags<Features> f .apply(); } -auto RefreshRateOverlay::getOrCreateBuffers(Fps displayFps, Fps renderFps) -> const Buffers& { +auto RefreshRateOverlay::getOrCreateBuffers(Fps vsyncRate, Fps renderFps) -> const Buffers& { static const Buffers kNoBuffers; if (!mSurfaceControl) return kNoBuffers; @@ -180,16 +180,16 @@ auto RefreshRateOverlay::getOrCreateBuffers(Fps displayFps, Fps renderFps) -> co createTransaction().setTransform(mSurfaceControl->get(), transform).apply(); BufferCache::const_iterator it = - mBufferCache.find({displayFps.getIntValue(), renderFps.getIntValue(), transformHint}); + mBufferCache.find({vsyncRate.getIntValue(), renderFps.getIntValue(), transformHint}); if (it == mBufferCache.end()) { // HWC minFps is not known by the framework in order // to consider lower rates we set minFps to 0. const int minFps = isSetByHwc() ? 0 : mFpsRange.min.getIntValue(); const int maxFps = mFpsRange.max.getIntValue(); - // Clamp to the range. The current displayFps may be outside of this range if the display + // Clamp to the range. The current vsyncRate may be outside of this range if the display // has changed its set of supported refresh rates. - const int displayIntFps = std::clamp(displayFps.getIntValue(), minFps, maxFps); + const int displayIntFps = std::clamp(vsyncRate.getIntValue(), minFps, maxFps); const int renderIntFps = renderFps.getIntValue(); // Ensure non-zero range to avoid division by zero. @@ -242,17 +242,17 @@ void RefreshRateOverlay::setLayerStack(ui::LayerStack stack) { createTransaction().setLayerStack(mSurfaceControl->get(), stack).apply(); } -void RefreshRateOverlay::changeRefreshRate(Fps displayFps, Fps renderFps) { - mDisplayFps = displayFps; +void RefreshRateOverlay::changeRefreshRate(Fps vsyncRate, Fps renderFps) { + mVsyncRate = vsyncRate; mRenderFps = renderFps; - const auto buffer = getOrCreateBuffers(displayFps, renderFps)[mFrame]; + const auto buffer = getOrCreateBuffers(vsyncRate, renderFps)[mFrame]; createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply(); } void RefreshRateOverlay::animate() { - if (!mFeatures.test(Features::Spinner) || !mDisplayFps) return; + if (!mFeatures.test(Features::Spinner) || !mVsyncRate) return; - const auto& buffers = getOrCreateBuffers(*mDisplayFps, *mRenderFps); + const auto& buffers = getOrCreateBuffers(*mVsyncRate, *mRenderFps); mFrame = (mFrame + 1) % buffers.size(); const auto buffer = buffers[mFrame]; createTransaction().setBuffer(mSurfaceControl->get(), buffer).apply(); diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 65c61cb4ca..c0fc79b0ba 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -56,7 +56,7 @@ public: private: using Buffers = std::vector<sp<GraphicBuffer>>; - static Buffers draw(int displayFps, int renderFps, SkColor, ui::Transform::RotationFlags, + static Buffers draw(int vsyncRate, int renderFps, SkColor, ui::Transform::RotationFlags, ftl::Flags<Features>); static void drawNumber(int number, int left, SkColor, SkCanvas&); @@ -65,12 +65,12 @@ private: SurfaceComposerClient::Transaction createTransaction() const; struct Key { - int displayFps; + int vsyncRate; int renderFps; ui::Transform::RotationFlags flags; bool operator==(Key other) const { - return displayFps == other.displayFps && renderFps == other.renderFps && + return vsyncRate == other.vsyncRate && renderFps == other.renderFps && flags == other.flags; } }; @@ -78,7 +78,7 @@ private: using BufferCache = ftl::SmallMap<Key, Buffers, 9>; BufferCache mBufferCache; - std::optional<Fps> mDisplayFps; + std::optional<Fps> mVsyncRate; std::optional<Fps> mRenderFps; size_t mFrame = 0; diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index be28e98ead..3ee6a4d854 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -39,12 +39,16 @@ #include "../SurfaceFlingerProperties.h" #include "RefreshRateSelector.h" +#include <com_android_graphics_surfaceflinger_flags.h> + #undef LOG_TAG #define LOG_TAG "RefreshRateSelector" namespace android::scheduler { namespace { +using namespace com::android::graphics::surfaceflinger; + struct RefreshRateScore { FrameRateMode frameRateMode; float overallScore; @@ -69,7 +73,7 @@ std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) { // Add all supported refresh rates. for (const auto& [id, mode] : modes) { - knownFrameRates.push_back(mode->getFps()); + knownFrameRates.push_back(mode->getPeakFps()); } // Sort and remove duplicates. @@ -91,17 +95,17 @@ std::vector<DisplayModeIterator> sortByRefreshRate(const DisplayModes& modes) { const auto& mode1 = it1->second; const auto& mode2 = it2->second; - if (mode1->getVsyncPeriod() == mode2->getVsyncPeriod()) { + if (mode1->getVsyncRate().getPeriodNsecs() == mode2->getVsyncRate().getPeriodNsecs()) { return mode1->getGroup() > mode2->getGroup(); } - return mode1->getVsyncPeriod() > mode2->getVsyncPeriod(); + return mode1->getVsyncRate().getPeriodNsecs() > mode2->getVsyncRate().getPeriodNsecs(); }); return sortedModes; } -std::pair<unsigned, unsigned> divisorRange(Fps fps, FpsRange range, +std::pair<unsigned, unsigned> divisorRange(Fps vsyncRate, Fps peakFps, FpsRange range, RefreshRateSelector::Config::FrameRateOverride config) { if (config != RefreshRateSelector::Config::FrameRateOverride::Enabled) { return {1, 1}; @@ -109,8 +113,14 @@ std::pair<unsigned, unsigned> divisorRange(Fps fps, FpsRange range, using fps_approx_ops::operator/; // use signed type as `fps / range.max` might be 0 - const auto start = std::max(1, static_cast<int>(fps / range.max) - 1); - const auto end = fps / + auto start = std::max(1, static_cast<int>(peakFps / range.max) - 1); + if (flags::vrr_config()) { + start = std::max(1, + static_cast<int>(vsyncRate / + std::min(range.max, peakFps, fps_approx_ops::operator<)) - + 1); + } + const auto end = vsyncRate / std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate, fps_approx_ops::operator<); @@ -123,7 +133,8 @@ bool shouldEnableFrameRateOverride(const std::vector<DisplayModeIterator>& sorte for (const auto it2 : sortedModes) { const auto& mode2 = it2->second; - if (RefreshRateSelector::getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) { + if (RefreshRateSelector::getFrameRateDivisor(mode1->getPeakFps(), + mode2->getPeakFps()) >= 2) { return true; } } @@ -176,10 +187,12 @@ auto RefreshRateSelector::createFrameRateModes( if (!filterModes(*mode)) { continue; } + const auto vsyncRate = mode->getVsyncRate(); + const auto peakFps = mode->getPeakFps(); const auto [start, end] = - divisorRange(mode->getFps(), renderRange, mConfig.enableFrameRateOverride); + divisorRange(vsyncRate, peakFps, renderRange, mConfig.enableFrameRateOverride); for (auto divisor = start; divisor <= end; divisor++) { - const auto fps = mode->getFps() / divisor; + const auto fps = vsyncRate / divisor; using fps_approx_ops::operator<; if (divisor > 1 && fps < kMinSupportedFrameRate) { break; @@ -199,28 +212,30 @@ auto RefreshRateSelector::createFrameRateModes( const auto [existingIter, emplaceHappened] = ratesMap.try_emplace(Key{fps, mode->getGroup()}, it); if (emplaceHappened) { - ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(), - to_string(mode->getFps()).c_str()); + ALOGV("%s: including %s (%s(%s))", __func__, to_string(fps).c_str(), + to_string(peakFps).c_str(), to_string(vsyncRate).c_str()); } else { // If the primary physical range is a single rate, prefer to stay in that rate // even if there is a lower physical refresh rate available. This would cause more // cases to stay within the primary physical range - const Fps existingModeFps = existingIter->second->second->getFps(); + const Fps existingModeFps = existingIter->second->second->getPeakFps(); const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() && policy.primaryRanges.physical.includes(existingModeFps); const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() && - policy.primaryRanges.physical.includes(mode->getFps()); + policy.primaryRanges.physical.includes(mode->getPeakFps()); if (newModeIsPrimaryRange == existingModeIsPrimaryRange) { // We might need to update the map as we found a lower refresh rate - if (isStrictlyLess(mode->getFps(), existingModeFps)) { + if (isStrictlyLess(mode->getPeakFps(), existingModeFps)) { existingIter->second = it; - ALOGV("%s: changing %s (%s) as we found a lower physical rate", __func__, - to_string(fps).c_str(), to_string(mode->getFps()).c_str()); + ALOGV("%s: changing %s (%s(%s)) as we found a lower physical rate", + __func__, to_string(fps).c_str(), to_string(peakFps).c_str(), + to_string(vsyncRate).c_str()); } } else if (newModeIsPrimaryRange) { existingIter->second = it; - ALOGV("%s: changing %s (%s) to stay in the primary range", __func__, - to_string(fps).c_str(), to_string(mode->getFps()).c_str()); + ALOGV("%s: changing %s (%s(%s)) to stay in the primary range", __func__, + to_string(fps).c_str(), to_string(peakFps).c_str(), + to_string(vsyncRate).c_str()); } } } @@ -237,8 +252,8 @@ auto RefreshRateSelector::createFrameRateModes( const auto lowestRefreshRateIt = std::min_element(frameRateModes.begin(), frameRateModes.end(), [](const FrameRateMode& lhs, const FrameRateMode& rhs) { - return isStrictlyLess(lhs.modePtr->getFps(), - rhs.modePtr->getFps()); + return isStrictlyLess(lhs.modePtr->getVsyncRate(), + rhs.modePtr->getVsyncRate()); }); frameRateModes.erase(frameRateModes.begin(), lowestRefreshRateIt); @@ -623,7 +638,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi } const bool inPrimaryPhysicalRange = - policy->primaryRanges.physical.includes(modePtr->getFps()); + policy->primaryRanges.physical.includes(modePtr->getPeakFps()); const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps); if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) || !inPrimaryRenderRange) && @@ -664,21 +679,24 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi Fps::fromValue(mConfig.frameRateMultipleThreshold / 2); if (fixedSourceLayer && layerBelowThreshold) { const bool modeAboveThreshold = - modePtr->getFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); + modePtr->getPeakFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); if (modeAboveThreshold) { - ALOGV("%s gives %s (%s) fixed source (above threshold) score of %.4f", + ALOGV("%s gives %s (%s(%s)) fixed source (above threshold) score of %.4f", formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(), - to_string(modePtr->getFps()).c_str(), layerScore); + to_string(modePtr->getPeakFps()).c_str(), + to_string(modePtr->getVsyncRate()).c_str(), layerScore); fixedRateBelowThresholdLayersScore.modeAboveThreshold += weightedLayerScore; } else { - ALOGV("%s gives %s (%s) fixed source (below threshold) score of %.4f", + ALOGV("%s gives %s (%s(%s)) fixed source (below threshold) score of %.4f", formatLayerInfo(layer, weight).c_str(), to_string(fps).c_str(), - to_string(modePtr->getFps()).c_str(), layerScore); + to_string(modePtr->getPeakFps()).c_str(), + to_string(modePtr->getVsyncRate()).c_str(), layerScore); fixedRateBelowThresholdLayersScore.modeBelowThreshold += weightedLayerScore; } } else { - ALOGV("%s gives %s (%s) score of %.4f", formatLayerInfo(layer, weight).c_str(), - to_string(fps).c_str(), to_string(modePtr->getFps()).c_str(), layerScore); + ALOGV("%s gives %s (%s(%s)) score of %.4f", formatLayerInfo(layer, weight).c_str(), + to_string(fps).c_str(), to_string(modePtr->getPeakFps()).c_str(), + to_string(modePtr->getVsyncRate()).c_str(), layerScore); overallScore += weightedLayerScore; } } @@ -699,13 +717,14 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi [](RefreshRateScore max, RefreshRateScore current) { return current.overallScore > max.overallScore; }); - ALOGV("%s (%s) is the best refresh rate without fixed source layers. It is %s the " + ALOGV("%s (%s(%s)) is the best refresh rate without fixed source layers. It is %s the " "threshold for " "refresh rate multiples", to_string(maxScoreIt->frameRateMode.fps).c_str(), - to_string(maxScoreIt->frameRateMode.modePtr->getFps()).c_str(), + to_string(maxScoreIt->frameRateMode.modePtr->getPeakFps()).c_str(), + to_string(maxScoreIt->frameRateMode.modePtr->getVsyncRate()).c_str(), maxScoreAboveThreshold ? "above" : "below"); - return maxScoreIt->frameRateMode.modePtr->getFps() >= + return maxScoreIt->frameRateMode.modePtr->getPeakFps() >= Fps::fromValue(mConfig.frameRateMultipleThreshold); }(); @@ -715,8 +734,9 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi if (maxScoreAboveThreshold) { overallScore += fixedRateBelowThresholdLayersScore.modeAboveThreshold; } - ALOGV("%s (%s) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(), - to_string(frameRateMode.modePtr->getFps()).c_str(), overallScore); + ALOGV("%s (%s(%s)) adjusted overallScore is %.4f", to_string(frameRateMode.fps).c_str(), + to_string(frameRateMode.modePtr->getPeakFps()).c_str(), + to_string(frameRateMode.modePtr->getVsyncRate()).c_str(), overallScore); } // Now that we scored all the refresh rates we need to pick the one that got the highest @@ -842,6 +862,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme const auto* policyPtr = getCurrentPolicyLocked(); // We don't want to run lower than 30fps + // TODO(b/297600226): revise this for dVRR const Fps minFrameRate = std::max(policyPtr->appRequestRanges.render.min, 30_Hz, isApproxLess); using fps_approx_ops::operator/; @@ -933,7 +954,7 @@ ftl::Optional<FrameRateMode> RefreshRateSelector::onKernelTimerChanged( const auto current = [&]() REQUIRES(mLock) -> FrameRateMode { if (desiredActiveModeId) { const auto& modePtr = mDisplayModes.get(*desiredActiveModeId)->get(); - return FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)}; + return FrameRateMode{modePtr->getPeakFps(), ftl::as_non_null(modePtr)}; } return getActiveModeLocked(); @@ -944,7 +965,7 @@ ftl::Optional<FrameRateMode> RefreshRateSelector::onKernelTimerChanged( return {}; } - return timerExpired ? FrameRateMode{min->getFps(), ftl::as_non_null(min)} : current; + return timerExpired ? FrameRateMode{min->getPeakFps(), ftl::as_non_null(min)} : current; } const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const { @@ -970,12 +991,12 @@ const DisplayModePtr& RefreshRateSelector::getMaxRefreshRateByPolicyLocked(int a bool maxByAnchorFound = false; for (auto it = mPrimaryFrameRates.rbegin(); it != mPrimaryFrameRates.rend(); ++it) { using namespace fps_approx_ops; - if (it->modePtr->getFps() > (*max)->getFps()) { + if (it->modePtr->getPeakFps() > (*max)->getPeakFps()) { max = &it->modePtr; } if (anchorGroup == it->modePtr->getGroup() && - it->modePtr->getFps() >= (*maxByAnchor)->getFps()) { + it->modePtr->getPeakFps() >= (*maxByAnchor)->getPeakFps()) { maxByAnchorFound = true; maxByAnchor = &it->modePtr; } @@ -1053,8 +1074,9 @@ auto RefreshRateSelector::rankFrameRates(std::optional<int> anchorGroupOpt, return; } - ALOGV("%s(%s) %s (%s) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(), - to_string(frameRateMode.fps).c_str(), to_string(modePtr->getFps()).c_str(), score); + ALOGV("%s(%s) %s (%s(%s)) scored %.2f", whence, ftl::enum_string(refreshRateOrder).c_str(), + to_string(frameRateMode.fps).c_str(), to_string(modePtr->getPeakFps()).c_str(), + to_string(modePtr->getVsyncRate()).c_str(), score); ranking.emplace_back(ScoredFrameRate{frameRateMode, score}); }; @@ -1134,8 +1156,8 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a mDisplayModes = std::move(modes); const auto activeModeOpt = mDisplayModes.get(activeModeId); LOG_ALWAYS_FATAL_IF(!activeModeOpt); - mActiveModeOpt = - FrameRateMode{activeModeOpt->get()->getFps(), ftl::as_non_null(activeModeOpt->get())}; + mActiveModeOpt = FrameRateMode{activeModeOpt->get()->getPeakFps(), + ftl::as_non_null(activeModeOpt->get())}; const auto sortedModes = sortByRefreshRate(mDisplayModes); mMinRefreshRateModeIt = sortedModes.front(); @@ -1161,7 +1183,7 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::AppOverrideNativeRefreshRates) { for (const auto& [_, mode] : mDisplayModes) { - mAppOverrideNativeRefreshRates.try_emplace(mode->getFps(), ftl::unit); + mAppOverrideNativeRefreshRates.try_emplace(mode->getPeakFps(), ftl::unit); } } @@ -1171,7 +1193,7 @@ void RefreshRateSelector::updateDisplayModes(DisplayModes modes, DisplayModeId a bool RefreshRateSelector::isPolicyValidLocked(const Policy& policy) const { // defaultMode must be a valid mode, and within the given refresh rate range. if (const auto mode = mDisplayModes.get(policy.defaultMode)) { - if (!policy.primaryRanges.physical.includes(mode->get()->getFps())) { + if (!policy.primaryRanges.physical.includes(mode->get()->getPeakFps())) { ALOGE("Default mode is not in the primary range."); return false; } @@ -1284,8 +1306,8 @@ void RefreshRateSelector::constructAvailableRefreshRates() { return mode.getResolution() == defaultMode->getResolution() && mode.getDpi() == defaultMode->getDpi() && (policy->allowGroupSwitching || mode.getGroup() == defaultMode->getGroup()) && - ranges.physical.includes(mode.getFps()) && - (supportsFrameRateOverride() || ranges.render.includes(mode.getFps())); + ranges.physical.includes(mode.getPeakFps()) && + (supportsFrameRateOverride() || ranges.render.includes(mode.getPeakFps())); }; auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render); @@ -1340,13 +1362,13 @@ Fps RefreshRateSelector::findClosestKnownFrameRate(Fps frameRate) const { auto RefreshRateSelector::getIdleTimerAction() const -> KernelIdleTimerAction { std::lock_guard lock(mLock); - const Fps deviceMinFps = mMinRefreshRateModeIt->second->getFps(); + const Fps deviceMinFps = mMinRefreshRateModeIt->second->getPeakFps(); const DisplayModePtr& minByPolicy = getMinRefreshRateByPolicyLocked(); // Kernel idle timer will set the refresh rate to the device min. If DisplayManager says that // the min allowed refresh rate is higher than the device min, we do not want to enable the // timer. - if (isStrictlyLess(deviceMinFps, minByPolicy->getFps())) { + if (isStrictlyLess(deviceMinFps, minByPolicy->getPeakFps())) { return KernelIdleTimerAction::TurnOff; } diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h index 73e1d380fa..9bcbc0e9f7 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h @@ -253,7 +253,8 @@ public: FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { std::lock_guard lock(mLock); - return {mMinRefreshRateModeIt->second->getFps(), mMaxRefreshRateModeIt->second->getFps()}; + return {mMinRefreshRateModeIt->second->getPeakFps(), + mMaxRefreshRateModeIt->second->getPeakFps()}; } ftl::Optional<FrameRateMode> onKernelTimerChanged( diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 27c96f7d4f..595550bd3d 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -494,7 +494,7 @@ void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEn if (display.schedulePtr->isHardwareVsyncAllowed(allowToEnable)) { if (!refreshRate) { - refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps(); + refreshRate = display.selectorPtr->getActiveMode().modePtr->getVsyncRate(); } if (refreshRate->isValid()) { constexpr bool kForce = false; @@ -542,7 +542,7 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) { to_string(mode.fps).c_str(), to_string(renderFrameRate).c_str(), id.value); ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(), - to_string(mode.modePtr->getFps()).c_str()); + to_string(mode.modePtr->getVsyncRate()).c_str()); display.schedulePtr->getTracker().setRenderRate(renderFrameRate); } @@ -717,7 +717,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number - const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getFps(); + const Fps refreshRate = pacesetterSelectorPtr()->getActiveMode().modePtr->getPeakFps(); constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER = 65_Hz; using namespace fps_approx_ops; @@ -877,7 +877,7 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked( newVsyncSchedulePtr = pacesetter.schedulePtr; - const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps(); + const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getVsyncRate(); constexpr bool kForce = true; newVsyncSchedulePtr->startPeriodTransition(refreshRate.getPeriod(), kForce); } diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h index a24e43f9d6..b6cb373b7e 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h @@ -143,7 +143,7 @@ private: */ class WorkDuration : public VsyncConfiguration { public: - explicit WorkDuration(Fps currentRefrshRate); + explicit WorkDuration(Fps currentRefreshRate); protected: // Used for unit tests diff --git a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h index db38ebe658..59a6df23fd 100644 --- a/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h +++ b/services/surfaceflinger/Scheduler/include/scheduler/FrameRateMode.h @@ -36,7 +36,8 @@ struct FrameRateMode { }; inline std::string to_string(const FrameRateMode& mode) { - return to_string(mode.fps) + " (" + to_string(mode.modePtr->getFps()) + ")"; + return to_string(mode.fps) + " (" + to_string(mode.modePtr->getPeakFps()) + "(" + + to_string(mode.modePtr->getVsyncRate()) + "))"; } } // namespace android::scheduler diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e6a2de5d4a..54d6740c38 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -498,6 +498,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mMiscFlagValue = flags::misc1(); mConnectedDisplayFlagValue = flags::connected_display(); mMisc2FlagEarlyBootValue = flags::late_boot_misc2(); + mVrrConfigFlagValue = flags::vrr_config(); } LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() { @@ -1043,8 +1044,8 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info outMode.xDpi = xDpi; outMode.yDpi = yDpi; - const nsecs_t period = mode->getVsyncPeriod(); - outMode.refreshRate = Fps::fromPeriodNsecs(period).getValue(); + const auto peakFps = mode->getPeakFps(); + outMode.refreshRate = peakFps.getValue(); const auto vsyncConfigSet = mVsyncConfiguration->getConfigsForRefreshRate(Fps::fromValue(outMode.refreshRate)); @@ -1064,7 +1065,7 @@ void SurfaceFlinger::getDynamicDisplayInfoInternal(ui::DynamicDisplayInfo*& info // // We add an additional 1ms to allow for processing time and // differences between the ideal and actual refresh rate. - outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000; + outMode.presentationDeadline = peakFps.getPeriodNsecs() - outMode.sfVsyncOffset + 1000000; excludeDolbyVisionIf4k30Present(display->getHdrCapabilities().getSupportedHdrTypes(), outMode); info->supportedDisplayModes.push_back(outMode); @@ -1199,7 +1200,7 @@ void SurfaceFlinger::setDesiredActiveMode(display::DisplayModeRequest&& request, // Start receiving vsync samples now, so that we can detect a period // switch. mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, - mode.modePtr->getFps()); + mode.modePtr->getVsyncRate()); // As we called to set period, we will call to onRefreshRateChangeCompleted once // VsyncController model is locked. @@ -1253,7 +1254,7 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke const auto& snapshot = snapshotRef.get(); const auto fpsOpt = snapshot.displayModes().get(modeId).transform( - [](const DisplayModePtr& mode) { return mode->getFps(); }); + [](const DisplayModePtr& mode) { return mode->getPeakFps(); }); if (!fpsOpt) { ALOGE("%s: Invalid mode %d for display %s", whence, modeId.value(), @@ -1302,7 +1303,7 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { } const auto& activeMode = *upcomingModeInfo.modeOpt; - display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getFps(), + display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(), activeMode.fps); if (displayId == mActiveDisplayId) { @@ -1327,10 +1328,10 @@ void SurfaceFlinger::desiredActiveModeChangeDone(const sp<DisplayDevice>& displa const auto desiredActiveMode = display->getDesiredActiveMode(); const auto& modeOpt = desiredActiveMode->modeOpt; const auto displayId = modeOpt->modePtr->getPhysicalDisplayId(); - const auto displayFps = modeOpt->modePtr->getFps(); + const auto vsyncRate = modeOpt->modePtr->getVsyncRate(); const auto renderFps = modeOpt->fps; clearDesiredActiveModeState(display); - mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, displayFps); + mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */, vsyncRate); mScheduler->setRenderRate(displayId, renderFps); if (displayId == mActiveDisplayId) { @@ -1371,7 +1372,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() { } ALOGV("%s changing active mode to %d(%s) for display %s", __func__, desiredModeId.value(), - to_string(displayModePtrOpt->get()->getFps()).c_str(), + to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(), to_string(display->getId()).c_str()); if (display->getActiveMode() == desiredActiveMode->modeOpt) { @@ -3211,6 +3212,7 @@ std::pair<DisplayModes, DisplayModePtr> SurfaceFlinger::loadDisplayModes( .setPhysicalDisplayId(displayId) .setResolution({hwcMode.width, hwcMode.height}) .setVsyncPeriod(hwcMode.vsyncPeriod) + .setVrrConfig(hwcMode.vrrConfig) .setDpiX(hwcMode.dpiX) .setDpiY(hwcMode.dpiY) .setGroup(hwcMode.configGroup) @@ -3434,7 +3436,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( if (const auto& physical = state.physical) { const auto& mode = *physical->activeMode; - display->setActiveMode(mode.getId(), mode.getFps(), mode.getFps()); + display->setActiveMode(mode.getId(), mode.getVsyncRate(), mode.getVsyncRate()); } display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack)); @@ -5677,7 +5679,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: display->setPowerMode(mode); - const auto refreshRate = display->refreshRateSelector().getActiveMode().modePtr->getFps(); + const auto refreshRate = display->refreshRateSelector().getActiveMode().modePtr->getVsyncRate(); if (!currentModeOpt || *currentModeOpt == hal::PowerMode::OFF) { // Turn on the display @@ -6385,6 +6387,7 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp StringAppendF(&result, "Misc2FlagValue: %s (%s after boot)\n", mMisc2FlagLateBootValue ? "true" : "false", mMisc2FlagEarlyBootValue == mMisc2FlagLateBootValue ? "stable" : "modified"); + StringAppendF(&result, "VrrConfigFlagValue: %s\n", mVrrConfigFlagValue ? "true" : "false"); getRenderEngine().dump(result); @@ -6404,7 +6407,7 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp std::string fps, xDpi, yDpi; if (const auto activeModePtr = display->refreshRateSelector().getActiveMode().modePtr.get()) { - fps = to_string(activeModePtr->getFps()); + fps = to_string(activeModePtr->getVsyncRate()); const auto dpi = activeModePtr->getDpi(); xDpi = base::StringPrintf("%.2f", dpi.x); @@ -7967,7 +7970,7 @@ ftl::Optional<scheduler::FrameRateMode> SurfaceFlinger::getPreferredDisplayMode( return snapshot.displayModes().get(defaultModeId); }) .transform([](const DisplayModePtr& modePtr) { - return scheduler::FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)}; + return scheduler::FrameRateMode{modePtr->getPeakFps(), ftl::as_non_null(modePtr)}; }); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e22dd5680f..ef6b8159e4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1457,6 +1457,7 @@ private: bool mConnectedDisplayFlagValue; bool mMisc2FlagEarlyBootValue; bool mMisc2FlagLateBootValue; + bool mVrrConfigFlagValue; }; class SurfaceComposerAIDL : public gui::BnSurfaceComposer { diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 437fd35c15..c4077dfbaa 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -666,7 +666,7 @@ public: } mRefreshRateSelector = std::make_shared<scheduler::RefreshRateSelector>(modes, kModeId60); - const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getFps(); + const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getVsyncRate(); mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps); mFlinger->mRefreshRateStats = diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp index 4d1a5ffa67..cbbfa1695c 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp @@ -390,7 +390,7 @@ void SchedulerFuzzer::fuzzRefreshRateSelector() { PowerMode::OFF); const auto fpsOpt = displayModes.get(modeId).transform( - [](const DisplayModePtr& mode) { return mode->getFps(); }); + [](const DisplayModePtr& mode) { return mode->getVsyncRate(); }); refreshRateStats.setRefreshRate(*fpsOpt); refreshRateStats.setPowerMode(mFdp.PickValueInArray(kPowerModes)); diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig index 6519d3ad34..bfc03aae09 100644 --- a/services/surfaceflinger/surfaceflinger_flags.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags.aconfig @@ -22,3 +22,11 @@ flag{ description: "This flag controls minor miscellaneous SurfaceFlinger changes. Cannot be read before boot finished!" bug: "297389311" } + +flag { + name: "vrr_config" + namespace: "core_graphics" + description: "Controls SurfaceFlinger support for VRR Configurations" + bug: "284845445" + is_fixed_read_only: true +} diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 91c6239c87..9b46009704 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -703,7 +703,7 @@ TEST_F(EventThreadTest, postConfigChangedPrimary) { .setId(DisplayModeId(7)) .setVsyncPeriod(16666666) .build(); - const Fps fps = mode->getFps() / 2; + const Fps fps = mode->getPeakFps() / 2; mThread->onModeChanged({fps, ftl::as_non_null(mode)}); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, fps.getPeriodNsecs()); @@ -717,7 +717,7 @@ TEST_F(EventThreadTest, postConfigChangedExternal) { .setId(DisplayModeId(5)) .setVsyncPeriod(16666666) .build(); - const Fps fps = mode->getFps() / 2; + const Fps fps = mode->getPeakFps() / 2; mThread->onModeChanged({fps, ftl::as_non_null(mode)}); expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, fps.getPeriodNsecs()); @@ -731,7 +731,7 @@ TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { .setId(DisplayModeId(7)) .setVsyncPeriod(16666666) .build(); - const Fps fps = mode->getFps() / 2; + const Fps fps = mode->getPeakFps() / 2; mThread->onModeChanged({fps, ftl::as_non_null(mode)}); expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, fps.getPeriodNsecs()); } @@ -748,7 +748,7 @@ TEST_F(EventThreadTest, suppressConfigChanged) { .setId(DisplayModeId(9)) .setVsyncPeriod(16666666) .build(); - const Fps fps = mode->getFps() / 2; + const Fps fps = mode->getPeakFps() / 2; mThread->onModeChanged({fps, ftl::as_non_null(mode)}); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, fps.getPeriodNsecs()); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index 50c1626971..264b172107 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -36,6 +36,9 @@ #include "libsurfaceflinger_unittest_main.h" +#include <com_android_graphics_surfaceflinger_flags.h> + +using namespace com::android::graphics::surfaceflinger; using namespace std::chrono_literals; namespace android::scheduler { @@ -48,6 +51,7 @@ using LayerVoteType = RefreshRateSelector::LayerVoteType; using SetPolicyResult = RefreshRateSelector::SetPolicyResult; using mock::createDisplayMode; +using mock::createVrrDisplayMode; struct TestableRefreshRateSelector : RefreshRateSelector { using RefreshRateSelector::FrameRateRanking; @@ -201,6 +205,19 @@ protected: static inline const ftl::NonNull<DisplayModePtr> kMode10 = ftl::as_non_null(createDisplayMode(kModeId10, 10_Hz)); + // VRR modes + static inline const ftl::NonNull<DisplayModePtr> kVrrMode120TE240 = ftl::as_non_null( + createVrrDisplayMode(kModeId120, 240_Hz, + hal::VrrConfig{ + .minFrameIntervalNs = + static_cast<Fps>(120_Hz).getPeriodNsecs()})); + + static inline const ftl::NonNull<DisplayModePtr> kVrrMode60TE120 = ftl::as_non_null( + createVrrDisplayMode(kModeId60, 120_Hz, + hal::VrrConfig{.minFrameIntervalNs = + static_cast<Fps>(60_Hz).getPeriodNsecs()}, + /*group=*/1)); + // Test configurations. static inline const DisplayModes kModes_60 = makeModes(kMode60); static inline const DisplayModes kModes_35_60_90 = makeModes(kMode35, kMode60, kMode90); @@ -225,6 +242,11 @@ protected: static inline const DisplayModes kModes_1_5_10 = makeModes(kMode1, kMode5, kMode10); static inline const DisplayModes kModes_60_90_120 = makeModes(kMode60, kMode90, kMode120); + // VRR display modes + static inline const DisplayModes kVrrMode_120 = makeModes(kVrrMode120TE240); + static inline const DisplayModes kVrrModes_60_120 = + makeModes(kVrrMode60TE120, kVrrMode120TE240); + // This is a typical TV configuration. static inline const DisplayModes kModes_24_25_30_50_60_Frac = makeModes(kMode24, kMode24Frac, kMode25, kMode30, kMode30Frac, kMode50, kMode60, @@ -973,7 +995,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo) { lr.desiredRefreshRate = Fps::fromValue(fps); const auto mode = selector.getBestFrameRateMode(layers); EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " - << to_string(mode->getFps()); + << to_string(mode->getPeakFps()) << "(" + << to_string(mode->getVsyncRate()) << ")"; } } @@ -988,7 +1011,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_24FpsVideo_multipleThreshol lr.desiredRefreshRate = Fps::fromValue(fps); const auto mode = selector.getBestFrameRateMode(layers); EXPECT_EQ(kMode60, mode) << lr.desiredRefreshRate << " chooses " - << to_string(mode->getFps()); + << to_string(mode->getPeakFps()) << "(" + << to_string(mode->getVsyncRate()) << ")"; } } @@ -1029,7 +1053,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_75HzContent) { lr.desiredRefreshRate = Fps::fromValue(fps); const auto mode = selector.getBestFrameRateMode(layers, {}); EXPECT_EQ(kMode90, mode) << lr.desiredRefreshRate << " chooses " - << to_string(mode->getFps()); + << to_string(mode->getPeakFps()) << "(" + << to_string(mode->getVsyncRate()) << ")"; } } @@ -1146,9 +1171,9 @@ TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicy) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -1175,9 +1200,9 @@ TEST_P(RefreshRateSelectorTest, getMinRefreshRatesByPolicy) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -1207,9 +1232,9 @@ TEST_P(RefreshRateSelectorTest, getMinRefreshRatesByPolicyOutsideTheGroup) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -1239,9 +1264,9 @@ TEST_P(RefreshRateSelectorTest, getMaxRefreshRatesByPolicyOutsideTheGroup) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -1267,9 +1292,9 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } std::tie(refreshRates, signals) = @@ -1281,9 +1306,9 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } std::vector<LayerRequirement> layers = {{.weight = 1.f}}; @@ -1301,9 +1326,9 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } std::tie(refreshRates, signals) = @@ -1326,9 +1351,9 @@ TEST_P(RefreshRateSelectorTest, powerOnImminentConsidered) { for (size_t i = 0; i < expectedRefreshRates.size(); ++i) { EXPECT_EQ(expectedRefreshRates[i], refreshRates[i].frameRateMode) << "Expected " << expectedRefreshRates[i].fps.getIntValue() << " (" - << expectedRefreshRates[i].modePtr->getFps().getIntValue() << ")" + << expectedRefreshRates[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << refreshRates[i].frameRateMode.fps.getIntValue() << " (" - << refreshRates[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << refreshRates[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -1434,7 +1459,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60 layers[1].frameRateCategory = testCase.frameRateCategory; } - EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps()) + EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps()) << "did not get expected frame rate for " << lr.name; } } @@ -1491,7 +1516,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_60_12 layers[1].frameRateCategory = testCase.frameRateCategory; } - EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getFps()) + EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers)->getPeakFps()) << "did not get expected frame rate for " << lr.name; } } @@ -1529,9 +1554,10 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitDefault) { ss << "ExplicitDefault " << desired; lr.name = ss.str(); - const auto bestFps = selector.getBestFrameRateMode(layers)->getFps(); - EXPECT_EQ(expected, bestFps) - << "expected " << expected << " for " << desired << " but got " << bestFps; + const auto bestMode = selector.getBestFrameRateMode(layers); + EXPECT_EQ(expected, bestMode->getPeakFps()) + << "expected " << expected << " for " << desired << " but got " + << bestMode->getPeakFps() << "(" << bestMode->getVsyncRate() << ")"; } } @@ -1608,7 +1634,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_ExplicitExact_WithFractiona ss << "ExplicitExact " << desired; lr.name = ss.str(); - EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getFps()); + EXPECT_EQ(lr.desiredRefreshRate, selector.getBestFrameRateMode(layers)->getPeakFps()); } } } @@ -1713,9 +1739,9 @@ TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { for (size_t i = 0; i < expectedRanking.size(); ++i) { EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) << "Expected " << expectedRanking[i].fps.getIntValue() << " (" - << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" - << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } lr1.vote = LayerVoteType::Max; @@ -1755,9 +1781,9 @@ TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { for (size_t i = 0; i < expectedRanking.size(); ++i) { EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) << "Expected " << expectedRanking[i].fps.getIntValue() << " (" - << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" - << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } lr1.vote = LayerVoteType::Heuristic; @@ -1795,9 +1821,9 @@ TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { for (size_t i = 0; i < expectedRanking.size(); ++i) { EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) << "Expected " << expectedRanking[i].fps.getIntValue() << " (" - << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" - << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } lr1.desiredRefreshRate = 120_Hz; @@ -1838,9 +1864,9 @@ TEST_P(RefreshRateSelectorTest, testDisplayModeOrdering) { for (size_t i = 0; i < expectedRanking.size(); ++i) { EXPECT_EQ(expectedRanking[i], actualRanking[i].frameRateMode) << "Expected " << expectedRanking[i].fps.getIntValue() << " (" - << expectedRanking[i].modePtr->getFps().getIntValue() << ")" + << expectedRanking[i].modePtr->getVsyncRate().getIntValue() << ")" << " Actual " << actualRanking[i].frameRateMode.fps.getIntValue() << " (" - << actualRanking[i].frameRateMode.modePtr->getFps().getIntValue() << ")"; + << actualRanking[i].frameRateMode.modePtr->getVsyncRate().getIntValue() << ")"; } } @@ -2485,7 +2511,8 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withCloseRefreshRates) { const auto testRefreshRate = [&](Fps fps, LayerVoteType vote) { layers[0].desiredRefreshRate = fps; layers[0].vote = vote; - EXPECT_EQ(fps.getIntValue(), selector.getBestFrameRateMode(layers)->getFps().getIntValue()) + EXPECT_EQ(fps.getIntValue(), + selector.getBestFrameRateMode(layers)->getPeakFps().getIntValue()) << "Failed for " << ftl::enum_string(vote); }; @@ -2524,13 +2551,13 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_conflictingVotes) { }, }; - EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getFps()); + EXPECT_EQ(53_Hz, selector.getBestFrameRateMode(layers, globalSignals)->getPeakFps()); } TEST_P(RefreshRateSelectorTest, modeComparison) { - EXPECT_LT(kMode60->getFps(), kMode90->getFps()); - EXPECT_GE(kMode60->getFps(), kMode60->getFps()); - EXPECT_GE(kMode90->getFps(), kMode90->getFps()); + EXPECT_LT(kMode60->getPeakFps(), kMode90->getPeakFps()); + EXPECT_GE(kMode60->getPeakFps(), kMode60->getPeakFps()); + EXPECT_GE(kMode90->getPeakFps(), kMode90->getPeakFps()); } TEST_P(RefreshRateSelectorTest, testKernelIdleTimerAction) { @@ -2579,27 +2606,27 @@ TEST_P(RefreshRateSelectorTest, getFrameRateDivisor) { auto selector = createSelector(kModes_30_60_72_90_120, kModeId30); const auto frameRate = 30_Hz; - Fps displayRefreshRate = selector.getActiveMode().getFps(); + Fps displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(1, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate)); selector.setActiveMode(kModeId60, 60_Hz); - displayRefreshRate = selector.getActiveMode().getFps(); + displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(2, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate)); selector.setActiveMode(kModeId72, 72_Hz); - displayRefreshRate = selector.getActiveMode().getFps(); + displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(0, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate)); selector.setActiveMode(kModeId90, 90_Hz); - displayRefreshRate = selector.getActiveMode().getFps(); + displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(3, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate)); selector.setActiveMode(kModeId120, 120_Hz); - displayRefreshRate = selector.getActiveMode().getFps(); + displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(4, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, frameRate)); selector.setActiveMode(kModeId90, 90_Hz); - displayRefreshRate = selector.getActiveMode().getFps(); + displayRefreshRate = selector.getActiveMode().getPeakFps(); EXPECT_EQ(4, RefreshRateSelector::getFrameRateDivisor(displayRefreshRate, 22.5_Hz)); EXPECT_EQ(0, RefreshRateSelector::getFrameRateDivisor(24_Hz, 25_Hz)); @@ -3029,7 +3056,7 @@ TEST_P(RefreshRateSelectorTest, renderFrameRates) { for (size_t i = 0; i < expected.size(); i++) { const auto [expectedRenderRate, expectedRefreshRate] = expected[i]; EXPECT_EQ(expectedRenderRate, primaryRefreshRates[i].fps); - EXPECT_EQ(expectedRefreshRate, primaryRefreshRates[i].modePtr->getFps()); + EXPECT_EQ(expectedRefreshRate, primaryRefreshRates[i].modePtr->getPeakFps()); } } @@ -3175,6 +3202,7 @@ TEST_P(RefreshRateSelectorTest, SupportsLowPhysicalRefreshRates) { } // TODO(b/266481656): Once this bug is fixed, we can remove this test +// And test for VRR when we remove this work around for VRR. TEST_P(RefreshRateSelectorTest, noLowerFrameRateOnMinVote) { auto selector = createSelector(kModes_60_90, kModeId60); @@ -3304,5 +3332,187 @@ TEST_P(RefreshRateSelectorTest, frameRateOverrideInBlockingZone60_90_NonDivisor) EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, selector.getBestScoredFrameRate(layers).frameRateMode); } +// VRR tests +TEST_P(RefreshRateSelectorTest, singleMinMaxRateForVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) { + return; + } + + auto selector = createSelector(kVrrMode_120, kModeId120); + EXPECT_TRUE(selector.supportsFrameRateOverride()); + + const auto minRate = selector.getMinSupportedRefreshRate(); + const auto performanceRate = selector.getMaxSupportedRefreshRate(); + const auto minRateByPolicy = selector.getMinRefreshRateByPolicy(); + const auto performanceRateByPolicy = selector.getMaxRefreshRateByPolicy(); + + EXPECT_EQ(kVrrMode120TE240, minRate); + EXPECT_EQ(kVrrMode120TE240, performanceRate); + EXPECT_EQ(kVrrMode120TE240, minRateByPolicy); + EXPECT_EQ(kVrrMode120TE240, performanceRateByPolicy); +} + +TEST_P(RefreshRateSelectorTest, renderRateChangesWithPolicyChangeForVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) { + return; + } + + auto selector = createSelector(kVrrModes_60_120, kModeId120); + + const FpsRange only120 = {120_Hz, 120_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, only120}, {only120, only120}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 120_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range120 = {0_Hz, 120_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range120}, {only120, range120}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 120_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range90 = {0_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range90}, {only120, range90}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 80_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range80 = {0_Hz, 80_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range80}, {only120, range80}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 80_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range60 = {0_Hz, 60_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range60}, {only120, range60}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 60_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range48 = {0_Hz, 48_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range48}, {only120, range48}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 48_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + const FpsRange range30 = {0_Hz, 30_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range30}, {only120, range30}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 30_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); +} + +TEST_P(RefreshRateSelectorTest, modeChangesWithPolicyChangeForVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) { + return; + } + + auto selector = createSelector(kVrrModes_60_120, kModeId120); + + const FpsRange range120 = {0_Hz, 120_Hz}; + const FpsRange range60 = {0_Hz, 60_Hz}; + + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {range120, range60}, {range120, range60}})); + EXPECT_FRAME_RATE_MODE(kVrrMode120TE240, 60_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); + + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId60, {range60, range60}, {range60, range60}})); + EXPECT_FRAME_RATE_MODE(kVrrMode60TE120, 60_Hz, + selector.getBestScoredFrameRate({}).frameRateMode); +} + +TEST_P(RefreshRateSelectorTest, getFrameRateOverridesForVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) { + return; + } + + auto selector = createSelector(kVrrMode_120, kModeId120); + // TODO(b/297600226) Run at lower than 30 Fps for dVRR + const std::vector<Fps> desiredRefreshRates = {30_Hz, 34.285_Hz, 40_Hz, 48_Hz, + 60_Hz, 80_Hz, 120_Hz}; + const std::vector<LayerVoteType> layerVotes = {LayerVoteType::ExplicitDefault, + LayerVoteType::ExplicitExactOrMultiple, + LayerVoteType::ExplicitExact}; + + std::vector<LayerRequirement> layers = {{.weight = 1.f}}; + layers[0].name = "Test layer"; + layers[0].ownerUid = 1234; + + for (auto desiredRefreshRate : desiredRefreshRates) { + layers[0].desiredRefreshRate = desiredRefreshRate; + for (auto vote : layerVotes) { + layers[0].vote = vote; + auto frameRateOverrides = selector.getFrameRateOverrides(layers, 240_Hz, {}); + EXPECT_EQ(1u, frameRateOverrides.size()); + ASSERT_EQ(1u, frameRateOverrides.count(1234)); + EXPECT_EQ(desiredRefreshRate, frameRateOverrides.at(1234)); + } + } +} + +TEST_P(RefreshRateSelectorTest, renderFrameRatesForVrr) { + if (GetParam() != Config::FrameRateOverride::Enabled || !flags::vrr_config()) { + return; + } + + auto selector = createSelector(kVrrMode_120, kModeId120); + const FpsRange only120 = {120_Hz, 120_Hz}; + const FpsRange range120 = {0_Hz, 120_Hz}; + + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {only120, range120}, {only120, range120}})); + + std::vector<Fps> expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz, + 40_Hz, 48_Hz, 60_Hz, 80_Hz, 120_Hz}; + + auto primaryRefreshRates = selector.getPrimaryFrameRates(); + ASSERT_EQ(expected.size(), primaryRefreshRates.size()); + + for (size_t i = 0; i < expected.size(); i++) { + EXPECT_EQ(expected[i], primaryRefreshRates[i].fps); + EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps()); + } + + // Render range (0,90) + const FpsRange range90 = {0_Hz, 90_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {range120, range90}, {range120, range90}})); + + expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz, 40_Hz, 48_Hz, 60_Hz, 80_Hz}; + + primaryRefreshRates = selector.getPrimaryFrameRates(); + ASSERT_EQ(expected.size(), primaryRefreshRates.size()); + for (size_t i = 0; i < expected.size(); i++) { + EXPECT_EQ(expected[i], primaryRefreshRates[i].fps); + EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps()); + } + + // Render range (0,60) + const FpsRange range60 = {0_Hz, 60_Hz}; + EXPECT_EQ(SetPolicyResult::Changed, + selector.setDisplayManagerPolicy( + {kModeId120, {range120, range60}, {range120, range60}})); + expected = {20_Hz, 21.818_Hz, 24_Hz, 26.666_Hz, 30_Hz, 34.285_Hz, 40_Hz, 48_Hz, 60_Hz}; + + primaryRefreshRates = selector.getPrimaryFrameRates(); + ASSERT_EQ(expected.size(), primaryRefreshRates.size()); + for (size_t i = 0; i < expected.size(); i++) { + EXPECT_EQ(expected[i], primaryRefreshRates[i].fps); + EXPECT_EQ(120_Hz, primaryRefreshRates[i].modePtr->getPeakFps()); + } +} } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 8458aa3ce0..908c9abc03 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -997,7 +997,7 @@ public: const auto activeMode = modes.get(activeModeId); LOG_ALWAYS_FATAL_IF(!activeMode); - const auto fps = activeMode->get()->getFps(); + const auto fps = activeMode->get()->getPeakFps(); state.physical = {.id = physicalId, .hwcDisplayId = *mHwcDisplayId, diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h index 3b36361657..cb05c00699 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplayMode.h @@ -20,17 +20,23 @@ namespace android::mock { -inline DisplayModePtr createDisplayMode( - DisplayModeId modeId, Fps refreshRate, int32_t group = 0, +inline DisplayMode::Builder createDisplayModeBuilder( + DisplayModeId modeId, Fps displayRefreshRate, int32_t group = 0, ui::Size resolution = ui::Size(1920, 1080), PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) { return DisplayMode::Builder(hal::HWConfigId(modeId.value())) .setId(modeId) .setPhysicalDisplayId(displayId) - .setVsyncPeriod(refreshRate.getPeriodNsecs()) + .setVsyncPeriod(displayRefreshRate.getPeriodNsecs()) .setGroup(group) - .setResolution(resolution) - .build(); + .setResolution(resolution); +} + +inline DisplayModePtr createDisplayMode( + DisplayModeId modeId, Fps refreshRate, int32_t group = 0, + ui::Size resolution = ui::Size(1920, 1080), + PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) { + return createDisplayModeBuilder(modeId, refreshRate, group, resolution, displayId).build(); } inline DisplayModePtr createDisplayMode(PhysicalDisplayId displayId, DisplayModeId modeId, @@ -38,11 +44,19 @@ inline DisplayModePtr createDisplayMode(PhysicalDisplayId displayId, DisplayMode return createDisplayMode(modeId, refreshRate, {}, {}, displayId); } +inline DisplayModePtr createVrrDisplayMode( + DisplayModeId modeId, Fps displayRefreshRate, hal::VrrConfig vrrConfig, int32_t group = 0, + ui::Size resolution = ui::Size(1920, 1080), + PhysicalDisplayId displayId = PhysicalDisplayId::fromPort(0)) { + return createDisplayModeBuilder(modeId, displayRefreshRate, group, resolution, displayId) + .setVrrConfig(std::move(vrrConfig)) + .build(); +} inline DisplayModePtr cloneForDisplay(PhysicalDisplayId displayId, const DisplayModePtr& modePtr) { return DisplayMode::Builder(modePtr->getHwcId()) .setId(modePtr->getId()) .setPhysicalDisplayId(displayId) - .setVsyncPeriod(modePtr->getVsyncPeriod()) + .setVsyncPeriod(modePtr->getVsyncRate().getPeriodNsecs()) .setGroup(modePtr->getGroup()) .setResolution(modePtr->getResolution()) .build(); diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h index 4cfdd58c70..bfcdd9bbd5 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h @@ -19,7 +19,7 @@ #include <scheduler/FrameRateMode.h> // Use a C style macro to keep the line numbers printed in gtest -#define EXPECT_FRAME_RATE_MODE(_modePtr, _fps, _mode) \ - EXPECT_EQ((scheduler::FrameRateMode{(_fps), (_modePtr)}), (_mode)) \ - << "Expected " << (_fps) << " (" << (_modePtr)->getFps() << ") but was " \ - << (_mode).fps << " (" << (_mode).modePtr->getFps() << ")" +#define EXPECT_FRAME_RATE_MODE(_modePtr, _fps, _mode) \ + EXPECT_EQ((scheduler::FrameRateMode{(_fps), (_modePtr)}), (_mode)) \ + << "Expected " << (_fps) << " (" << (_modePtr)->getVsyncRate() << ") but was " \ + << (_mode).fps << " (" << (_mode).modePtr->getVsyncRate() << ")" |