blob: 96d47ad3c9651a705978567a765b318ad64f47fa [file] [log] [blame]
Alec Mourib488afa2019-05-23 10:22:24 -07001/*
2 * Copyright 2019 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
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Alec Mourid7599d82019-05-22 19:58:00 -070021#define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
Dominik Laskowskia93a5312020-07-23 15:10:03 -070023#include "VsyncModulator.h"
Alec Mourib488afa2019-05-23 10:22:24 -070024
Alec Mourid7599d82019-05-22 19:58:00 -070025#include <cutils/properties.h>
26#include <utils/Trace.h>
27
Alec Mourif792cfe2020-06-05 13:11:23 -070028#include <chrono>
Alec Mourib488afa2019-05-23 10:22:24 -070029#include <cinttypes>
30#include <mutex>
31
Dominik Laskowskieddeda12019-07-19 11:54:13 -070032namespace android::scheduler {
Alec Mourib488afa2019-05-23 10:22:24 -070033
Ady Abrahambf1349c2020-06-12 14:26:18 -070034VSyncModulator::VSyncModulator(IPhaseOffsetControl& phaseOffsetControl,
Dominik Laskowski98041832019-08-01 18:35:59 -070035 Scheduler::ConnectionHandle appConnectionHandle,
36 Scheduler::ConnectionHandle sfConnectionHandle,
Dominik Laskowskieddeda12019-07-19 11:54:13 -070037 const OffsetsConfig& config)
Ady Abrahambf1349c2020-06-12 14:26:18 -070038 : mPhaseOffsetControl(phaseOffsetControl),
Dominik Laskowskieddeda12019-07-19 11:54:13 -070039 mAppConnectionHandle(appConnectionHandle),
40 mSfConnectionHandle(sfConnectionHandle),
41 mOffsetsConfig(config) {
Alec Mourid7599d82019-05-22 19:58:00 -070042 char value[PROPERTY_VALUE_MAX];
43 property_get("debug.sf.vsync_trace_detailed_info", value, "0");
44 mTraceDetailedInfo = atoi(value);
Alec Mourid7599d82019-05-22 19:58:00 -070045}
46
Dominik Laskowskieddeda12019-07-19 11:54:13 -070047void VSyncModulator::setPhaseOffsets(const OffsetsConfig& config) {
Alec Mourid7599d82019-05-22 19:58:00 -070048 std::lock_guard<std::mutex> lock(mMutex);
Dominik Laskowskieddeda12019-07-19 11:54:13 -070049 mOffsetsConfig = config;
Alec Mourid7599d82019-05-22 19:58:00 -070050 updateOffsetsLocked();
Alec Mourib488afa2019-05-23 10:22:24 -070051}
52
53void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
Ady Abrahambf1349c2020-06-12 14:26:18 -070054 switch (transactionStart) {
55 case Scheduler::TransactionStart::EarlyStart:
56 ALOGW_IF(mExplicitEarlyWakeup, "Already in TransactionStart::EarlyStart");
57 mExplicitEarlyWakeup = true;
58 break;
59 case Scheduler::TransactionStart::EarlyEnd:
60 ALOGW_IF(!mExplicitEarlyWakeup, "Not in TransactionStart::EarlyStart");
61 mExplicitEarlyWakeup = false;
62 break;
63 case Scheduler::TransactionStart::Normal:
64 case Scheduler::TransactionStart::Early:
65 // Non explicit don't change the explicit early wakeup state
66 break;
67 }
68
69 if (mTraceDetailedInfo) {
70 ATRACE_INT("mExplicitEarlyWakeup", mExplicitEarlyWakeup);
71 }
72
73 if (!mExplicitEarlyWakeup &&
74 (transactionStart == Scheduler::TransactionStart::Early ||
75 transactionStart == Scheduler::TransactionStart::EarlyEnd)) {
Alec Mourib488afa2019-05-23 10:22:24 -070076 mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
Alec Mourif792cfe2020-06-05 13:11:23 -070077 mEarlyTxnStartTime = std::chrono::steady_clock::now();
Alec Mourib488afa2019-05-23 10:22:24 -070078 }
79
80 // An early transaction stays an early transaction.
81 if (transactionStart == mTransactionStart ||
Ady Abrahambf1349c2020-06-12 14:26:18 -070082 mTransactionStart == Scheduler::TransactionStart::EarlyEnd) {
Alec Mourib488afa2019-05-23 10:22:24 -070083 return;
84 }
85 mTransactionStart = transactionStart;
86 updateOffsets();
87}
88
89void VSyncModulator::onTransactionHandled() {
Alec Mourif792cfe2020-06-05 13:11:23 -070090 mTxnAppliedTime = std::chrono::steady_clock::now();
Ady Abrahambf1349c2020-06-12 14:26:18 -070091 if (mTransactionStart == Scheduler::TransactionStart::Normal) return;
92 mTransactionStart = Scheduler::TransactionStart::Normal;
Alec Mourib488afa2019-05-23 10:22:24 -070093 updateOffsets();
94}
95
96void VSyncModulator::onRefreshRateChangeInitiated() {
97 if (mRefreshRateChangePending) {
98 return;
99 }
100 mRefreshRateChangePending = true;
101 updateOffsets();
102}
103
104void VSyncModulator::onRefreshRateChangeCompleted() {
105 if (!mRefreshRateChangePending) {
106 return;
107 }
108 mRefreshRateChangePending = false;
109 updateOffsets();
110}
111
112void VSyncModulator::onRefreshed(bool usedRenderEngine) {
113 bool updateOffsetsNeeded = false;
Alec Mourif792cfe2020-06-05 13:11:23 -0700114
Ady Abrahambf1349c2020-06-12 14:26:18 -0700115 // Apply a margin to account for potential data races
Alec Mourif792cfe2020-06-05 13:11:23 -0700116 // This might make us stay in early offsets for one
117 // additional frame but it's better to be conservative here.
Ady Abrahambf1349c2020-06-12 14:26:18 -0700118 if ((mEarlyTxnStartTime.load() + MARGIN_FOR_TX_APPLY) < mTxnAppliedTime.load()) {
Alec Mourif792cfe2020-06-05 13:11:23 -0700119 if (mRemainingEarlyFrameCount > 0) {
120 mRemainingEarlyFrameCount--;
121 updateOffsetsNeeded = true;
122 }
Alec Mourib488afa2019-05-23 10:22:24 -0700123 }
124 if (usedRenderEngine) {
125 mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
126 updateOffsetsNeeded = true;
127 } else if (mRemainingRenderEngineUsageCount > 0) {
128 mRemainingRenderEngineUsageCount--;
129 updateOffsetsNeeded = true;
130 }
131 if (updateOffsetsNeeded) {
132 updateOffsets();
133 }
134}
135
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700136VSyncModulator::Offsets VSyncModulator::getOffsets() const {
Alec Mourid7599d82019-05-22 19:58:00 -0700137 std::lock_guard<std::mutex> lock(mMutex);
Alec Mourib656aed2019-06-21 16:27:05 -0700138 return mOffsets;
Alec Mourid7599d82019-05-22 19:58:00 -0700139}
140
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700141const VSyncModulator::Offsets& VSyncModulator::getNextOffsets() const {
Alec Mourib488afa2019-05-23 10:22:24 -0700142 // Early offsets are used if we're in the middle of a refresh rate
143 // change, or if we recently begin a transaction.
Ady Abrahambf1349c2020-06-12 14:26:18 -0700144 if (mExplicitEarlyWakeup || mTransactionStart == Scheduler::TransactionStart::EarlyEnd ||
145 mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700146 return mOffsetsConfig.early;
Alec Mourib488afa2019-05-23 10:22:24 -0700147 } else if (mRemainingRenderEngineUsageCount > 0) {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700148 return mOffsetsConfig.earlyGl;
Alec Mourib488afa2019-05-23 10:22:24 -0700149 } else {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700150 return mOffsetsConfig.late;
Alec Mourib488afa2019-05-23 10:22:24 -0700151 }
152}
153
154void VSyncModulator::updateOffsets() {
Alec Mourid7599d82019-05-22 19:58:00 -0700155 std::lock_guard<std::mutex> lock(mMutex);
156 updateOffsetsLocked();
157}
158
159void VSyncModulator::updateOffsetsLocked() {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700160 const Offsets& offsets = getNextOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -0700161
Ady Abrahambf1349c2020-06-12 14:26:18 -0700162 mPhaseOffsetControl.setPhaseOffset(mSfConnectionHandle, offsets.sf);
163 mPhaseOffsetControl.setPhaseOffset(mAppConnectionHandle, offsets.app);
Alec Mourib488afa2019-05-23 10:22:24 -0700164
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700165 mOffsets = offsets;
Ady Abraham11b6a702019-06-27 11:24:19 -0700166
Alec Mourid7599d82019-05-22 19:58:00 -0700167 if (!mTraceDetailedInfo) {
168 return;
169 }
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700170
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700171 const bool isEarly = &offsets == &mOffsetsConfig.early;
172 const bool isEarlyGl = &offsets == &mOffsetsConfig.earlyGl;
173 const bool isLate = &offsets == &mOffsetsConfig.late;
174
Ady Abraham2139f732019-11-13 18:56:40 -0800175 ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
176 ATRACE_INT("Vsync-EarlyGLOffsetsOn", isEarlyGl);
177 ATRACE_INT("Vsync-LateOffsetsOn", isLate);
Alec Mourid7599d82019-05-22 19:58:00 -0700178}
179
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700180} // namespace android::scheduler
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800181
182// TODO(b/129481165): remove the #pragma below and fix conversion issues
183#pragma clang diagnostic pop // ignored "-Wconversion"