1 /*
2  * Copyright 2018 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 <cinttypes>
20 #include <mutex>
21 
22 #include "Scheduler.h"
23 
24 namespace android {
25 
26 /*
27  * Modulates the vsync-offsets depending on current SurfaceFlinger state.
28  */
29 class VSyncModulator {
30 private:
31     // Number of frames we'll keep the early phase offsets once they are activated for a
32     // transaction. This acts as a low-pass filter in case the client isn't quick enough in
33     // sending new transactions.
34     const int MIN_EARLY_FRAME_COUNT_TRANSACTION = 2;
35 
36     // Number of frames we'll keep the early gl phase offsets once they are activated.
37     // This acts as a low-pass filter to avoid scenarios where we rapidly
38     // switch in and out of gl composition.
39     const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
40 
41 public:
42     VSyncModulator();
43 
44     // Wrapper for a collection of surfaceflinger/app offsets for a particular
45     // configuration .
46     struct Offsets {
47         scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
48         nsecs_t sf;
49         nsecs_t app;
50     };
51 
52     enum class OffsetType {
53         Early,
54         EarlyGl,
55         Late,
56     };
57 
58     // Sets the phase offsets
59     //
60     // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
61     //          as early. May be the same as late, in which case we don't shift offsets.
62     // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
63     //            and the transaction was marked as early, we'll use sfEarly.
64     // sfLate: The regular SF vsync phase offset.
65     // appEarly: Like sfEarly, but for the app-vsync
66     // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
67     // appLate: The regular app vsync phase offset.
68     void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
69                          nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);
70 
71     // Sets the scheduler and vsync connection handlers.
setSchedulerAndHandles(Scheduler * scheduler,Scheduler::ConnectionHandle * appConnectionHandle,Scheduler::ConnectionHandle * sfConnectionHandle)72     void setSchedulerAndHandles(Scheduler* scheduler,
73                                 Scheduler::ConnectionHandle* appConnectionHandle,
74                                 Scheduler::ConnectionHandle* sfConnectionHandle) {
75         mScheduler = scheduler;
76         mAppConnectionHandle = appConnectionHandle;
77         mSfConnectionHandle = sfConnectionHandle;
78     }
79 
80     // Signals that a transaction has started, and changes offsets accordingly.
81     void setTransactionStart(Scheduler::TransactionStart transactionStart);
82 
83     // Signals that a transaction has been completed, so that we can finish
84     // special handling for a transaction.
85     void onTransactionHandled();
86 
87     // Called when we send a refresh rate change to hardware composer, so that
88     // we can move into early offsets.
89     void onRefreshRateChangeInitiated();
90 
91     // Called when we detect from vsync signals that the refresh rate changed.
92     // This way we can move out of early offsets if no longer necessary.
93     void onRefreshRateChangeCompleted();
94 
95     // Called when the display is presenting a new frame. usedRenderEngine
96     // should be set to true if RenderEngine was involved with composing the new
97     // frame.
98     void onRefreshed(bool usedRenderEngine);
99 
100     // Returns the offsets that we are currently using
101     Offsets getOffsets() EXCLUDES(mMutex);
102 
103 private:
104     // Returns the next offsets that we should be using
105     Offsets getNextOffsets() REQUIRES(mMutex);
106     // Returns the next offset type that we should use.
107     OffsetType getNextOffsetType();
108     // Updates offsets and persists them into the scheduler framework.
109     void updateOffsets() EXCLUDES(mMutex);
110     void updateOffsetsLocked() REQUIRES(mMutex);
111     // Updates the internal offsets and offset type.
112     void flushOffsets() REQUIRES(mMutex);
113 
114     mutable std::mutex mMutex;
115     std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
116     nsecs_t mThresholdForNextVsync;
117 
118     Scheduler* mScheduler = nullptr;
119     Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
120     Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
121 
122     Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};
123 
124     std::atomic<Scheduler::TransactionStart> mTransactionStart =
125             Scheduler::TransactionStart::NORMAL;
126     std::atomic<bool> mRefreshRateChangePending = false;
127     std::atomic<int> mRemainingEarlyFrameCount = 0;
128     std::atomic<int> mRemainingRenderEngineUsageCount = 0;
129 
130     bool mTraceDetailedInfo = false;
131 };
132 
133 } // namespace android
134