blob: 747032be0d6d4f290581194a73e15f885bd32c15 [file] [log] [blame]
Ana Krulec241cf832018-08-10 15:03:23 -07001/*
2 * Copyright 2018 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
Midas Chienbc5f22f2018-08-16 15:51:19 +080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Ana Krulec241cf832018-08-10 15:03:23 -070019#include "DispSyncSource.h"
20
Ana Krulec072233f2018-08-10 15:03:23 -070021#include <android-base/stringprintf.h>
Ana Krulec241cf832018-08-10 15:03:23 -070022#include <utils/Trace.h>
Ana Krulec072233f2018-08-10 15:03:23 -070023#include <mutex>
Ana Krulec241cf832018-08-10 15:03:23 -070024
Ana Krulec241cf832018-08-10 15:03:23 -070025#include "EventThread.h"
Rachel Leeef2e21f2022-02-01 14:51:34 -080026#include "VSyncTracker.h"
Ady Abraham8cb21882020-08-26 18:22:05 -070027#include "VsyncController.h"
Ana Krulec241cf832018-08-10 15:03:23 -070028
Ady Abraham9c53ee72020-07-22 21:16:18 -070029namespace android::scheduler {
Ady Abraham5e7371c2020-03-24 14:47:24 -070030using base::StringAppendF;
Ady Abraham9c53ee72020-07-22 21:16:18 -070031using namespace std::chrono_literals;
Ana Krulec241cf832018-08-10 15:03:23 -070032
Ady Abraham9c53ee72020-07-22 21:16:18 -070033class CallbackRepeater {
34public:
35 CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
36 std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
37 std::chrono::nanoseconds notBefore)
38 : mName(name),
39 mCallback(cb),
40 mRegistration(dispatch,
41 std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
42 std::placeholders::_2, std::placeholders::_3),
43 mName),
44 mStarted(false),
45 mWorkDuration(workDuration),
46 mReadyDuration(readyDuration),
47 mLastCallTime(notBefore) {}
48
49 ~CallbackRepeater() {
50 std::lock_guard lock(mMutex);
51 mRegistration.cancel();
52 }
53
54 void start(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) {
55 std::lock_guard lock(mMutex);
56 mStarted = true;
57 mWorkDuration = workDuration;
58 mReadyDuration = readyDuration;
59
60 auto const scheduleResult =
61 mRegistration.schedule({.workDuration = mWorkDuration.count(),
62 .readyDuration = mReadyDuration.count(),
63 .earliestVsync = mLastCallTime.count()});
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070064 LOG_ALWAYS_FATAL_IF((!scheduleResult.has_value()), "Error scheduling callback");
Ady Abraham9c53ee72020-07-22 21:16:18 -070065 }
66
67 void stop() {
68 std::lock_guard lock(mMutex);
69 LOG_ALWAYS_FATAL_IF(!mStarted, "DispSyncInterface misuse: callback already stopped");
70 mStarted = false;
71 mRegistration.cancel();
72 }
73
74 void dump(std::string& result) const {
75 std::lock_guard lock(mMutex);
76 const auto relativeLastCallTime =
77 mLastCallTime - std::chrono::steady_clock::now().time_since_epoch();
78 StringAppendF(&result, "\t%s: ", mName.c_str());
79 StringAppendF(&result, "mWorkDuration=%.2f mReadyDuration=%.2f last vsync time ",
80 mWorkDuration.count() / 1e6f, mReadyDuration.count() / 1e6f);
81 StringAppendF(&result, "%.2fms relative to now (%s)\n", relativeLastCallTime.count() / 1e6f,
82 mStarted ? "running" : "stopped");
83 }
84
85private:
86 void callback(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
87 {
88 std::lock_guard lock(mMutex);
89 mLastCallTime = std::chrono::nanoseconds(vsyncTime);
90 }
91
92 mCallback(vsyncTime, wakeupTime, readyTime);
93
94 {
95 std::lock_guard lock(mMutex);
96 if (!mStarted) {
97 return;
98 }
99 auto const scheduleResult =
100 mRegistration.schedule({.workDuration = mWorkDuration.count(),
101 .readyDuration = mReadyDuration.count(),
102 .earliestVsync = vsyncTime});
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700103 LOG_ALWAYS_FATAL_IF(!scheduleResult.has_value(), "Error rescheduling callback");
Ady Abraham9c53ee72020-07-22 21:16:18 -0700104 }
105 }
106
107 const std::string mName;
108 scheduler::VSyncDispatch::Callback mCallback;
109
110 mutable std::mutex mMutex;
111 VSyncCallbackRegistration mRegistration GUARDED_BY(mMutex);
112 bool mStarted GUARDED_BY(mMutex) = false;
113 std::chrono::nanoseconds mWorkDuration GUARDED_BY(mMutex) = 0ns;
114 std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex) = 0ns;
115 std::chrono::nanoseconds mLastCallTime GUARDED_BY(mMutex) = 0ns;
116};
117
Rachel Leeef2e21f2022-02-01 14:51:34 -0800118DispSyncSource::DispSyncSource(VSyncDispatch& vSyncDispatch, VSyncTracker& vSyncTracker,
Ady Abraham9c53ee72020-07-22 21:16:18 -0700119 std::chrono::nanoseconds workDuration,
120 std::chrono::nanoseconds readyDuration, bool traceVsync,
Ana Krulec241cf832018-08-10 15:03:23 -0700121 const char* name)
122 : mName(name),
Ady Abraham50204dd2019-07-19 15:47:11 -0700123 mValue(base::StringPrintf("VSYNC-%s", name), 0),
Ana Krulec241cf832018-08-10 15:03:23 -0700124 mTraceVsync(traceVsync),
Ana Krulec072233f2018-08-10 15:03:23 -0700125 mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
Rachel Leeef2e21f2022-02-01 14:51:34 -0800126 mVSyncTracker(vSyncTracker),
Ady Abraham9c53ee72020-07-22 21:16:18 -0700127 mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
128 mReadyDuration(readyDuration) {
129 mCallbackRepeater =
130 std::make_unique<CallbackRepeater>(vSyncDispatch,
131 std::bind(&DispSyncSource::onVsyncCallback, this,
132 std::placeholders::_1,
133 std::placeholders::_2,
134 std::placeholders::_3),
135 name, workDuration, readyDuration,
136 std::chrono::steady_clock::now().time_since_epoch());
137}
138
139DispSyncSource::~DispSyncSource() = default;
Ana Krulec241cf832018-08-10 15:03:23 -0700140
141void DispSyncSource::setVSyncEnabled(bool enable) {
Ana Krulec072233f2018-08-10 15:03:23 -0700142 std::lock_guard lock(mVsyncMutex);
Ana Krulec241cf832018-08-10 15:03:23 -0700143 if (enable) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700144 mCallbackRepeater->start(mWorkDuration, mReadyDuration);
Ana Krulec072233f2018-08-10 15:03:23 -0700145 // ATRACE_INT(mVsyncOnLabel.c_str(), 1);
Ana Krulec241cf832018-08-10 15:03:23 -0700146 } else {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700147 mCallbackRepeater->stop();
Ana Krulec072233f2018-08-10 15:03:23 -0700148 // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
Ana Krulec241cf832018-08-10 15:03:23 -0700149 }
150 mEnabled = enable;
151}
152
153void DispSyncSource::setCallback(VSyncSource::Callback* callback) {
Ana Krulec072233f2018-08-10 15:03:23 -0700154 std::lock_guard lock(mCallbackMutex);
Ana Krulec241cf832018-08-10 15:03:23 -0700155 mCallback = callback;
156}
157
Ady Abraham9c53ee72020-07-22 21:16:18 -0700158void DispSyncSource::setDuration(std::chrono::nanoseconds workDuration,
159 std::chrono::nanoseconds readyDuration) {
Ana Krulec072233f2018-08-10 15:03:23 -0700160 std::lock_guard lock(mVsyncMutex);
Ady Abraham9c53ee72020-07-22 21:16:18 -0700161 mWorkDuration = workDuration;
162 mReadyDuration = readyDuration;
Ana Krulec241cf832018-08-10 15:03:23 -0700163
164 // If we're not enabled, we don't need to mess with the listeners
165 if (!mEnabled) {
166 return;
167 }
168
Ady Abraham9c53ee72020-07-22 21:16:18 -0700169 mCallbackRepeater->start(mWorkDuration, mReadyDuration);
Ana Krulec241cf832018-08-10 15:03:23 -0700170}
171
Ady Abraham9c53ee72020-07-22 21:16:18 -0700172void DispSyncSource::onVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime,
173 nsecs_t readyTime) {
Ana Krulec241cf832018-08-10 15:03:23 -0700174 VSyncSource::Callback* callback;
175 {
Ana Krulec072233f2018-08-10 15:03:23 -0700176 std::lock_guard lock(mCallbackMutex);
Ana Krulec241cf832018-08-10 15:03:23 -0700177 callback = mCallback;
Alec Mourid7599d82019-05-22 19:58:00 -0700178 }
Ana Krulec241cf832018-08-10 15:03:23 -0700179
Alec Mourid7599d82019-05-22 19:58:00 -0700180 if (mTraceVsync) {
181 mValue = (mValue + 1) % 2;
Ana Krulec241cf832018-08-10 15:03:23 -0700182 }
183
184 if (callback != nullptr) {
Rachel Leef16da3c2022-01-20 13:57:18 -0800185 callback->onVSyncEvent(targetWakeupTime, {vsyncTime, readyTime});
Ana Krulec241cf832018-08-10 15:03:23 -0700186 }
187}
188
Rachel Leeef2e21f2022-02-01 14:51:34 -0800189VSyncSource::VSyncData DispSyncSource::getLatestVSyncData() const {
190 std::lock_guard lock(mVsyncMutex);
191 nsecs_t expectedPresentTime = mVSyncTracker.nextAnticipatedVSyncTimeFrom(
192 systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
193 nsecs_t deadline = expectedPresentTime - mWorkDuration.get().count() - mReadyDuration.count();
194 return {expectedPresentTime, deadline};
195}
196
Ady Abraham5e7371c2020-03-24 14:47:24 -0700197void DispSyncSource::dump(std::string& result) const {
198 std::lock_guard lock(mVsyncMutex);
199 StringAppendF(&result, "DispSyncSource: %s(%s)\n", mName, mEnabled ? "enabled" : "disabled");
Ady Abraham5e7371c2020-03-24 14:47:24 -0700200}
201
Ady Abraham9c53ee72020-07-22 21:16:18 -0700202} // namespace android::scheduler