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 <unordered_map>
20 
21 #include "RefreshRateConfigs.h"
22 #include "VSyncModulator.h"
23 
24 namespace android::scheduler {
25 
26 /*
27  * This class encapsulates offsets for different refresh rates. Depending
28  * on what refresh rate we are using, and wheter we are composing in GL,
29  * different offsets will help us with latency. This class keeps track of
30  * which mode the device is on, and returns approprate offsets when needed.
31  */
32 class PhaseConfiguration {
33 public:
34     using Offsets = VSyncModulator::OffsetsConfig;
35 
36     virtual ~PhaseConfiguration();
37 
38     virtual Offsets getCurrentOffsets() const = 0;
39     virtual Offsets getOffsetsForRefreshRate(float fps) const = 0;
40 
41     virtual void setRefreshRateFps(float fps) = 0;
42 
43     virtual void dump(std::string& result) const = 0;
44 };
45 
46 namespace impl {
47 
48 /*
49  * This is the old implementation of phase offsets and considered as deprecated.
50  * PhaseDurations is the new implementation.
51  */
52 class PhaseOffsets : public scheduler::PhaseConfiguration {
53 public:
54     PhaseOffsets(const scheduler::RefreshRateConfigs&);
55 
56     // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
57     Offsets getOffsetsForRefreshRate(float fps) const override;
58 
59     // Returns early, early GL, and late offsets for Apps and SF.
getCurrentOffsets()60     Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); }
61 
62     // This function should be called when the device is switching between different
63     // refresh rates, to properly update the offsets.
setRefreshRateFps(float fps)64     void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; }
65 
66     // Returns current offsets in human friendly format.
67     void dump(std::string& result) const override;
68 
69 protected:
70     // Used for unit tests
71     PhaseOffsets(const std::vector<float>& refreshRates, float currentFps,
72                  nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs,
73                  std::optional<nsecs_t> earlySfOffsetNs, std::optional<nsecs_t> earlyGlSfOffsetNs,
74                  std::optional<nsecs_t> earlyAppOffsetNs, std::optional<nsecs_t> earlyGlAppOffsetNs,
75                  nsecs_t thresholdForNextVsync);
76     std::unordered_map<float, Offsets> initializeOffsets(
77             const std::vector<float>& refreshRates) const;
78     Offsets getDefaultOffsets(nsecs_t vsyncPeriod) const;
79     Offsets getHighFpsOffsets(nsecs_t vsyncPeriod) const;
80     Offsets getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const;
81 
82     const nsecs_t mVSyncPhaseOffsetNs;
83     const nsecs_t mSfVSyncPhaseOffsetNs;
84     const std::optional<nsecs_t> mEarlySfOffsetNs;
85     const std::optional<nsecs_t> mEarlyGlSfOffsetNs;
86     const std::optional<nsecs_t> mEarlyAppOffsetNs;
87     const std::optional<nsecs_t> mEarlyGlAppOffsetNs;
88     const nsecs_t mThresholdForNextVsync;
89     const std::unordered_map<float, Offsets> mOffsets;
90 
91     std::atomic<float> mRefreshRateFps;
92 };
93 
94 /*
95  * Class that encapsulates the phase offsets for SurfaceFlinger and App.
96  * The offsets are calculated from durations for each one of the (late, early, earlyGL)
97  * offset types.
98  */
99 class PhaseDurations : public scheduler::PhaseConfiguration {
100 public:
101     PhaseDurations(const scheduler::RefreshRateConfigs&);
102 
103     // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
104     Offsets getOffsetsForRefreshRate(float fps) const override;
105 
106     // Returns early, early GL, and late offsets for Apps and SF.
getCurrentOffsets()107     Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); }
108 
109     // This function should be called when the device is switching between different
110     // refresh rates, to properly update the offsets.
setRefreshRateFps(float fps)111     void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; }
112 
113     // Returns current offsets in human friendly format.
114     void dump(std::string& result) const override;
115 
116 protected:
117     // Used for unit tests
118     PhaseDurations(const std::vector<float>& refreshRates, float currentFps, nsecs_t sfDuration,
119                    nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration,
120                    nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration);
121 
122 private:
123     std::unordered_map<float, Offsets> initializeOffsets(const std::vector<float>&) const;
124     PhaseDurations::Offsets constructOffsets(nsecs_t vsyncDuration) const;
125 
126     const nsecs_t mSfDuration;
127     const nsecs_t mAppDuration;
128 
129     const nsecs_t mSfEarlyDuration;
130     const nsecs_t mAppEarlyDuration;
131 
132     const nsecs_t mSfEarlyGlDuration;
133     const nsecs_t mAppEarlyGlDuration;
134 
135     const std::unordered_map<float, Offsets> mOffsets;
136 
137     std::atomic<float> mRefreshRateFps;
138 };
139 
140 } // namespace impl
141 } // namespace android::scheduler
142