blob: 381308ab34d8973081b58b4709161e9c74efe7eb [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
Alec Mourid7599d82019-05-22 19:58:00 -070017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Alec Mourib488afa2019-05-23 10:22:24 -070019#include "VSyncModulator.h"
20
Alec Mourid7599d82019-05-22 19:58:00 -070021#include <cutils/properties.h>
22#include <utils/Trace.h>
23
Alec Mourib488afa2019-05-23 10:22:24 -070024#include <cinttypes>
25#include <mutex>
26
27namespace android {
28
Alec Mourid7599d82019-05-22 19:58:00 -070029using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
30VSyncModulator::VSyncModulator() {
31 char value[PROPERTY_VALUE_MAX];
32 property_get("debug.sf.vsync_trace_detailed_info", value, "0");
33 mTraceDetailedInfo = atoi(value);
34 // Populate the offset map with some default offsets.
35 const Offsets defaultOffsets = {RefreshRateType::DEFAULT, 0, 0};
36 setPhaseOffsets(defaultOffsets, defaultOffsets, defaultOffsets, 0);
37}
38
Alec Mourib488afa2019-05-23 10:22:24 -070039void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
40 nsecs_t thresholdForNextVsync) {
Alec Mourid7599d82019-05-22 19:58:00 -070041 std::lock_guard<std::mutex> lock(mMutex);
42 mOffsetMap.insert_or_assign(OffsetType::Early, early);
43 mOffsetMap.insert_or_assign(OffsetType::EarlyGl, earlyGl);
44 mOffsetMap.insert_or_assign(OffsetType::Late, late);
Alec Mourib488afa2019-05-23 10:22:24 -070045 mThresholdForNextVsync = thresholdForNextVsync;
Alec Mourid7599d82019-05-22 19:58:00 -070046 updateOffsetsLocked();
Alec Mourib488afa2019-05-23 10:22:24 -070047}
48
49void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
50 if (transactionStart == Scheduler::TransactionStart::EARLY) {
51 mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
52 }
53
54 // An early transaction stays an early transaction.
55 if (transactionStart == mTransactionStart ||
56 mTransactionStart == Scheduler::TransactionStart::EARLY) {
57 return;
58 }
59 mTransactionStart = transactionStart;
60 updateOffsets();
61}
62
63void VSyncModulator::onTransactionHandled() {
64 if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
65 mTransactionStart = Scheduler::TransactionStart::NORMAL;
66 updateOffsets();
67}
68
69void VSyncModulator::onRefreshRateChangeInitiated() {
70 if (mRefreshRateChangePending) {
71 return;
72 }
73 mRefreshRateChangePending = true;
74 updateOffsets();
75}
76
77void VSyncModulator::onRefreshRateChangeCompleted() {
78 if (!mRefreshRateChangePending) {
79 return;
80 }
81 mRefreshRateChangePending = false;
82 updateOffsets();
83}
84
85void VSyncModulator::onRefreshed(bool usedRenderEngine) {
86 bool updateOffsetsNeeded = false;
87 if (mRemainingEarlyFrameCount > 0) {
88 mRemainingEarlyFrameCount--;
89 updateOffsetsNeeded = true;
90 }
91 if (usedRenderEngine) {
92 mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
93 updateOffsetsNeeded = true;
94 } else if (mRemainingRenderEngineUsageCount > 0) {
95 mRemainingRenderEngineUsageCount--;
96 updateOffsetsNeeded = true;
97 }
98 if (updateOffsetsNeeded) {
99 updateOffsets();
100 }
101}
102
103VSyncModulator::Offsets VSyncModulator::getOffsets() {
Alec Mourid7599d82019-05-22 19:58:00 -0700104 std::lock_guard<std::mutex> lock(mMutex);
105 return mOffsetMap.at(mOffsetType);
106}
107
108VSyncModulator::Offsets VSyncModulator::getNextOffsets() {
109 return mOffsetMap.at(getNextOffsetType());
110}
111
112VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() {
Alec Mourib488afa2019-05-23 10:22:24 -0700113 // Early offsets are used if we're in the middle of a refresh rate
114 // change, or if we recently begin a transaction.
115 if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
116 mRefreshRateChangePending) {
Alec Mourid7599d82019-05-22 19:58:00 -0700117 return OffsetType::Early;
Alec Mourib488afa2019-05-23 10:22:24 -0700118 } else if (mRemainingRenderEngineUsageCount > 0) {
Alec Mourid7599d82019-05-22 19:58:00 -0700119 return OffsetType::EarlyGl;
Alec Mourib488afa2019-05-23 10:22:24 -0700120 } else {
Alec Mourid7599d82019-05-22 19:58:00 -0700121 return OffsetType::Late;
Alec Mourib488afa2019-05-23 10:22:24 -0700122 }
123}
124
125void VSyncModulator::updateOffsets() {
Alec Mourid7599d82019-05-22 19:58:00 -0700126 std::lock_guard<std::mutex> lock(mMutex);
127 updateOffsetsLocked();
128}
129
130void VSyncModulator::updateOffsetsLocked() {
131 const Offsets desired = getNextOffsets();
132 const Offsets current = mOffsetMap.at(mOffsetType);
Alec Mourib488afa2019-05-23 10:22:24 -0700133
134 bool changed = false;
135 if (desired.sf != current.sf) {
136 if (mSfConnectionHandle != nullptr) {
137 mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
138 } else {
139 mSfEventThread->setPhaseOffset(desired.sf);
140 }
141 changed = true;
142 }
143 if (desired.app != current.app) {
144 if (mAppConnectionHandle != nullptr) {
145 mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
146 } else {
147 mAppEventThread->setPhaseOffset(desired.app);
148 }
149 changed = true;
150 }
151
152 if (changed) {
Alec Mourid7599d82019-05-22 19:58:00 -0700153 updateOffsetType();
Alec Mourib488afa2019-05-23 10:22:24 -0700154 }
155}
156
Alec Mourid7599d82019-05-22 19:58:00 -0700157void VSyncModulator::updateOffsetType() {
158 mOffsetType = getNextOffsetType();
159 if (!mTraceDetailedInfo) {
160 return;
161 }
162 OffsetType type = mOffsetType;
163 Offsets offsets = mOffsetMap.at(type);
164 ATRACE_INT("Vsync-EarlyOffsetsOn",
165 offsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early);
166 ATRACE_INT("Vsync-EarlyGLOffsetsOn",
167 offsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl);
168 ATRACE_INT("Vsync-LateOffsetsOn",
169 offsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late);
170 ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn",
171 offsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early);
172 ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn",
173 offsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl);
174 ATRACE_INT("Vsync-HighFpsLateOffsetsOn",
175 offsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late);
176}
177
Alec Mourib488afa2019-05-23 10:22:24 -0700178} // namespace android