blob: af8f445b3023289382a4c0b5778c89b9d8090f21 [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
17#include "VSyncModulator.h"
18
19#include <cinttypes>
20#include <mutex>
21
22namespace android {
23
24void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
25 nsecs_t thresholdForNextVsync) {
26 mEarlyOffsets = early;
27 mEarlyGlOffsets = earlyGl;
28 mLateOffsets = late;
29 mThresholdForNextVsync = thresholdForNextVsync;
30
31 if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
32 mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
33 }
34
35 if (mAppConnectionHandle && late.app != mOffsets.load().app) {
36 mScheduler->setPhaseOffset(mAppConnectionHandle, late.app);
37 }
38 mOffsets = late;
39}
40
41void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
42 if (transactionStart == Scheduler::TransactionStart::EARLY) {
43 mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
44 }
45
46 // An early transaction stays an early transaction.
47 if (transactionStart == mTransactionStart ||
48 mTransactionStart == Scheduler::TransactionStart::EARLY) {
49 return;
50 }
51 mTransactionStart = transactionStart;
52 updateOffsets();
53}
54
55void VSyncModulator::onTransactionHandled() {
56 if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
57 mTransactionStart = Scheduler::TransactionStart::NORMAL;
58 updateOffsets();
59}
60
61void VSyncModulator::onRefreshRateChangeInitiated() {
62 if (mRefreshRateChangePending) {
63 return;
64 }
65 mRefreshRateChangePending = true;
66 updateOffsets();
67}
68
69void VSyncModulator::onRefreshRateChangeCompleted() {
70 if (!mRefreshRateChangePending) {
71 return;
72 }
73 mRefreshRateChangePending = false;
74 updateOffsets();
75}
76
77void VSyncModulator::onRefreshed(bool usedRenderEngine) {
78 bool updateOffsetsNeeded = false;
79 if (mRemainingEarlyFrameCount > 0) {
80 mRemainingEarlyFrameCount--;
81 updateOffsetsNeeded = true;
82 }
83 if (usedRenderEngine) {
84 mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
85 updateOffsetsNeeded = true;
86 } else if (mRemainingRenderEngineUsageCount > 0) {
87 mRemainingRenderEngineUsageCount--;
88 updateOffsetsNeeded = true;
89 }
90 if (updateOffsetsNeeded) {
91 updateOffsets();
92 }
93}
94
95VSyncModulator::Offsets VSyncModulator::getOffsets() {
96 // Early offsets are used if we're in the middle of a refresh rate
97 // change, or if we recently begin a transaction.
98 if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
99 mRefreshRateChangePending) {
100 return mEarlyOffsets;
101 } else if (mRemainingRenderEngineUsageCount > 0) {
102 return mEarlyGlOffsets;
103 } else {
104 return mLateOffsets;
105 }
106}
107
108void VSyncModulator::updateOffsets() {
109 const Offsets desired = getOffsets();
110 const Offsets current = mOffsets;
111
112 bool changed = false;
113 if (desired.sf != current.sf) {
114 if (mSfConnectionHandle != nullptr) {
115 mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
116 } else {
117 mSfEventThread->setPhaseOffset(desired.sf);
118 }
119 changed = true;
120 }
121 if (desired.app != current.app) {
122 if (mAppConnectionHandle != nullptr) {
123 mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
124 } else {
125 mAppEventThread->setPhaseOffset(desired.app);
126 }
127 changed = true;
128 }
129
130 if (changed) {
131 mOffsets = desired;
132 }
133}
134
135} // namespace android