1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <mutex>
20 #include <type_traits>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include <utils/Timers.h>
25 
26 #include "Fps.h"
27 #include "VsyncModulator.h"
28 
29 namespace android::scheduler {
30 
31 /*
32  * This class encapsulates vsync configurations for different refresh rates. Depending
33  * on what refresh rate we are using, and wheter we are composing in GL,
34  * different offsets will help us with latency. This class keeps track of
35  * which mode the device is on, and returns approprate offsets when needed.
36  */
37 class VsyncConfiguration {
38 public:
39     using VsyncConfigSet = VsyncModulator::VsyncConfigSet;
40 
41     virtual ~VsyncConfiguration() = default;
42     virtual VsyncConfigSet getCurrentConfigs() const = 0;
43     virtual VsyncConfigSet getConfigsForRefreshRate(Fps fps) const = 0;
44     virtual void reset() = 0;
45 
46     virtual void setRefreshRateFps(Fps fps) = 0;
47     virtual void dump(std::string& result) const = 0;
48 };
49 
50 namespace impl {
51 
52 /*
53  * This is a common implementation for both phase offsets and durations.
54  * PhaseOffsets and WorkDuration derive from this class and implement the
55  * constructOffsets method
56  */
57 class VsyncConfiguration : public scheduler::VsyncConfiguration {
58 public:
59     explicit VsyncConfiguration(Fps currentFps);
60 
61     // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
62     VsyncConfigSet getConfigsForRefreshRate(Fps fps) const override EXCLUDES(mLock);
63 
64     // Returns early, early GL, and late offsets for Apps and SF.
getCurrentConfigs()65     VsyncConfigSet getCurrentConfigs() const override EXCLUDES(mLock) {
66         std::lock_guard lock(mLock);
67         return getConfigsForRefreshRateLocked(mRefreshRateFps);
68     }
69 
70     // Cleans the internal cache.
reset()71     void reset() override EXCLUDES(mLock) {
72         std::lock_guard lock(mLock);
73         mOffsetsCache.clear();
74     }
75 
76     // This function should be called when the device is switching between different
77     // refresh rates, to properly update the offsets.
setRefreshRateFps(Fps fps)78     void setRefreshRateFps(Fps fps) override EXCLUDES(mLock) {
79         std::lock_guard lock(mLock);
80         mRefreshRateFps = fps;
81     }
82 
83     // Returns current offsets in human friendly format.
84     void dump(std::string& result) const override;
85 
86 protected:
87     virtual VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const = 0;
88 
89     VsyncConfigSet getConfigsForRefreshRateLocked(Fps fps) const REQUIRES(mLock);
90 
91     mutable std::unordered_map<Fps, VsyncConfigSet, std::hash<Fps>, Fps::EqualsInBuckets>
92             mOffsetsCache GUARDED_BY(mLock);
93     std::atomic<Fps> mRefreshRateFps GUARDED_BY(mLock);
94     mutable std::mutex mLock;
95 };
96 
97 /*
98  * This is the old implementation of phase offsets and considered as deprecated.
99  * WorkDuration is the new implementation.
100  */
101 class PhaseOffsets : public VsyncConfiguration {
102 public:
103     explicit PhaseOffsets(Fps currentRefreshRate);
104 
105 protected:
106     // Used for unit tests
107     PhaseOffsets(Fps currentRefreshRate, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
108                  std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGpuSfOffsetNs,
109                  std::optional<nsecs_t> earlyAppOffsetNs,
110                  std::optional<nsecs_t> earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs,
111                  nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional<nsecs_t> highFpsEarlySfOffsetNs,
112                  std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs,
113                  std::optional<nsecs_t> highFpsEarlyAppOffsetNs,
114                  std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync,
115                  nsecs_t hwcMinWorkDuration);
116 
117 private:
118     VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
119 
120     VsyncConfigSet getDefaultOffsets(nsecs_t vsyncPeriod) const;
121     VsyncConfigSet getHighFpsOffsets(nsecs_t vsyncPeriod) const;
122 
123     const nsecs_t mVSyncPhaseOffsetNs;
124     const nsecs_t mSfVSyncPhaseOffsetNs;
125     const std::optional<nsecs_t> mEarlySfOffsetNs;
126     const std::optional<nsecs_t> mEarlyGpuSfOffsetNs;
127     const std::optional<nsecs_t> mEarlyAppOffsetNs;
128     const std::optional<nsecs_t> mEarlyGpuAppOffsetNs;
129 
130     const nsecs_t mHighFpsVSyncPhaseOffsetNs;
131     const nsecs_t mHighFpsSfVSyncPhaseOffsetNs;
132     const std::optional<nsecs_t> mHighFpsEarlySfOffsetNs;
133     const std::optional<nsecs_t> mHighFpsEarlyGpuSfOffsetNs;
134     const std::optional<nsecs_t> mHighFpsEarlyAppOffsetNs;
135     const std::optional<nsecs_t> mHighFpsEarlyGpuAppOffsetNs;
136 
137     const nsecs_t mThresholdForNextVsync;
138     const nsecs_t mHwcMinWorkDuration;
139 };
140 
141 /*
142  * Class that encapsulates the phase offsets for SurfaceFlinger and App.
143  * The offsets are calculated from durations for each one of the (late, early, earlyGpu)
144  * offset types.
145  */
146 class WorkDuration : public VsyncConfiguration {
147 public:
148     explicit WorkDuration(Fps currentRefrshRate);
149 
150 protected:
151     // Used for unit tests
152     WorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration,
153                  nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
154                  nsecs_t hwcMinWorkDuration);
155 
156 private:
157     VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;
158 
159     const nsecs_t mSfDuration;
160     const nsecs_t mAppDuration;
161 
162     const nsecs_t mSfEarlyDuration;
163     const nsecs_t mAppEarlyDuration;
164 
165     const nsecs_t mSfEarlyGpuDuration;
166     const nsecs_t mAppEarlyGpuDuration;
167 
168     const nsecs_t mHwcMinWorkDuration;
169 };
170 
171 } // namespace impl
172 } // namespace android::scheduler
173