blob: 7a1b7e469545ef0eb4ad9fa80349023de9b29cd8 [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
Dominik Laskowski08d05c22020-07-22 00:05:08 -070019#undef LOG_TAG
20#define LOG_TAG "VsyncModulator"
21
Dominik Laskowskia93a5312020-07-23 15:10:03 -070022#include "VsyncModulator.h"
Alec Mourib488afa2019-05-23 10:22:24 -070023
Dominik Laskowski08d05c22020-07-22 00:05:08 -070024#include <android-base/properties.h>
25#include <log/log.h>
Alec Mourid7599d82019-05-22 19:58:00 -070026#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 Laskowski08d05c22020-07-22 00:05:08 -070032using namespace std::chrono_literals;
33
Dominik Laskowskieddeda12019-07-19 11:54:13 -070034namespace android::scheduler {
Alec Mourib488afa2019-05-23 10:22:24 -070035
Dominik Laskowski08d05c22020-07-22 00:05:08 -070036const std::chrono::nanoseconds VsyncModulator::MIN_EARLY_TRANSACTION_TIME = 1ms;
Alec Mourid7599d82019-05-22 19:58:00 -070037
Dominik Laskowski08d05c22020-07-22 00:05:08 -070038VsyncModulator::VsyncModulator(const OffsetsConfig& config, Now now)
39 : mOffsetsConfig(config),
40 mNow(now),
41 mTraceDetailedInfo(base::GetBoolProperty("debug.sf.vsync_trace_detailed_info", false)) {}
42
43VsyncModulator::Offsets VsyncModulator::setPhaseOffsets(const OffsetsConfig& config) {
Alec Mourid7599d82019-05-22 19:58:00 -070044 std::lock_guard<std::mutex> lock(mMutex);
Dominik Laskowskieddeda12019-07-19 11:54:13 -070045 mOffsetsConfig = config;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070046 return updateOffsetsLocked();
Alec Mourib488afa2019-05-23 10:22:24 -070047}
48
Dominik Laskowski08d05c22020-07-22 00:05:08 -070049VsyncModulator::OffsetsOpt VsyncModulator::setTransactionSchedule(TransactionSchedule schedule) {
50 switch (schedule) {
51 case Schedule::EarlyStart:
52 ALOGW_IF(mExplicitEarlyWakeup, "%s: Duplicate EarlyStart", __FUNCTION__);
Ady Abrahambf1349c2020-06-12 14:26:18 -070053 mExplicitEarlyWakeup = true;
54 break;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070055 case Schedule::EarlyEnd:
56 ALOGW_IF(!mExplicitEarlyWakeup, "%s: Unexpected EarlyEnd", __FUNCTION__);
Ady Abrahambf1349c2020-06-12 14:26:18 -070057 mExplicitEarlyWakeup = false;
58 break;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070059 case Schedule::Early:
60 case Schedule::Late:
61 // No change to mExplicitEarlyWakeup for non-explicit states.
Ady Abrahambf1349c2020-06-12 14:26:18 -070062 break;
63 }
64
65 if (mTraceDetailedInfo) {
66 ATRACE_INT("mExplicitEarlyWakeup", mExplicitEarlyWakeup);
67 }
68
Dominik Laskowski08d05c22020-07-22 00:05:08 -070069 if (!mExplicitEarlyWakeup && (schedule == Schedule::Early || schedule == Schedule::EarlyEnd)) {
70 mEarlyTransactionFrames = MIN_EARLY_TRANSACTION_FRAMES;
71 mEarlyTransactionStartTime = mNow();
Alec Mourib488afa2019-05-23 10:22:24 -070072 }
73
74 // An early transaction stays an early transaction.
Dominik Laskowski08d05c22020-07-22 00:05:08 -070075 if (schedule == mTransactionSchedule || mTransactionSchedule == Schedule::EarlyEnd) {
76 return std::nullopt;
Alec Mourib488afa2019-05-23 10:22:24 -070077 }
Dominik Laskowski08d05c22020-07-22 00:05:08 -070078 mTransactionSchedule = schedule;
79 return updateOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -070080}
81
Dominik Laskowski08d05c22020-07-22 00:05:08 -070082VsyncModulator::OffsetsOpt VsyncModulator::onTransactionCommit() {
83 mLastTransactionCommitTime = mNow();
84 if (mTransactionSchedule == Schedule::Late) return std::nullopt;
85 mTransactionSchedule = Schedule::Late;
86 return updateOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -070087}
88
Dominik Laskowski08d05c22020-07-22 00:05:08 -070089VsyncModulator::OffsetsOpt VsyncModulator::onRefreshRateChangeInitiated() {
90 if (mRefreshRateChangePending) return std::nullopt;
Alec Mourib488afa2019-05-23 10:22:24 -070091 mRefreshRateChangePending = true;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070092 return updateOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -070093}
94
Dominik Laskowski08d05c22020-07-22 00:05:08 -070095VsyncModulator::OffsetsOpt VsyncModulator::onRefreshRateChangeCompleted() {
96 if (!mRefreshRateChangePending) return std::nullopt;
Alec Mourib488afa2019-05-23 10:22:24 -070097 mRefreshRateChangePending = false;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070098 return updateOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -070099}
100
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700101VsyncModulator::OffsetsOpt VsyncModulator::onDisplayRefresh(bool usedGpuComposition) {
Alec Mourib488afa2019-05-23 10:22:24 -0700102 bool updateOffsetsNeeded = false;
Alec Mourif792cfe2020-06-05 13:11:23 -0700103
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700104 if (mEarlyTransactionStartTime.load() + MIN_EARLY_TRANSACTION_TIME <=
105 mLastTransactionCommitTime.load()) {
106 if (mEarlyTransactionFrames > 0) {
107 mEarlyTransactionFrames--;
Alec Mourif792cfe2020-06-05 13:11:23 -0700108 updateOffsetsNeeded = true;
109 }
Alec Mourib488afa2019-05-23 10:22:24 -0700110 }
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700111 if (usedGpuComposition) {
112 mEarlyGpuFrames = MIN_EARLY_GPU_FRAMES;
Alec Mourib488afa2019-05-23 10:22:24 -0700113 updateOffsetsNeeded = true;
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700114 } else if (mEarlyGpuFrames > 0) {
115 mEarlyGpuFrames--;
Alec Mourib488afa2019-05-23 10:22:24 -0700116 updateOffsetsNeeded = true;
117 }
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700118
119 if (!updateOffsetsNeeded) return std::nullopt;
120 return updateOffsets();
Alec Mourib488afa2019-05-23 10:22:24 -0700121}
122
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700123VsyncModulator::Offsets VsyncModulator::getOffsets() const {
Alec Mourid7599d82019-05-22 19:58:00 -0700124 std::lock_guard<std::mutex> lock(mMutex);
Alec Mourib656aed2019-06-21 16:27:05 -0700125 return mOffsets;
Alec Mourid7599d82019-05-22 19:58:00 -0700126}
127
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700128const VsyncModulator::Offsets& VsyncModulator::getNextOffsets() const {
Alec Mourib488afa2019-05-23 10:22:24 -0700129 // Early offsets are used if we're in the middle of a refresh rate
130 // change, or if we recently begin a transaction.
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700131 if (mExplicitEarlyWakeup || mTransactionSchedule == Schedule::EarlyEnd ||
132 mEarlyTransactionFrames > 0 || mRefreshRateChangePending) {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700133 return mOffsetsConfig.early;
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700134 } else if (mEarlyGpuFrames > 0) {
135 return mOffsetsConfig.earlyGpu;
Alec Mourib488afa2019-05-23 10:22:24 -0700136 } else {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700137 return mOffsetsConfig.late;
Alec Mourib488afa2019-05-23 10:22:24 -0700138 }
139}
140
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700141VsyncModulator::Offsets VsyncModulator::updateOffsets() {
Alec Mourid7599d82019-05-22 19:58:00 -0700142 std::lock_guard<std::mutex> lock(mMutex);
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700143 return updateOffsetsLocked();
Alec Mourid7599d82019-05-22 19:58:00 -0700144}
145
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700146VsyncModulator::Offsets VsyncModulator::updateOffsetsLocked() {
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700147 const Offsets& offsets = getNextOffsets();
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700148 mOffsets = offsets;
Ady Abraham11b6a702019-06-27 11:24:19 -0700149
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700150 if (mTraceDetailedInfo) {
151 const bool isEarly = &offsets == &mOffsetsConfig.early;
152 const bool isEarlyGpu = &offsets == &mOffsetsConfig.earlyGpu;
153 const bool isLate = &offsets == &mOffsetsConfig.late;
154
155 ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
156 ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
157 ATRACE_INT("Vsync-LateOffsetsOn", isLate);
Alec Mourid7599d82019-05-22 19:58:00 -0700158 }
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700159
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700160 return offsets;
Alec Mourid7599d82019-05-22 19:58:00 -0700161}
162
Dominik Laskowskieddeda12019-07-19 11:54:13 -0700163} // namespace android::scheduler