blob: ce5c31ac19d099f001c55518b0fe37b709ec982b [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"
Ady Abraham8cb21882020-08-26 18:22:05 -070026#include "VsyncController.h"
Ana Krulec241cf832018-08-10 15:03:23 -070027
Ady Abraham9c53ee72020-07-22 21:16:18 -070028namespace android::scheduler {
Ady Abraham5e7371c2020-03-24 14:47:24 -070029using base::StringAppendF;
Ady Abraham9c53ee72020-07-22 21:16:18 -070030using namespace std::chrono_literals;
Ana Krulec241cf832018-08-10 15:03:23 -070031
Ady Abraham9c53ee72020-07-22 21:16:18 -070032class CallbackRepeater {
33public:
34 CallbackRepeater(VSyncDispatch& dispatch, VSyncDispatch::Callback cb, const char* name,
35 std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
36 std::chrono::nanoseconds notBefore)
37 : mName(name),
38 mCallback(cb),
39 mRegistration(dispatch,
40 std::bind(&CallbackRepeater::callback, this, std::placeholders::_1,
41 std::placeholders::_2, std::placeholders::_3),
42 mName),
43 mStarted(false),
44 mWorkDuration(workDuration),
45 mReadyDuration(readyDuration),
46 mLastCallTime(notBefore) {}
47
48 ~CallbackRepeater() {
49 std::lock_guard lock(mMutex);
50 mRegistration.cancel();
51 }
52
53 void start(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) {
54 std::lock_guard lock(mMutex);
55 mStarted = true;
56 mWorkDuration = workDuration;
57 mReadyDuration = readyDuration;
58
59 auto const scheduleResult =
60 mRegistration.schedule({.workDuration = mWorkDuration.count(),
61 .readyDuration = mReadyDuration.count(),
62 .earliestVsync = mLastCallTime.count()});
63 LOG_ALWAYS_FATAL_IF((scheduleResult != scheduler::ScheduleResult::Scheduled),
64 "Error scheduling callback: rc %X", scheduleResult);
65 }
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});
103 LOG_ALWAYS_FATAL_IF((scheduleResult != ScheduleResult::Scheduled),
104 "Error rescheduling callback: rc %X", scheduleResult);
105 }
106 }
107
108 const std::string mName;
109 scheduler::VSyncDispatch::Callback mCallback;
110
111 mutable std::mutex mMutex;
112 VSyncCallbackRegistration mRegistration GUARDED_BY(mMutex);
113 bool mStarted GUARDED_BY(mMutex) = false;
114 std::chrono::nanoseconds mWorkDuration GUARDED_BY(mMutex) = 0ns;
115 std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex) = 0ns;
116 std::chrono::nanoseconds mLastCallTime GUARDED_BY(mMutex) = 0ns;
117};
118
119DispSyncSource::DispSyncSource(scheduler::VSyncDispatch& vSyncDispatch,
120 std::chrono::nanoseconds workDuration,
121 std::chrono::nanoseconds readyDuration, bool traceVsync,
Ana Krulec241cf832018-08-10 15:03:23 -0700122 const char* name)
123 : mName(name),
Ady Abraham50204dd2019-07-19 15:47:11 -0700124 mValue(base::StringPrintf("VSYNC-%s", name), 0),
Ana Krulec241cf832018-08-10 15:03:23 -0700125 mTraceVsync(traceVsync),
Ana Krulec072233f2018-08-10 15:03:23 -0700126 mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
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) {
Ady Abraham9c53ee72020-07-22 21:16:18 -0700185 callback->onVSyncEvent(targetWakeupTime, vsyncTime, readyTime);
Ana Krulec241cf832018-08-10 15:03:23 -0700186 }
187}
188
Ady Abraham5e7371c2020-03-24 14:47:24 -0700189void DispSyncSource::dump(std::string& result) const {
190 std::lock_guard lock(mVsyncMutex);
191 StringAppendF(&result, "DispSyncSource: %s(%s)\n", mName, mEnabled ? "enabled" : "disabled");
Ady Abraham5e7371c2020-03-24 14:47:24 -0700192}
193
Ady Abraham9c53ee72020-07-22 21:16:18 -0700194} // namespace android::scheduler