summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Scheduler/VsyncConfiguration.h
blob: 3e53b3faa2028addaafff9ac70ef4ac3cec90854 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * 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.
 */

#pragma once

#include <mutex>
#include <type_traits>
#include <unordered_map>
#include <vector>

#include <utils/Timers.h>

#include "Fps.h"
#include "VsyncModulator.h"

namespace android::scheduler {

/*
 * This class encapsulates vsync configurations for different refresh rates. Depending
 * on what refresh rate we are using, and wheter we are composing in GL,
 * different offsets will help us with latency. This class keeps track of
 * which mode the device is on, and returns approprate offsets when needed.
 */
class VsyncConfiguration {
public:
    using VsyncConfigSet = VsyncModulator::VsyncConfigSet;

    virtual ~VsyncConfiguration() = default;
    virtual VsyncConfigSet getCurrentConfigs() const = 0;
    virtual VsyncConfigSet getConfigsForRefreshRate(Fps fps) const = 0;
    virtual void reset() = 0;

    virtual void setRefreshRateFps(Fps fps) = 0;
    virtual void dump(std::string& result) const = 0;
};

namespace impl {

/*
 * This is a common implementation for both phase offsets and durations.
 * PhaseOffsets and WorkDuration derive from this class and implement the
 * constructOffsets method
 */
class VsyncConfiguration : public scheduler::VsyncConfiguration {
public:
    explicit VsyncConfiguration(Fps currentFps);

    // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
    VsyncConfigSet getConfigsForRefreshRate(Fps fps) const override EXCLUDES(mLock);

    // Returns early, early GL, and late offsets for Apps and SF.
    VsyncConfigSet getCurrentConfigs() const override EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        return getConfigsForRefreshRateLocked(mRefreshRateFps);
    }

    // Cleans the internal cache.
    void reset() override EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        mOffsetsCache.clear();
    }

    // This function should be called when the device is switching between different
    // refresh rates, to properly update the offsets.
    void setRefreshRateFps(Fps fps) override EXCLUDES(mLock) {
        std::lock_guard lock(mLock);
        mRefreshRateFps = fps;
    }

    // Returns current offsets in human friendly format.
    void dump(std::string& result) const override;

protected:
    virtual VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const = 0;

    VsyncConfigSet getConfigsForRefreshRateLocked(Fps fps) const REQUIRES(mLock);

    mutable std::unordered_map<Fps, VsyncConfigSet, std::hash<Fps>, Fps::EqualsInBuckets>
            mOffsetsCache GUARDED_BY(mLock);
    std::atomic<Fps> mRefreshRateFps GUARDED_BY(mLock);
    mutable std::mutex mLock;
};

/*
 * This is the old implementation of phase offsets and considered as deprecated.
 * WorkDuration is the new implementation.
 */
class PhaseOffsets : public VsyncConfiguration {
public:
    explicit PhaseOffsets(Fps currentRefreshRate);

protected:
    // Used for unit tests
    PhaseOffsets(Fps currentRefreshRate, 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);

private:
    VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;

    VsyncConfigSet getDefaultOffsets(nsecs_t vsyncPeriod) const;
    VsyncConfigSet getHighFpsOffsets(nsecs_t vsyncPeriod) const;

    const nsecs_t mVSyncPhaseOffsetNs;
    const nsecs_t mSfVSyncPhaseOffsetNs;
    const std::optional<nsecs_t> mEarlySfOffsetNs;
    const std::optional<nsecs_t> mEarlyGpuSfOffsetNs;
    const std::optional<nsecs_t> mEarlyAppOffsetNs;
    const std::optional<nsecs_t> mEarlyGpuAppOffsetNs;

    const nsecs_t mHighFpsVSyncPhaseOffsetNs;
    const nsecs_t mHighFpsSfVSyncPhaseOffsetNs;
    const std::optional<nsecs_t> mHighFpsEarlySfOffsetNs;
    const std::optional<nsecs_t> mHighFpsEarlyGpuSfOffsetNs;
    const std::optional<nsecs_t> mHighFpsEarlyAppOffsetNs;
    const std::optional<nsecs_t> mHighFpsEarlyGpuAppOffsetNs;

    const nsecs_t mThresholdForNextVsync;
    const nsecs_t mHwcMinWorkDuration;
};

/*
 * Class that encapsulates the phase offsets for SurfaceFlinger and App.
 * The offsets are calculated from durations for each one of the (late, early, earlyGpu)
 * offset types.
 */
class WorkDuration : public VsyncConfiguration {
public:
    explicit WorkDuration(Fps currentRefrshRate);

protected:
    // Used for unit tests
    WorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration,
                 nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration,
                 nsecs_t hwcMinWorkDuration);

private:
    VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const override;

    const nsecs_t mSfDuration;
    const nsecs_t mAppDuration;

    const nsecs_t mSfEarlyDuration;
    const nsecs_t mAppEarlyDuration;

    const nsecs_t mSfEarlyGpuDuration;
    const nsecs_t mAppEarlyGpuDuration;

    const nsecs_t mHwcMinWorkDuration;
};

} // namespace impl
} // namespace android::scheduler