1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2019 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include "VsyncConfiguration.h"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <chrono>
20*38e8c45fSAndroid Build Coastguard Worker #include <cinttypes>
21*38e8c45fSAndroid Build Coastguard Worker #include <optional>
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include <cutils/properties.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker #include "SurfaceFlingerProperties.h"
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker namespace {
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker using namespace std::chrono_literals;
31*38e8c45fSAndroid Build Coastguard Worker
getProperty(const char * name)32*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> getProperty(const char* name) {
33*38e8c45fSAndroid Build Coastguard Worker char value[PROPERTY_VALUE_MAX];
34*38e8c45fSAndroid Build Coastguard Worker property_get(name, value, "-1");
35*38e8c45fSAndroid Build Coastguard Worker if (const int i = atoi(value); i != -1) return i;
36*38e8c45fSAndroid Build Coastguard Worker return std::nullopt;
37*38e8c45fSAndroid Build Coastguard Worker }
38*38e8c45fSAndroid Build Coastguard Worker
39*38e8c45fSAndroid Build Coastguard Worker } // namespace
40*38e8c45fSAndroid Build Coastguard Worker
41*38e8c45fSAndroid Build Coastguard Worker namespace android::scheduler::impl {
42*38e8c45fSAndroid Build Coastguard Worker
VsyncConfiguration(Fps currentFps)43*38e8c45fSAndroid Build Coastguard Worker VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {}
44*38e8c45fSAndroid Build Coastguard Worker
getConfigsForRefreshRate(Fps fps) const45*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(Fps fps) const {
46*38e8c45fSAndroid Build Coastguard Worker std::lock_guard lock(mLock);
47*38e8c45fSAndroid Build Coastguard Worker return getConfigsForRefreshRateLocked(fps);
48*38e8c45fSAndroid Build Coastguard Worker }
49*38e8c45fSAndroid Build Coastguard Worker
getConfigsForRefreshRateLocked(Fps fps) const50*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRateLocked(Fps fps) const {
51*38e8c45fSAndroid Build Coastguard Worker if (const auto offsets = mOffsetsCache.get(fps)) {
52*38e8c45fSAndroid Build Coastguard Worker return offsets->get();
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker
55*38e8c45fSAndroid Build Coastguard Worker const auto [it, _] = mOffsetsCache.try_emplace(fps, constructOffsets(fps.getPeriodNsecs()));
56*38e8c45fSAndroid Build Coastguard Worker return it->second;
57*38e8c45fSAndroid Build Coastguard Worker }
58*38e8c45fSAndroid Build Coastguard Worker
dump(std::string & result) const59*38e8c45fSAndroid Build Coastguard Worker void VsyncConfiguration::dump(std::string& result) const {
60*38e8c45fSAndroid Build Coastguard Worker const auto [early, earlyGpu, late, hwcMinWorkDuration] = getCurrentConfigs();
61*38e8c45fSAndroid Build Coastguard Worker using base::StringAppendF;
62*38e8c45fSAndroid Build Coastguard Worker StringAppendF(&result,
63*38e8c45fSAndroid Build Coastguard Worker " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64
64*38e8c45fSAndroid Build Coastguard Worker " ns\n"
65*38e8c45fSAndroid Build Coastguard Worker " app duration: %9lld ns\t SF duration: %9lld ns\n"
66*38e8c45fSAndroid Build Coastguard Worker " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64
67*38e8c45fSAndroid Build Coastguard Worker " ns\n"
68*38e8c45fSAndroid Build Coastguard Worker " early app duration: %9lld ns\t early SF duration: %9lld ns\n"
69*38e8c45fSAndroid Build Coastguard Worker " GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64
70*38e8c45fSAndroid Build Coastguard Worker " ns\n"
71*38e8c45fSAndroid Build Coastguard Worker " GL early app duration: %9lld ns\tGL early SF duration: %9lld ns\n"
72*38e8c45fSAndroid Build Coastguard Worker " HWC min duration: %9lld ns\n",
73*38e8c45fSAndroid Build Coastguard Worker late.appOffset, late.sfOffset,
74*38e8c45fSAndroid Build Coastguard Worker
75*38e8c45fSAndroid Build Coastguard Worker late.appWorkDuration.count(), late.sfWorkDuration.count(),
76*38e8c45fSAndroid Build Coastguard Worker
77*38e8c45fSAndroid Build Coastguard Worker early.appOffset, early.sfOffset,
78*38e8c45fSAndroid Build Coastguard Worker
79*38e8c45fSAndroid Build Coastguard Worker early.appWorkDuration.count(), early.sfWorkDuration.count(),
80*38e8c45fSAndroid Build Coastguard Worker
81*38e8c45fSAndroid Build Coastguard Worker earlyGpu.appOffset, earlyGpu.sfOffset,
82*38e8c45fSAndroid Build Coastguard Worker
83*38e8c45fSAndroid Build Coastguard Worker earlyGpu.appWorkDuration.count(), earlyGpu.sfWorkDuration.count(),
84*38e8c45fSAndroid Build Coastguard Worker
85*38e8c45fSAndroid Build Coastguard Worker hwcMinWorkDuration.count());
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
PhaseOffsets(Fps currentRefreshRate)88*38e8c45fSAndroid Build Coastguard Worker PhaseOffsets::PhaseOffsets(Fps currentRefreshRate)
89*38e8c45fSAndroid Build Coastguard Worker : PhaseOffsets(currentRefreshRate, sysprop::vsync_event_phase_offset_ns(1000000),
90*38e8c45fSAndroid Build Coastguard Worker sysprop::vsync_sf_event_phase_offset_ns(1000000),
91*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early_phase_offset_ns"),
92*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early_gl_phase_offset_ns"),
93*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early_app_phase_offset_ns"),
94*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early_gl_app_phase_offset_ns"),
95*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_late_app_phase_offset_ns").value_or(2000000),
96*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_late_sf_phase_offset_ns").value_or(1000000),
97*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_early_phase_offset_ns"),
98*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_early_gl_phase_offset_ns"),
99*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_early_app_phase_offset_ns"),
100*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"),
101*38e8c45fSAndroid Build Coastguard Worker // Below defines the threshold when an offset is considered to be negative,
102*38e8c45fSAndroid Build Coastguard Worker // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset
103*38e8c45fSAndroid Build Coastguard Worker // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For
104*38e8c45fSAndroid Build Coastguard Worker // offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW
105*38e8c45fSAndroid Build Coastguard Worker // vsync.
106*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns")
107*38e8c45fSAndroid Build Coastguard Worker .value_or(std::numeric_limits<nsecs_t>::max()),
108*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.hwc.min.duration").value_or(0)) {}
109*38e8c45fSAndroid Build Coastguard Worker
PhaseOffsets(Fps currentFps,nsecs_t vsyncPhaseOffsetNs,nsecs_t sfVSyncPhaseOffsetNs,std::optional<nsecs_t> earlySfOffsetNs,std::optional<nsecs_t> earlyGpuSfOffsetNs,std::optional<nsecs_t> earlyAppOffsetNs,std::optional<nsecs_t> earlyGpuAppOffsetNs,nsecs_t highFpsVsyncPhaseOffsetNs,nsecs_t highFpsSfVSyncPhaseOffsetNs,std::optional<nsecs_t> highFpsEarlySfOffsetNs,std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,std::optional<nsecs_t> highFpsEarlyAppOffsetNs,std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,nsecs_t thresholdForNextVsync,nsecs_t hwcMinWorkDuration)110*38e8c45fSAndroid Build Coastguard Worker PhaseOffsets::PhaseOffsets(Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
111*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> earlySfOffsetNs,
112*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> earlyGpuSfOffsetNs,
113*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> earlyAppOffsetNs,
114*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> earlyGpuAppOffsetNs,
115*38e8c45fSAndroid Build Coastguard Worker nsecs_t highFpsVsyncPhaseOffsetNs, nsecs_t highFpsSfVSyncPhaseOffsetNs,
116*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> highFpsEarlySfOffsetNs,
117*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
118*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
119*38e8c45fSAndroid Build Coastguard Worker std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs,
120*38e8c45fSAndroid Build Coastguard Worker nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration)
121*38e8c45fSAndroid Build Coastguard Worker : VsyncConfiguration(currentFps),
122*38e8c45fSAndroid Build Coastguard Worker mVSyncPhaseOffsetNs(vsyncPhaseOffsetNs),
123*38e8c45fSAndroid Build Coastguard Worker mSfVSyncPhaseOffsetNs(sfVSyncPhaseOffsetNs),
124*38e8c45fSAndroid Build Coastguard Worker mEarlySfOffsetNs(earlySfOffsetNs),
125*38e8c45fSAndroid Build Coastguard Worker mEarlyGpuSfOffsetNs(earlyGpuSfOffsetNs),
126*38e8c45fSAndroid Build Coastguard Worker mEarlyAppOffsetNs(earlyAppOffsetNs),
127*38e8c45fSAndroid Build Coastguard Worker mEarlyGpuAppOffsetNs(earlyGpuAppOffsetNs),
128*38e8c45fSAndroid Build Coastguard Worker mHighFpsVSyncPhaseOffsetNs(highFpsVsyncPhaseOffsetNs),
129*38e8c45fSAndroid Build Coastguard Worker mHighFpsSfVSyncPhaseOffsetNs(highFpsSfVSyncPhaseOffsetNs),
130*38e8c45fSAndroid Build Coastguard Worker mHighFpsEarlySfOffsetNs(highFpsEarlySfOffsetNs),
131*38e8c45fSAndroid Build Coastguard Worker mHighFpsEarlyGpuSfOffsetNs(highFpsEarlyGpuSfOffsetNs),
132*38e8c45fSAndroid Build Coastguard Worker mHighFpsEarlyAppOffsetNs(highFpsEarlyAppOffsetNs),
133*38e8c45fSAndroid Build Coastguard Worker mHighFpsEarlyGpuAppOffsetNs(highFpsEarlyGpuAppOffsetNs),
134*38e8c45fSAndroid Build Coastguard Worker mThresholdForNextVsync(thresholdForNextVsync),
135*38e8c45fSAndroid Build Coastguard Worker mHwcMinWorkDuration(hwcMinWorkDuration) {}
136*38e8c45fSAndroid Build Coastguard Worker
constructOffsets(nsecs_t vsyncDuration) const137*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::constructOffsets(nsecs_t vsyncDuration) const {
138*38e8c45fSAndroid Build Coastguard Worker if (vsyncDuration < std::chrono::nanoseconds(15ms).count()) {
139*38e8c45fSAndroid Build Coastguard Worker return getHighFpsOffsets(vsyncDuration);
140*38e8c45fSAndroid Build Coastguard Worker } else {
141*38e8c45fSAndroid Build Coastguard Worker return getDefaultOffsets(vsyncDuration);
142*38e8c45fSAndroid Build Coastguard Worker }
143*38e8c45fSAndroid Build Coastguard Worker }
144*38e8c45fSAndroid Build Coastguard Worker
145*38e8c45fSAndroid Build Coastguard Worker namespace {
sfOffsetToDuration(nsecs_t sfOffset,nsecs_t vsyncDuration)146*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds sfOffsetToDuration(nsecs_t sfOffset, nsecs_t vsyncDuration) {
147*38e8c45fSAndroid Build Coastguard Worker return std::chrono::nanoseconds(vsyncDuration - sfOffset);
148*38e8c45fSAndroid Build Coastguard Worker }
149*38e8c45fSAndroid Build Coastguard Worker
appOffsetToDuration(nsecs_t appOffset,nsecs_t sfOffset,nsecs_t vsyncDuration)150*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds appOffsetToDuration(nsecs_t appOffset, nsecs_t sfOffset,
151*38e8c45fSAndroid Build Coastguard Worker nsecs_t vsyncDuration) {
152*38e8c45fSAndroid Build Coastguard Worker auto duration = vsyncDuration + (sfOffset - appOffset);
153*38e8c45fSAndroid Build Coastguard Worker if (duration < vsyncDuration) {
154*38e8c45fSAndroid Build Coastguard Worker duration += vsyncDuration;
155*38e8c45fSAndroid Build Coastguard Worker }
156*38e8c45fSAndroid Build Coastguard Worker
157*38e8c45fSAndroid Build Coastguard Worker return std::chrono::nanoseconds(duration);
158*38e8c45fSAndroid Build Coastguard Worker }
159*38e8c45fSAndroid Build Coastguard Worker } // namespace
160*38e8c45fSAndroid Build Coastguard Worker
getDefaultOffsets(nsecs_t vsyncDuration) const161*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::getDefaultOffsets(nsecs_t vsyncDuration) const {
162*38e8c45fSAndroid Build Coastguard Worker const auto earlySfOffset =
163*38e8c45fSAndroid Build Coastguard Worker mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
164*38e8c45fSAndroid Build Coastguard Worker
165*38e8c45fSAndroid Build Coastguard Worker ? mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
166*38e8c45fSAndroid Build Coastguard Worker : mEarlySfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration;
167*38e8c45fSAndroid Build Coastguard Worker const auto earlyAppOffset = mEarlyAppOffsetNs.value_or(mVSyncPhaseOffsetNs);
168*38e8c45fSAndroid Build Coastguard Worker const auto earlyGpuSfOffset =
169*38e8c45fSAndroid Build Coastguard Worker mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
170*38e8c45fSAndroid Build Coastguard Worker
171*38e8c45fSAndroid Build Coastguard Worker ? mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs)
172*38e8c45fSAndroid Build Coastguard Worker : mEarlyGpuSfOffsetNs.value_or(mSfVSyncPhaseOffsetNs) - vsyncDuration;
173*38e8c45fSAndroid Build Coastguard Worker const auto earlyGpuAppOffset = mEarlyGpuAppOffsetNs.value_or(mVSyncPhaseOffsetNs);
174*38e8c45fSAndroid Build Coastguard Worker const auto lateSfOffset = mSfVSyncPhaseOffsetNs < mThresholdForNextVsync
175*38e8c45fSAndroid Build Coastguard Worker ? mSfVSyncPhaseOffsetNs
176*38e8c45fSAndroid Build Coastguard Worker : mSfVSyncPhaseOffsetNs - vsyncDuration;
177*38e8c45fSAndroid Build Coastguard Worker const auto lateAppOffset = mVSyncPhaseOffsetNs;
178*38e8c45fSAndroid Build Coastguard Worker
179*38e8c45fSAndroid Build Coastguard Worker return {
180*38e8c45fSAndroid Build Coastguard Worker .early = {.sfOffset = earlySfOffset,
181*38e8c45fSAndroid Build Coastguard Worker .appOffset = earlyAppOffset,
182*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(earlySfOffset, vsyncDuration),
183*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration =
184*38e8c45fSAndroid Build Coastguard Worker appOffsetToDuration(earlyAppOffset, earlySfOffset, vsyncDuration)},
185*38e8c45fSAndroid Build Coastguard Worker .earlyGpu = {.sfOffset = earlyGpuSfOffset,
186*38e8c45fSAndroid Build Coastguard Worker .appOffset = earlyGpuAppOffset,
187*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(earlyGpuSfOffset, vsyncDuration),
188*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appOffsetToDuration(earlyGpuAppOffset, earlyGpuSfOffset,
189*38e8c45fSAndroid Build Coastguard Worker vsyncDuration)},
190*38e8c45fSAndroid Build Coastguard Worker .late = {.sfOffset = lateSfOffset,
191*38e8c45fSAndroid Build Coastguard Worker .appOffset = lateAppOffset,
192*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
193*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration =
194*38e8c45fSAndroid Build Coastguard Worker appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration)},
195*38e8c45fSAndroid Build Coastguard Worker .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
196*38e8c45fSAndroid Build Coastguard Worker };
197*38e8c45fSAndroid Build Coastguard Worker }
198*38e8c45fSAndroid Build Coastguard Worker
getHighFpsOffsets(nsecs_t vsyncDuration) const199*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet PhaseOffsets::getHighFpsOffsets(nsecs_t vsyncDuration) const {
200*38e8c45fSAndroid Build Coastguard Worker const auto earlySfOffset =
201*38e8c45fSAndroid Build Coastguard Worker mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
202*38e8c45fSAndroid Build Coastguard Worker ? mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs)
203*38e8c45fSAndroid Build Coastguard Worker : mHighFpsEarlySfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) - vsyncDuration;
204*38e8c45fSAndroid Build Coastguard Worker const auto earlyAppOffset = mHighFpsEarlyAppOffsetNs.value_or(mHighFpsVSyncPhaseOffsetNs);
205*38e8c45fSAndroid Build Coastguard Worker const auto earlyGpuSfOffset = mHighFpsEarlyGpuSfOffsetNs.value_or(
206*38e8c45fSAndroid Build Coastguard Worker mHighFpsSfVSyncPhaseOffsetNs) < mThresholdForNextVsync
207*38e8c45fSAndroid Build Coastguard Worker
208*38e8c45fSAndroid Build Coastguard Worker ? mHighFpsEarlyGpuSfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs)
209*38e8c45fSAndroid Build Coastguard Worker : mHighFpsEarlyGpuSfOffsetNs.value_or(mHighFpsSfVSyncPhaseOffsetNs) - vsyncDuration;
210*38e8c45fSAndroid Build Coastguard Worker const auto earlyGpuAppOffset = mHighFpsEarlyGpuAppOffsetNs.value_or(mHighFpsVSyncPhaseOffsetNs);
211*38e8c45fSAndroid Build Coastguard Worker const auto lateSfOffset = mHighFpsSfVSyncPhaseOffsetNs < mThresholdForNextVsync
212*38e8c45fSAndroid Build Coastguard Worker ? mHighFpsSfVSyncPhaseOffsetNs
213*38e8c45fSAndroid Build Coastguard Worker : mHighFpsSfVSyncPhaseOffsetNs - vsyncDuration;
214*38e8c45fSAndroid Build Coastguard Worker const auto lateAppOffset = mHighFpsVSyncPhaseOffsetNs;
215*38e8c45fSAndroid Build Coastguard Worker
216*38e8c45fSAndroid Build Coastguard Worker return {
217*38e8c45fSAndroid Build Coastguard Worker .early =
218*38e8c45fSAndroid Build Coastguard Worker {
219*38e8c45fSAndroid Build Coastguard Worker .sfOffset = earlySfOffset,
220*38e8c45fSAndroid Build Coastguard Worker .appOffset = earlyAppOffset,
221*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(earlySfOffset, vsyncDuration),
222*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appOffsetToDuration(earlyAppOffset, earlySfOffset,
223*38e8c45fSAndroid Build Coastguard Worker vsyncDuration),
224*38e8c45fSAndroid Build Coastguard Worker },
225*38e8c45fSAndroid Build Coastguard Worker .earlyGpu =
226*38e8c45fSAndroid Build Coastguard Worker {
227*38e8c45fSAndroid Build Coastguard Worker .sfOffset = earlyGpuSfOffset,
228*38e8c45fSAndroid Build Coastguard Worker .appOffset = earlyGpuAppOffset,
229*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(earlyGpuSfOffset, vsyncDuration),
230*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appOffsetToDuration(earlyGpuAppOffset,
231*38e8c45fSAndroid Build Coastguard Worker earlyGpuSfOffset, vsyncDuration),
232*38e8c45fSAndroid Build Coastguard Worker },
233*38e8c45fSAndroid Build Coastguard Worker .late =
234*38e8c45fSAndroid Build Coastguard Worker {
235*38e8c45fSAndroid Build Coastguard Worker .sfOffset = lateSfOffset,
236*38e8c45fSAndroid Build Coastguard Worker .appOffset = lateAppOffset,
237*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfOffsetToDuration(lateSfOffset, vsyncDuration),
238*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration =
239*38e8c45fSAndroid Build Coastguard Worker appOffsetToDuration(lateAppOffset, lateSfOffset, vsyncDuration),
240*38e8c45fSAndroid Build Coastguard Worker },
241*38e8c45fSAndroid Build Coastguard Worker .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
242*38e8c45fSAndroid Build Coastguard Worker };
243*38e8c45fSAndroid Build Coastguard Worker }
244*38e8c45fSAndroid Build Coastguard Worker
validateSysprops()245*38e8c45fSAndroid Build Coastguard Worker static void validateSysprops() {
246*38e8c45fSAndroid Build Coastguard Worker const auto validatePropertyBool = [](const char* prop) {
247*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop);
248*38e8c45fSAndroid Build Coastguard Worker };
249*38e8c45fSAndroid Build Coastguard Worker
250*38e8c45fSAndroid Build Coastguard Worker validatePropertyBool("debug.sf.use_phase_offsets_as_durations");
251*38e8c45fSAndroid Build Coastguard Worker
252*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(sysprop::vsync_event_phase_offset_ns(-1) != -1,
253*38e8c45fSAndroid Build Coastguard Worker "ro.surface_flinger.vsync_event_phase_offset_ns is set but expecting "
254*38e8c45fSAndroid Build Coastguard Worker "duration");
255*38e8c45fSAndroid Build Coastguard Worker
256*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(sysprop::vsync_sf_event_phase_offset_ns(-1) != -1,
257*38e8c45fSAndroid Build Coastguard Worker "ro.surface_flinger.vsync_sf_event_phase_offset_ns is set but expecting "
258*38e8c45fSAndroid Build Coastguard Worker "duration");
259*38e8c45fSAndroid Build Coastguard Worker
260*38e8c45fSAndroid Build Coastguard Worker const auto validateProperty = [](const char* prop) {
261*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(getProperty(prop).has_value(),
262*38e8c45fSAndroid Build Coastguard Worker "%s is set to %" PRId64 " but expecting duration", prop,
263*38e8c45fSAndroid Build Coastguard Worker getProperty(prop).value_or(-1));
264*38e8c45fSAndroid Build Coastguard Worker };
265*38e8c45fSAndroid Build Coastguard Worker
266*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.early_phase_offset_ns");
267*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.early_gl_phase_offset_ns");
268*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.early_app_phase_offset_ns");
269*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.early_gl_app_phase_offset_ns");
270*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_late_app_phase_offset_ns");
271*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_late_sf_phase_offset_ns");
272*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_early_phase_offset_ns");
273*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_early_gl_phase_offset_ns");
274*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_early_app_phase_offset_ns");
275*38e8c45fSAndroid Build Coastguard Worker validateProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns");
276*38e8c45fSAndroid Build Coastguard Worker }
277*38e8c45fSAndroid Build Coastguard Worker
278*38e8c45fSAndroid Build Coastguard Worker namespace {
sfDurationToOffset(std::chrono::nanoseconds sfDuration,nsecs_t vsyncDuration)279*38e8c45fSAndroid Build Coastguard Worker nsecs_t sfDurationToOffset(std::chrono::nanoseconds sfDuration, nsecs_t vsyncDuration) {
280*38e8c45fSAndroid Build Coastguard Worker return vsyncDuration - sfDuration.count() % vsyncDuration;
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker
appDurationToOffset(std::chrono::nanoseconds appDuration,std::chrono::nanoseconds sfDuration,nsecs_t vsyncDuration)283*38e8c45fSAndroid Build Coastguard Worker nsecs_t appDurationToOffset(std::chrono::nanoseconds appDuration,
284*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds sfDuration, nsecs_t vsyncDuration) {
285*38e8c45fSAndroid Build Coastguard Worker return vsyncDuration - (appDuration + sfDuration).count() % vsyncDuration;
286*38e8c45fSAndroid Build Coastguard Worker }
287*38e8c45fSAndroid Build Coastguard Worker } // namespace
288*38e8c45fSAndroid Build Coastguard Worker
constructOffsets(nsecs_t vsyncDuration) const289*38e8c45fSAndroid Build Coastguard Worker VsyncConfigSet WorkDuration::constructOffsets(nsecs_t vsyncDuration) const {
290*38e8c45fSAndroid Build Coastguard Worker const auto sfDurationFixup = [vsyncDuration](nsecs_t duration) {
291*38e8c45fSAndroid Build Coastguard Worker return duration == -1 ? std::chrono::nanoseconds(vsyncDuration) - 1ms
292*38e8c45fSAndroid Build Coastguard Worker : std::chrono::nanoseconds(duration);
293*38e8c45fSAndroid Build Coastguard Worker };
294*38e8c45fSAndroid Build Coastguard Worker
295*38e8c45fSAndroid Build Coastguard Worker const auto appDurationFixup = [vsyncDuration](nsecs_t duration) {
296*38e8c45fSAndroid Build Coastguard Worker return duration == -1 ? std::chrono::nanoseconds(vsyncDuration)
297*38e8c45fSAndroid Build Coastguard Worker : std::chrono::nanoseconds(duration);
298*38e8c45fSAndroid Build Coastguard Worker };
299*38e8c45fSAndroid Build Coastguard Worker
300*38e8c45fSAndroid Build Coastguard Worker const auto sfEarlyDuration = sfDurationFixup(mSfEarlyDuration);
301*38e8c45fSAndroid Build Coastguard Worker const auto appEarlyDuration = appDurationFixup(mAppEarlyDuration);
302*38e8c45fSAndroid Build Coastguard Worker const auto sfEarlyGpuDuration = sfDurationFixup(mSfEarlyGpuDuration);
303*38e8c45fSAndroid Build Coastguard Worker const auto appEarlyGpuDuration = appDurationFixup(mAppEarlyGpuDuration);
304*38e8c45fSAndroid Build Coastguard Worker const auto sfDuration = sfDurationFixup(mSfDuration);
305*38e8c45fSAndroid Build Coastguard Worker const auto appDuration = appDurationFixup(mAppDuration);
306*38e8c45fSAndroid Build Coastguard Worker
307*38e8c45fSAndroid Build Coastguard Worker return {
308*38e8c45fSAndroid Build Coastguard Worker .early =
309*38e8c45fSAndroid Build Coastguard Worker {
310*38e8c45fSAndroid Build Coastguard Worker
311*38e8c45fSAndroid Build Coastguard Worker .sfOffset = sfEarlyDuration.count() < vsyncDuration
312*38e8c45fSAndroid Build Coastguard Worker ? sfDurationToOffset(sfEarlyDuration, vsyncDuration)
313*38e8c45fSAndroid Build Coastguard Worker : sfDurationToOffset(sfEarlyDuration, vsyncDuration) -
314*38e8c45fSAndroid Build Coastguard Worker vsyncDuration,
315*38e8c45fSAndroid Build Coastguard Worker
316*38e8c45fSAndroid Build Coastguard Worker .appOffset = appDurationToOffset(appEarlyDuration, sfEarlyDuration,
317*38e8c45fSAndroid Build Coastguard Worker vsyncDuration),
318*38e8c45fSAndroid Build Coastguard Worker
319*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfEarlyDuration,
320*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appEarlyDuration,
321*38e8c45fSAndroid Build Coastguard Worker },
322*38e8c45fSAndroid Build Coastguard Worker .earlyGpu =
323*38e8c45fSAndroid Build Coastguard Worker {
324*38e8c45fSAndroid Build Coastguard Worker
325*38e8c45fSAndroid Build Coastguard Worker .sfOffset = sfEarlyGpuDuration.count() < vsyncDuration
326*38e8c45fSAndroid Build Coastguard Worker
327*38e8c45fSAndroid Build Coastguard Worker ? sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration)
328*38e8c45fSAndroid Build Coastguard Worker : sfDurationToOffset(sfEarlyGpuDuration, vsyncDuration) -
329*38e8c45fSAndroid Build Coastguard Worker vsyncDuration,
330*38e8c45fSAndroid Build Coastguard Worker
331*38e8c45fSAndroid Build Coastguard Worker .appOffset = appDurationToOffset(appEarlyGpuDuration,
332*38e8c45fSAndroid Build Coastguard Worker sfEarlyGpuDuration, vsyncDuration),
333*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfEarlyGpuDuration,
334*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appEarlyGpuDuration,
335*38e8c45fSAndroid Build Coastguard Worker },
336*38e8c45fSAndroid Build Coastguard Worker .late =
337*38e8c45fSAndroid Build Coastguard Worker {
338*38e8c45fSAndroid Build Coastguard Worker
339*38e8c45fSAndroid Build Coastguard Worker .sfOffset = sfDuration.count() < vsyncDuration
340*38e8c45fSAndroid Build Coastguard Worker
341*38e8c45fSAndroid Build Coastguard Worker ? sfDurationToOffset(sfDuration, vsyncDuration)
342*38e8c45fSAndroid Build Coastguard Worker : sfDurationToOffset(sfDuration, vsyncDuration) - vsyncDuration,
343*38e8c45fSAndroid Build Coastguard Worker
344*38e8c45fSAndroid Build Coastguard Worker .appOffset =
345*38e8c45fSAndroid Build Coastguard Worker appDurationToOffset(appDuration, sfDuration, vsyncDuration),
346*38e8c45fSAndroid Build Coastguard Worker
347*38e8c45fSAndroid Build Coastguard Worker .sfWorkDuration = sfDuration,
348*38e8c45fSAndroid Build Coastguard Worker .appWorkDuration = appDuration,
349*38e8c45fSAndroid Build Coastguard Worker },
350*38e8c45fSAndroid Build Coastguard Worker .hwcMinWorkDuration = std::chrono::nanoseconds(mHwcMinWorkDuration),
351*38e8c45fSAndroid Build Coastguard Worker };
352*38e8c45fSAndroid Build Coastguard Worker }
353*38e8c45fSAndroid Build Coastguard Worker
WorkDuration(Fps currentRefreshRate)354*38e8c45fSAndroid Build Coastguard Worker WorkDuration::WorkDuration(Fps currentRefreshRate)
355*38e8c45fSAndroid Build Coastguard Worker : WorkDuration(currentRefreshRate, getProperty("debug.sf.late.sf.duration").value_or(-1),
356*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.late.app.duration").value_or(-1),
357*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
358*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.early.app.duration").value_or(mAppDuration),
359*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.earlyGl.sf.duration").value_or(mSfDuration),
360*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.earlyGl.app.duration").value_or(mAppDuration),
361*38e8c45fSAndroid Build Coastguard Worker getProperty("debug.sf.hwc.min.duration").value_or(0)) {
362*38e8c45fSAndroid Build Coastguard Worker validateSysprops();
363*38e8c45fSAndroid Build Coastguard Worker }
364*38e8c45fSAndroid Build Coastguard Worker
WorkDuration(Fps currentRefreshRate,nsecs_t sfDuration,nsecs_t appDuration,nsecs_t sfEarlyDuration,nsecs_t appEarlyDuration,nsecs_t sfEarlyGpuDuration,nsecs_t appEarlyGpuDuration,nsecs_t hwcMinWorkDuration)365*38e8c45fSAndroid Build Coastguard Worker WorkDuration::WorkDuration(Fps currentRefreshRate, nsecs_t sfDuration, nsecs_t appDuration,
366*38e8c45fSAndroid Build Coastguard Worker nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
367*38e8c45fSAndroid Build Coastguard Worker nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
368*38e8c45fSAndroid Build Coastguard Worker nsecs_t hwcMinWorkDuration)
369*38e8c45fSAndroid Build Coastguard Worker : VsyncConfiguration(currentRefreshRate),
370*38e8c45fSAndroid Build Coastguard Worker mSfDuration(sfDuration),
371*38e8c45fSAndroid Build Coastguard Worker mAppDuration(appDuration),
372*38e8c45fSAndroid Build Coastguard Worker mSfEarlyDuration(sfEarlyDuration),
373*38e8c45fSAndroid Build Coastguard Worker mAppEarlyDuration(appEarlyDuration),
374*38e8c45fSAndroid Build Coastguard Worker mSfEarlyGpuDuration(sfEarlyGpuDuration),
375*38e8c45fSAndroid Build Coastguard Worker mAppEarlyGpuDuration(appEarlyGpuDuration),
376*38e8c45fSAndroid Build Coastguard Worker mHwcMinWorkDuration(hwcMinWorkDuration) {}
377*38e8c45fSAndroid Build Coastguard Worker
378*38e8c45fSAndroid Build Coastguard Worker } // namespace android::scheduler::impl
379