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 <chrono> 20 #include <mutex> 21 22 #include "Scheduler.h" 23 24 namespace android::scheduler { 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 static constexpr 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 static constexpr int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2; 40 41 // Margin used to account for potential data races 42 static const constexpr std::chrono::nanoseconds MARGIN_FOR_TX_APPLY = 1ms; 43 44 public: 45 // Wrapper for a collection of surfaceflinger/app offsets for a particular 46 // configuration. 47 struct Offsets { 48 nsecs_t sf; 49 nsecs_t app; 50 51 bool operator==(const Offsets& other) const { return sf == other.sf && app == other.app; } 52 53 bool operator!=(const Offsets& other) const { return !(*this == other); } 54 }; 55 56 struct OffsetsConfig { 57 Offsets early; // For transactions with the eEarlyWakeup flag. 58 Offsets earlyGl; // As above but while compositing with GL. 59 Offsets late; // Default. 60 61 bool operator==(const OffsetsConfig& other) const { 62 return early == other.early && earlyGl == other.earlyGl && late == other.late; 63 } 64 65 bool operator!=(const OffsetsConfig& other) const { return !(*this == other); } 66 }; 67 68 VSyncModulator(IPhaseOffsetControl&, ConnectionHandle appConnectionHandle, 69 ConnectionHandle sfConnectionHandle, const OffsetsConfig&); 70 71 void setPhaseOffsets(const OffsetsConfig&) EXCLUDES(mMutex); 72 73 // Signals that a transaction has started, and changes offsets accordingly. 74 void setTransactionStart(Scheduler::TransactionStart transactionStart); 75 76 // Signals that a transaction has been completed, so that we can finish 77 // special handling for a transaction. 78 void onTransactionHandled(); 79 80 // Called when we send a refresh rate change to hardware composer, so that 81 // we can move into early offsets. 82 void onRefreshRateChangeInitiated(); 83 84 // Called when we detect from vsync signals that the refresh rate changed. 85 // This way we can move out of early offsets if no longer necessary. 86 void onRefreshRateChangeCompleted(); 87 88 // Called when the display is presenting a new frame. usedRenderEngine 89 // should be set to true if RenderEngine was involved with composing the new 90 // frame. 91 void onRefreshed(bool usedRenderEngine); 92 93 // Returns the offsets that we are currently using 94 Offsets getOffsets() const EXCLUDES(mMutex); 95 96 private: 97 friend class VSyncModulatorTest; 98 // Returns the next offsets that we should be using 99 const Offsets& getNextOffsets() const REQUIRES(mMutex); 100 // Updates offsets and persists them into the scheduler framework. 101 void updateOffsets() EXCLUDES(mMutex); 102 void updateOffsetsLocked() REQUIRES(mMutex); 103 104 IPhaseOffsetControl& mPhaseOffsetControl; 105 const ConnectionHandle mAppConnectionHandle; 106 const ConnectionHandle mSfConnectionHandle; 107 108 mutable std::mutex mMutex; 109 OffsetsConfig mOffsetsConfig GUARDED_BY(mMutex); 110 GUARDED_BY(mMutex)111 Offsets mOffsets GUARDED_BY(mMutex){mOffsetsConfig.late}; 112 113 std::atomic<Scheduler::TransactionStart> mTransactionStart = 114 Scheduler::TransactionStart::Normal; 115 std::atomic<bool> mRefreshRateChangePending = false; 116 std::atomic<bool> mExplicitEarlyWakeup = false; 117 std::atomic<int> mRemainingEarlyFrameCount = 0; 118 std::atomic<int> mRemainingRenderEngineUsageCount = 0; 119 std::atomic<std::chrono::steady_clock::time_point> mEarlyTxnStartTime = {}; 120 std::atomic<std::chrono::steady_clock::time_point> mTxnAppliedTime = {}; 121 122 bool mTraceDetailedInfo = false; 123 }; 124 125 } // namespace android::scheduler 126