summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Scheduler/PhaseOffsets.h
blob: 9ec6d56fdff57dd9647e6a0f395f7cda795cea13 (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
/*
 * 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 <unordered_map>

#include "RefreshRateConfigs.h"
#include "VSyncModulator.h"

namespace android::scheduler {

/*
 * This class encapsulates offsets 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 PhaseConfiguration {
public:
    using Offsets = VSyncModulator::OffsetsConfig;

    virtual ~PhaseConfiguration();

    virtual Offsets getCurrentOffsets() const = 0;
    virtual Offsets getOffsetsForRefreshRate(float fps) const = 0;

    virtual void setRefreshRateFps(float fps) = 0;

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

namespace impl {

/*
 * This is the old implementation of phase offsets and considered as deprecated.
 * PhaseDurations is the new implementation.
 */
class PhaseOffsets : public scheduler::PhaseConfiguration {
public:
    PhaseOffsets(const scheduler::RefreshRateConfigs&);

    // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
    Offsets getOffsetsForRefreshRate(float fps) const override;

    // Returns early, early GL, and late offsets for Apps and SF.
    Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); }

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

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

protected:
    // Used for unit tests
    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);
    std::unordered_map<float, Offsets> initializeOffsets(
            const std::vector<float>& refreshRates) const;
    Offsets getDefaultOffsets(nsecs_t vsyncPeriod) const;
    Offsets getHighFpsOffsets(nsecs_t vsyncPeriod) const;
    Offsets getPhaseOffsets(float fps, nsecs_t vsyncPeriod) const;

    const nsecs_t mVSyncPhaseOffsetNs;
    const nsecs_t mSfVSyncPhaseOffsetNs;
    const std::optional<nsecs_t> mEarlySfOffsetNs;
    const std::optional<nsecs_t> mEarlyGlSfOffsetNs;
    const std::optional<nsecs_t> mEarlyAppOffsetNs;
    const std::optional<nsecs_t> mEarlyGlAppOffsetNs;
    const nsecs_t mThresholdForNextVsync;
    const std::unordered_map<float, Offsets> mOffsets;

    std::atomic<float> mRefreshRateFps;
};

/*
 * Class that encapsulates the phase offsets for SurfaceFlinger and App.
 * The offsets are calculated from durations for each one of the (late, early, earlyGL)
 * offset types.
 */
class PhaseDurations : public scheduler::PhaseConfiguration {
public:
    PhaseDurations(const scheduler::RefreshRateConfigs&);

    // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate.
    Offsets getOffsetsForRefreshRate(float fps) const override;

    // Returns early, early GL, and late offsets for Apps and SF.
    Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); }

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

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

protected:
    // Used for unit tests
    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);

private:
    std::unordered_map<float, Offsets> initializeOffsets(const std::vector<float>&) const;
    PhaseDurations::Offsets constructOffsets(nsecs_t vsyncDuration) const;

    const nsecs_t mSfDuration;
    const nsecs_t mAppDuration;

    const nsecs_t mSfEarlyDuration;
    const nsecs_t mAppEarlyDuration;

    const nsecs_t mSfEarlyGlDuration;
    const nsecs_t mAppEarlyGlDuration;

    const std::unordered_map<float, Offsets> mOffsets;

    std::atomic<float> mRefreshRateFps;
};

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