diff options
Diffstat (limited to 'services/surfaceflinger/Scheduler/PhaseOffsets.cpp')
-rw-r--r-- | services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp deleted file mode 100644 index fe2e406775..0000000000 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PhaseOffsets.h" - -#include <cutils/properties.h> - -#include <optional> - -#include "SurfaceFlingerProperties.h" - -namespace { - -std::optional<nsecs_t> getProperty(const char* name) { - char value[PROPERTY_VALUE_MAX]; - property_get(name, value, "-1"); - if (const int i = atoi(value); i != -1) return i; - return std::nullopt; -} - -bool fpsEqualsWithMargin(float fpsA, float fpsB) { - static constexpr float MARGIN = 0.01f; - return std::abs(fpsA - fpsB) <= MARGIN; -} - -std::vector<float> getRefreshRatesFromConfigs( - const android::scheduler::RefreshRateConfigs& refreshRateConfigs) { - const auto& allRefreshRates = refreshRateConfigs.getAllRefreshRates(); - std::vector<float> refreshRates; - refreshRates.reserve(allRefreshRates.size()); - - for (const auto& [ignored, refreshRate] : allRefreshRates) { - refreshRates.emplace_back(refreshRate->getFps()); - } - - return refreshRates; -} - -} // namespace - -namespace android::scheduler { - -PhaseConfiguration::~PhaseConfiguration() = default; - -namespace impl { - -PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs) - : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs), - refreshRateConfigs.getCurrentRefreshRate().getFps(), - sysprop::vsync_event_phase_offset_ns(1000000), - sysprop::vsync_sf_event_phase_offset_ns(1000000), - getProperty("debug.sf.early_phase_offset_ns"), - getProperty("debug.sf.early_gl_phase_offset_ns"), - getProperty("debug.sf.early_app_phase_offset_ns"), - getProperty("debug.sf.early_gl_app_phase_offset_ns"), - // Below defines the threshold when an offset is considered to be negative, - // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset - // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For - // offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW - // vsync. - getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns") - .value_or(std::numeric_limits<nsecs_t>::max())) {} - -PhaseOffsets::PhaseOffsets(const std::vector<float>& refreshRates, float currentFps, - nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, - std::optional<nsecs_t> earlySfOffsetNs, - std::optional<nsecs_t> earlyGlSfOffsetNs, - std::optional<nsecs_t> earlyAppOffsetNs, - std::optional<nsecs_t> earlyGlAppOffsetNs, nsecs_t thresholdForNextVsync) - : mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs), - mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs), - mEarlySfOffsetNs(earlySfOffsetNs), - mEarlyGlSfOffsetNs(earlyGlSfOffsetNs), - mEarlyAppOffsetNs(earlyAppOffsetNs), - mEarlyGlAppOffsetNs(earlyGlAppOffsetNs), - mThresholdForNextVsync(thresholdForNextVsync), - mOffsets(initializeOffsets(refreshRates)), - mRefreshRateFps(currentFps) {} - -void PhaseOffsets::dump(std::string& result) const { - const auto [early, earlyGl, late] = getCurrentOffsets(); - using base::StringAppendF; - StringAppendF(&result, - " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 " ns\n" - " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 " ns\n" - " GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n" - "next VSYNC threshold: %9" PRId64 " ns\n", - late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf, - mThresholdForNextVsync); -} - -std::unordered_map<float, PhaseOffsets::Offsets> PhaseOffsets::initializeOffsets( - const std::vector<float>& refreshRates) const { - std::unordered_map<float, Offsets> offsets; - - for (const auto& refreshRate : refreshRates) { - offsets.emplace(refreshRate, - getPhaseOffsets(refreshRate, static_cast<nsecs_t>(1e9f / refreshRate))); - } - return offsets; -} - -PhaseOffsets::Offsets PhaseOffsets::getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const { - if (fps > 65.0f) { - return getHighFpsOffsets(vsyncPeriod); - } else { - return getDefaultOffsets(vsyncPeriod); - } -} - -PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const { - return { - { - mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync - ? mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - : mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration, - - mEarlyAppOffsetNs.value_or(mVSyncPhaseOffsetNs), - }, - { - mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync - ? mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - : mEarlyGlSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration, - - mEarlyGlAppOffsetNs.value_or(mVSyncPhaseOffsetNs), - }, - { - mSfVSyncPhaseOffsetNs < mThresholdForNextVsync - ? mSfVSyncPhaseOffsetNs - : mSfVSyncPhaseOffsetNs - vsyncDuration, - - mVSyncPhaseOffsetNs, - }, - }; -} - -PhaseOffsets::Offsets PhaseOffsets::getHighFpsOffsets(nsecs_t vsyncDuration) const { - const auto highFpsLateAppOffsetNs = - getProperty("debug.sf.high_fps_late_app_phase_offset_ns").value_or(2000000); - const auto highFpsLateSfOffsetNs = - getProperty("debug.sf.high_fps_late_sf_phase_offset_ns").value_or(1000000); - - const auto highFpsEarlySfOffsetNs = getProperty("debug.sf.high_fps_early_phase_offset_ns"); - const auto highFpsEarlyGlSfOffsetNs = getProperty("debug.sf.high_fps_early_gl_phase_offset_ns"); - const auto highFpsEarlyAppOffsetNs = getProperty("debug.sf.high_fps_early_app_phase_offset_ns"); - const auto highFpsEarlyGlAppOffsetNs = - getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"); - - return { - { - highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs) < mThresholdForNextVsync - ? highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs) - : highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs) - - vsyncDuration, - - highFpsEarlyAppOffsetNs.value_or(highFpsLateAppOffsetNs), - }, - { - highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs) < - mThresholdForNextVsync - ? highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs) - : highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs) - - vsyncDuration, - - highFpsEarlyGlAppOffsetNs.value_or(highFpsLateAppOffsetNs), - }, - { - highFpsLateSfOffsetNs < mThresholdForNextVsync - ? highFpsLateSfOffsetNs - : highFpsLateSfOffsetNs - vsyncDuration, - - highFpsLateAppOffsetNs, - }, - }; -} - -PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const { - const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(), - [&fps](const std::pair<float, Offsets>& candidateFps) { - return fpsEqualsWithMargin(fps, candidateFps.first); - }); - - if (iter != mOffsets.end()) { - return iter->second; - } - - // Unknown refresh rate. This might happen if we get a hotplug event for an external display. - // In this case just construct the offset. - ALOGW("Can't find offset for %.2f fps", fps); - return getPhaseOffsets(fps, static_cast<nsecs_t>(1e9f / fps)); -} - -static void validateSysprops() { - const auto validatePropertyBool = [](const char* prop) { - LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop); - }; - - validatePropertyBool("debug.sf.use_phase_offsets_as_durations"); - - LOG_ALWAYS_FATAL_IF(sysprop::vsync_event_phase_offset_ns(-1) != -1, - "ro.surface_flinger.vsync_event_phase_offset_ns is set but expecting " - "duration"); - - LOG_ALWAYS_FATAL_IF(sysprop::vsync_sf_event_phase_offset_ns(-1) != -1, - "ro.surface_flinger.vsync_sf_event_phase_offset_ns is set but expecting " - "duration"); - - const auto validateProperty = [](const char* prop) { - LOG_ALWAYS_FATAL_IF(getProperty(prop).has_value(), - "%s is set to %" PRId64 " but expecting duration", prop, - getProperty(prop).value_or(-1)); - }; - - validateProperty("debug.sf.early_phase_offset_ns"); - validateProperty("debug.sf.early_gl_phase_offset_ns"); - validateProperty("debug.sf.early_app_phase_offset_ns"); - validateProperty("debug.sf.early_gl_app_phase_offset_ns"); - validateProperty("debug.sf.high_fps_late_app_phase_offset_ns"); - validateProperty("debug.sf.high_fps_late_sf_phase_offset_ns"); - validateProperty("debug.sf.high_fps_early_phase_offset_ns"); - validateProperty("debug.sf.high_fps_early_gl_phase_offset_ns"); - validateProperty("debug.sf.high_fps_early_app_phase_offset_ns"); - validateProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"); -} - -static nsecs_t sfDurationToOffset(nsecs_t sfDuration, nsecs_t vsyncDuration) { - return sfDuration == -1 ? 1'000'000 : vsyncDuration - sfDuration % vsyncDuration; -} - -static nsecs_t appDurationToOffset(nsecs_t appDuration, nsecs_t sfDuration, nsecs_t vsyncDuration) { - return sfDuration == -1 ? 1'000'000 - : vsyncDuration - (appDuration + sfDuration) % vsyncDuration; -} - -PhaseDurations::Offsets PhaseDurations::constructOffsets(nsecs_t vsyncDuration) const { - return Offsets{ - { - mSfEarlyDuration < vsyncDuration - ? sfDurationToOffset(mSfEarlyDuration, vsyncDuration) - : sfDurationToOffset(mSfEarlyDuration, vsyncDuration) - vsyncDuration, - - appDurationToOffset(mAppEarlyDuration, mSfEarlyDuration, vsyncDuration), - }, - { - mSfEarlyGlDuration < vsyncDuration - ? sfDurationToOffset(mSfEarlyGlDuration, vsyncDuration) - : sfDurationToOffset(mSfEarlyGlDuration, vsyncDuration) - vsyncDuration, - - appDurationToOffset(mAppEarlyGlDuration, mSfEarlyGlDuration, vsyncDuration), - }, - { - mSfDuration < vsyncDuration - ? sfDurationToOffset(mSfDuration, vsyncDuration) - : sfDurationToOffset(mSfDuration, vsyncDuration) - vsyncDuration, - - appDurationToOffset(mAppDuration, mSfDuration, vsyncDuration), - }, - }; -} - -std::unordered_map<float, PhaseDurations::Offsets> PhaseDurations::initializeOffsets( - const std::vector<float>& refreshRates) const { - std::unordered_map<float, Offsets> offsets; - - for (const auto fps : refreshRates) { - offsets.emplace(fps, constructOffsets(static_cast<nsecs_t>(1e9f / fps))); - } - return offsets; -} - -PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs) - : PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs), - refreshRateConfigs.getCurrentRefreshRate().getFps(), - getProperty("debug.sf.late.sf.duration").value_or(-1), - getProperty("debug.sf.late.app.duration").value_or(-1), - getProperty("debug.sf.early.sf.duration").value_or(mSfDuration), - getProperty("debug.sf.early.app.duration").value_or(mAppDuration), - getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration), - getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration)) { - validateSysprops(); -} - -PhaseDurations::PhaseDurations(const std::vector<float>& refreshRates, float currentFps, - nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, - nsecs_t appEarlyDuration, nsecs_t sfEarlyGlDuration, - nsecs_t appEarlyGlDuration) - : mSfDuration(sfDuration), - mAppDuration(appDuration), - mSfEarlyDuration(sfEarlyDuration), - mAppEarlyDuration(appEarlyDuration), - mSfEarlyGlDuration(sfEarlyGlDuration), - mAppEarlyGlDuration(appEarlyGlDuration), - mOffsets(initializeOffsets(refreshRates)), - mRefreshRateFps(currentFps) {} - -PhaseOffsets::Offsets PhaseDurations::getOffsetsForRefreshRate(float fps) const { - const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(), [=](const auto& candidateFps) { - return fpsEqualsWithMargin(fps, candidateFps.first); - }); - - if (iter != mOffsets.end()) { - return iter->second; - } - - // Unknown refresh rate. This might happen if we get a hotplug event for an external display. - // In this case just construct the offset. - ALOGW("Can't find offset for %.2f fps", fps); - return constructOffsets(static_cast<nsecs_t>(1e9f / fps)); -} - -void PhaseDurations::dump(std::string& result) const { - const auto [early, earlyGl, late] = getCurrentOffsets(); - using base::StringAppendF; - StringAppendF(&result, - " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 - " ns\n" - " app duration: %9" PRId64 " ns\t SF duration: %9" PRId64 - " ns\n" - " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 - " ns\n" - " early app duration: %9" PRId64 " ns\t early SF duration: %9" PRId64 - " ns\n" - " GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 - " ns\n" - " GL early app duration: %9" PRId64 " ns\tGL early SF duration: %9" PRId64 - " ns\n", - late.app, - - late.sf, - - mAppDuration, mSfDuration, - - early.app, early.sf, - - mAppEarlyDuration, mSfEarlyDuration, - - earlyGl.app, - - earlyGl.sf, - - mAppEarlyGlDuration, mSfEarlyGlDuration); -} - -} // namespace impl -} // namespace android::scheduler |