File: VSyncModulator.h

package info (click to toggle)
android-platform-frameworks-native 1%3A10.0.0%2Br36-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 25,828 kB
  • sloc: cpp: 252,025; xml: 52,812; ansic: 26,775; java: 5,107; python: 1,887; sh: 266; asm: 105; makefile: 23
file content (133 lines) | stat: -rw-r--r-- 5,071 bytes parent folder | download | duplicates (3)
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
/*
 * Copyright 2018 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 <cinttypes>
#include <mutex>

#include "Scheduler.h"

namespace android {

/*
 * Modulates the vsync-offsets depending on current SurfaceFlinger state.
 */
class VSyncModulator {
private:
    // Number of frames we'll keep the early phase offsets once they are activated for a
    // transaction. This acts as a low-pass filter in case the client isn't quick enough in
    // sending new transactions.
    const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;

    // Number of frames we'll keep the early gl phase offsets once they are activated.
    // This acts as a low-pass filter to avoid scenarios where we rapidly
    // switch in and out of gl composition.
    const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;

public:
    VSyncModulator();

    // Wrapper for a collection of surfaceflinger/app offsets for a particular
    // configuration .
    struct Offsets {
        scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
        nsecs_t sf;
        nsecs_t app;
    };

    enum class OffsetType {
        Early,
        EarlyGl,
        Late,
    };

    // Sets the phase offsets
    //
    // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
    //          as early. May be the same as late, in which case we don't shift offsets.
    // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
    //            and the transaction was marked as early, we'll use sfEarly.
    // sfLate: The regular SF vsync phase offset.
    // appEarly: Like sfEarly, but for the app-vsync
    // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
    // appLate: The regular app vsync phase offset.
    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
                         nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);

    // Sets the scheduler and vsync connection handlers.
    void setSchedulerAndHandles(Scheduler* scheduler,
                                Scheduler::ConnectionHandle* appConnectionHandle,
                                Scheduler::ConnectionHandle* sfConnectionHandle) {
        mScheduler = scheduler;
        mAppConnectionHandle = appConnectionHandle;
        mSfConnectionHandle = sfConnectionHandle;
    }

    // Signals that a transaction has started, and changes offsets accordingly.
    void setTransactionStart(Scheduler::TransactionStart transactionStart);

    // Signals that a transaction has been completed, so that we can finish
    // special handling for a transaction.
    void onTransactionHandled();

    // Called when we send a refresh rate change to hardware composer, so that
    // we can move into early offsets.
    void onRefreshRateChangeInitiated();

    // Called when we detect from vsync signals that the refresh rate changed.
    // This way we can move out of early offsets if no longer necessary.
    void onRefreshRateChangeCompleted();

    // Called when the display is presenting a new frame. usedRenderEngine
    // should be set to true if RenderEngine was involved with composing the new
    // frame.
    void onRefreshed(bool usedRenderEngine);

    // Returns the offsets that we are currently using
    Offsets getOffsets() EXCLUDES(mMutex);

private:
    // Returns the next offsets that we should be using
    Offsets getNextOffsets() REQUIRES(mMutex);
    // Returns the next offset type that we should use.
    OffsetType getNextOffsetType();
    // Updates offsets and persists them into the scheduler framework.
    void updateOffsets() EXCLUDES(mMutex);
    void updateOffsetsLocked() REQUIRES(mMutex);
    // Updates the internal offsets and offset type.
    void flushOffsets() REQUIRES(mMutex);

    mutable std::mutex mMutex;
    std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
    nsecs_t mThresholdForNextVsync;

    Scheduler* mScheduler = nullptr;
    Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
    Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;

    Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};

    std::atomic<Scheduler::TransactionStart> mTransactionStart =
            Scheduler::TransactionStart::NORMAL;
    std::atomic<bool> mRefreshRateChangePending = false;
    std::atomic<int> mRemainingEarlyFrameCount = 0;
    std::atomic<int> mRemainingRenderEngineUsageCount = 0;

    bool mTraceDetailedInfo = false;
};

} // namespace android