blob: 194d80883615b6f74cecb2c5691b3d9b1c813d03 [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
Ady Abraham8287e852020-08-12 14:44:58 -070038VsyncModulator::VsyncModulator(const VsyncConfigSet& config, Now now)
39 : mVsyncConfigSet(config),
Dominik Laskowski08d05c22020-07-22 00:05:08 -070040 mNow(now),
41 mTraceDetailedInfo(base::GetBoolProperty("debug.sf.vsync_trace_detailed_info", false)) {}
42
Ady Abraham8287e852020-08-12 14:44:58 -070043VsyncModulator::VsyncConfig VsyncModulator::setVsyncConfigSet(const VsyncConfigSet& config) {
Alec Mourid7599d82019-05-22 19:58:00 -070044 std::lock_guard<std::mutex> lock(mMutex);
Ady Abraham8287e852020-08-12 14:44:58 -070045 mVsyncConfigSet = config;
46 return updateVsyncConfigLocked();
Alec Mourib488afa2019-05-23 10:22:24 -070047}
48
Ady Abraham8287e852020-08-12 14:44:58 -070049VsyncModulator::VsyncConfigOpt VsyncModulator::setTransactionSchedule(
50 TransactionSchedule schedule) {
Dominik Laskowski08d05c22020-07-22 00:05:08 -070051 switch (schedule) {
52 case Schedule::EarlyStart:
Ady Abraham8cbd3072021-03-15 16:39:06 -070053 ALOGW_IF(mEarlyWakeup, "%s: Duplicate EarlyStart", __FUNCTION__);
54 mEarlyWakeup = true;
Ady Abrahambf1349c2020-06-12 14:26:18 -070055 break;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070056 case Schedule::EarlyEnd:
Ady Abraham8cbd3072021-03-15 16:39:06 -070057 ALOGW_IF(!mEarlyWakeup, "%s: Unexpected EarlyEnd", __FUNCTION__);
58 mEarlyWakeup = false;
Ady Abrahambf1349c2020-06-12 14:26:18 -070059 break;
Dominik Laskowski08d05c22020-07-22 00:05:08 -070060 case Schedule::Late:
Ady Abraham8cbd3072021-03-15 16:39:06 -070061 // No change to mEarlyWakeup for non-explicit states.
Ady Abrahambf1349c2020-06-12 14:26:18 -070062 break;
63 }
64
65 if (mTraceDetailedInfo) {
Ady Abraham8cbd3072021-03-15 16:39:06 -070066 ATRACE_INT("mEarlyWakeup", mEarlyWakeup);
Ady Abrahambf1349c2020-06-12 14:26:18 -070067 }
68
Ady Abraham8cbd3072021-03-15 16:39:06 -070069 if (!mEarlyWakeup && schedule == Schedule::EarlyEnd) {
Dominik Laskowski08d05c22020-07-22 00:05:08 -070070 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;
Ady Abraham8287e852020-08-12 14:44:58 -070079 return updateVsyncConfig();
Alec Mourib488afa2019-05-23 10:22:24 -070080}
81
Ady Abraham8287e852020-08-12 14:44:58 -070082VsyncModulator::VsyncConfigOpt VsyncModulator::onTransactionCommit() {
Dominik Laskowski08d05c22020-07-22 00:05:08 -070083 mLastTransactionCommitTime = mNow();
84 if (mTransactionSchedule == Schedule::Late) return std::nullopt;
85 mTransactionSchedule = Schedule::Late;
Ady Abraham8287e852020-08-12 14:44:58 -070086 return updateVsyncConfig();
Alec Mourib488afa2019-05-23 10:22:24 -070087}
88
Ady Abraham8287e852020-08-12 14:44:58 -070089VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeInitiated() {
Dominik Laskowski08d05c22020-07-22 00:05:08 -070090 if (mRefreshRateChangePending) return std::nullopt;
Alec Mourib488afa2019-05-23 10:22:24 -070091 mRefreshRateChangePending = true;
Ady Abraham8287e852020-08-12 14:44:58 -070092 return updateVsyncConfig();
Alec Mourib488afa2019-05-23 10:22:24 -070093}
94
Ady Abraham8287e852020-08-12 14:44:58 -070095VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeCompleted() {
Dominik Laskowski08d05c22020-07-22 00:05:08 -070096 if (!mRefreshRateChangePending) return std::nullopt;
Alec Mourib488afa2019-05-23 10:22:24 -070097 mRefreshRateChangePending = false;
Ady Abraham8287e852020-08-12 14:44:58 -070098 return updateVsyncConfig();
Alec Mourib488afa2019-05-23 10:22:24 -070099}
100
Ady Abraham8287e852020-08-12 14:44:58 -0700101VsyncModulator::VsyncConfigOpt 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;
Ady Abraham8287e852020-08-12 14:44:58 -0700120 return updateVsyncConfig();
Alec Mourib488afa2019-05-23 10:22:24 -0700121}
122
Ady Abraham8287e852020-08-12 14:44:58 -0700123VsyncModulator::VsyncConfig VsyncModulator::getVsyncConfig() const {
Alec Mourid7599d82019-05-22 19:58:00 -0700124 std::lock_guard<std::mutex> lock(mMutex);
Ady Abraham8287e852020-08-12 14:44:58 -0700125 return mVsyncConfig;
Alec Mourid7599d82019-05-22 19:58:00 -0700126}
127
Ady Abraham8287e852020-08-12 14:44:58 -0700128const VsyncModulator::VsyncConfig& VsyncModulator::getNextVsyncConfig() 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.
Ady Abraham8cbd3072021-03-15 16:39:06 -0700131 if (mEarlyWakeup || mTransactionSchedule == Schedule::EarlyEnd || mEarlyTransactionFrames > 0 ||
132 mRefreshRateChangePending) {
Ady Abraham8287e852020-08-12 14:44:58 -0700133 return mVsyncConfigSet.early;
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700134 } else if (mEarlyGpuFrames > 0) {
Ady Abraham8287e852020-08-12 14:44:58 -0700135 return mVsyncConfigSet.earlyGpu;
Alec Mourib488afa2019-05-23 10:22:24 -0700136 } else {
Ady Abraham8287e852020-08-12 14:44:58 -0700137 return mVsyncConfigSet.late;
Alec Mourib488afa2019-05-23 10:22:24 -0700138 }
139}
140
Ady Abraham8287e852020-08-12 14:44:58 -0700141VsyncModulator::VsyncConfig VsyncModulator::updateVsyncConfig() {
Alec Mourid7599d82019-05-22 19:58:00 -0700142 std::lock_guard<std::mutex> lock(mMutex);
Ady Abraham8287e852020-08-12 14:44:58 -0700143 return updateVsyncConfigLocked();
Alec Mourid7599d82019-05-22 19:58:00 -0700144}
145
Ady Abraham8287e852020-08-12 14:44:58 -0700146VsyncModulator::VsyncConfig VsyncModulator::updateVsyncConfigLocked() {
147 const VsyncConfig& offsets = getNextVsyncConfig();
148 mVsyncConfig = offsets;
Ady Abraham11b6a702019-06-27 11:24:19 -0700149
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700150 if (mTraceDetailedInfo) {
Ady Abraham8287e852020-08-12 14:44:58 -0700151 const bool isEarly = &offsets == &mVsyncConfigSet.early;
152 const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
153 const bool isLate = &offsets == &mVsyncConfigSet.late;
Dominik Laskowski08d05c22020-07-22 00:05:08 -0700154
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