| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 1 | /* | 
|  | 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 Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 17 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS | 
|  | 18 |  | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 19 | #include "VSyncModulator.h" | 
|  | 20 |  | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 21 | #include <cutils/properties.h> | 
|  | 22 | #include <utils/Trace.h> | 
|  | 23 |  | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 24 | #include <cinttypes> | 
|  | 25 | #include <mutex> | 
|  | 26 |  | 
|  | 27 | namespace android { | 
|  | 28 |  | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 29 | using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; | 
|  | 30 | VSyncModulator::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 Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 39 | void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late, | 
|  | 40 | nsecs_t thresholdForNextVsync) { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 41 | 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 Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 45 | mThresholdForNextVsync = thresholdForNextVsync; | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 46 | updateOffsetsLocked(); | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 47 | } | 
|  | 48 |  | 
|  | 49 | void 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 |  | 
|  | 63 | void VSyncModulator::onTransactionHandled() { | 
|  | 64 | if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return; | 
|  | 65 | mTransactionStart = Scheduler::TransactionStart::NORMAL; | 
|  | 66 | updateOffsets(); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | void VSyncModulator::onRefreshRateChangeInitiated() { | 
|  | 70 | if (mRefreshRateChangePending) { | 
|  | 71 | return; | 
|  | 72 | } | 
|  | 73 | mRefreshRateChangePending = true; | 
|  | 74 | updateOffsets(); | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | void VSyncModulator::onRefreshRateChangeCompleted() { | 
|  | 78 | if (!mRefreshRateChangePending) { | 
|  | 79 | return; | 
|  | 80 | } | 
|  | 81 | mRefreshRateChangePending = false; | 
|  | 82 | updateOffsets(); | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | void 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 |  | 
|  | 103 | VSyncModulator::Offsets VSyncModulator::getOffsets() { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 104 | std::lock_guard<std::mutex> lock(mMutex); | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 105 | return mOffsets; | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 106 | } | 
|  | 107 |  | 
|  | 108 | VSyncModulator::Offsets VSyncModulator::getNextOffsets() { | 
|  | 109 | return mOffsetMap.at(getNextOffsetType()); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() { | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 113 | // 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 Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 117 | return OffsetType::Early; | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 118 | } else if (mRemainingRenderEngineUsageCount > 0) { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 119 | return OffsetType::EarlyGl; | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 120 | } else { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 121 | return OffsetType::Late; | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 122 | } | 
|  | 123 | } | 
|  | 124 |  | 
|  | 125 | void VSyncModulator::updateOffsets() { | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 126 | std::lock_guard<std::mutex> lock(mMutex); | 
|  | 127 | updateOffsetsLocked(); | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | void VSyncModulator::updateOffsetsLocked() { | 
|  | 131 | const Offsets desired = getNextOffsets(); | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 132 |  | 
| Ady Abraham | 11b6a70 | 2019-06-27 11:24:19 -0700 | [diff] [blame] | 133 | if (mSfConnectionHandle != nullptr) { | 
|  | 134 | mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf); | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 135 | } | 
|  | 136 |  | 
| Ady Abraham | 11b6a70 | 2019-06-27 11:24:19 -0700 | [diff] [blame] | 137 | if (mAppConnectionHandle != nullptr) { | 
|  | 138 | mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app); | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 139 | } | 
| Ady Abraham | 11b6a70 | 2019-06-27 11:24:19 -0700 | [diff] [blame] | 140 |  | 
|  | 141 | flushOffsets(); | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 142 | } | 
|  | 143 |  | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 144 | void VSyncModulator::flushOffsets() { | 
|  | 145 | OffsetType type = getNextOffsetType(); | 
|  | 146 | mOffsets = mOffsetMap.at(type); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 147 | if (!mTraceDetailedInfo) { | 
|  | 148 | return; | 
|  | 149 | } | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 150 | ATRACE_INT("Vsync-EarlyOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 151 | mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 152 | ATRACE_INT("Vsync-EarlyGLOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 153 | mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 154 | ATRACE_INT("Vsync-LateOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 155 | mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 156 | ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 157 | mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 158 | ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 159 | mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 160 | ATRACE_INT("Vsync-HighFpsLateOffsetsOn", | 
| Alec Mouri | b656aed | 2019-06-21 16:27:05 -0700 | [diff] [blame] | 161 | mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late); | 
| Alec Mouri | d7599d8 | 2019-05-22 19:58:00 -0700 | [diff] [blame] | 162 | } | 
|  | 163 |  | 
| Alec Mouri | b488afa | 2019-05-23 10:22:24 -0700 | [diff] [blame] | 164 | } // namespace android |