blob: f2af85e94ae9a3e336e1f87068c135d2e85ecdce [file] [log] [blame]
Mathias Agopianf1d8e872009-04-20 19:39:12 -07001/*
2 * Copyright (C) 2009 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
Ady Abraham55fa7272020-09-30 19:19:27 -070017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080018
Mathias Agopian8aedd472012-01-24 16:39:14 -080019#include <binder/IPCThreadState.h>
20
Mathias Agopianf1d8e872009-04-20 19:39:12 -070021#include <utils/Log.h>
Lloyd Pique78ce4182018-01-31 16:39:51 -080022#include <utils/Timers.h>
23#include <utils/threads.h>
Mathias Agopian8aedd472012-01-24 16:39:14 -080024
Lloyd Pique3fcdef12018-01-22 17:14:00 -080025#include <gui/DisplayEventReceiver.h>
Mathias Agopianf1d8e872009-04-20 19:39:12 -070026
Mathias Agopian8aedd472012-01-24 16:39:14 -080027#include "EventThread.h"
Ady Abraham55fa7272020-09-30 19:19:27 -070028#include "FrameTimeline.h"
Lloyd Pique78ce4182018-01-31 16:39:51 -080029#include "MessageQueue.h"
Mathias Agopianf1d8e872009-04-20 19:39:12 -070030
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070031namespace android::impl {
Lloyd Pique3fcdef12018-01-22 17:14:00 -080032
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070033void MessageQueue::Handler::dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime) {
34 if (!mFramePending.exchange(true)) {
Adithya Srinivasan5f683cf2020-09-15 14:21:04 -070035 mVsyncId = vsyncId;
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070036 mExpectedVsyncTime = expectedVsyncTime;
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070037 mQueue.mLooper->sendMessage(this, Message());
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080038 }
39}
40
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070041bool MessageQueue::Handler::isFramePending() const {
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070042 return mFramePending.load();
Ady Abraham562c2712021-05-07 15:10:42 -070043}
44
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070045void MessageQueue::Handler::handleMessage(const Message&) {
46 mFramePending.store(false);
47
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070048 const nsecs_t frameTime = systemTime();
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070049 auto& compositor = mQueue.mCompositor;
50
51 if (!compositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
52 return;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080053 }
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070054
Ady Abraham302ebed2022-03-07 16:03:41 -080055 compositor.composite(frameTime, mVsyncId);
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -070056 compositor.sample();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080057}
58
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070059MessageQueue::MessageQueue(ICompositor& compositor)
60 : MessageQueue(compositor, sp<Handler>::make(*this)) {}
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080061
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070062constexpr bool kAllowNonCallbacks = true;
63
64MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
65 : mCompositor(compositor),
66 mLooper(sp<Looper>::make(kAllowNonCallbacks)),
67 mHandler(std::move(handler)) {}
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080068
Ady Abraham55fa7272020-09-30 19:19:27 -070069// TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly
70// and remove the EventThread from MessageQueue
Dominik Laskowski208235c2020-12-03 15:38:51 -080071void MessageQueue::setInjector(sp<EventThreadConnection> connection) {
72 auto& tube = mInjector.tube;
73
74 if (const int fd = tube.getFd(); fd >= 0) {
75 mLooper->removeFd(fd);
Ana Krulec98b5b242018-08-10 15:03:23 -070076 }
77
Dominik Laskowski208235c2020-12-03 15:38:51 -080078 if (connection) {
79 // The EventThreadConnection is retained when disabling injection, so avoid subsequently
80 // stealing invalid FDs. Note that the stolen FDs are kept open.
81 if (tube.getFd() < 0) {
82 connection->stealReceiveChannel(&tube);
83 } else {
84 ALOGW("Recycling channel for VSYNC injection.");
85 }
86
87 mLooper->addFd(
88 tube.getFd(), 0, Looper::EVENT_INPUT,
89 [](int, int, void* data) {
90 reinterpret_cast<MessageQueue*>(data)->injectorCallback();
91 return 1; // Keep registration.
92 },
93 this);
Ady Abraham55fa7272020-09-30 19:19:27 -070094 }
Dominik Laskowski208235c2020-12-03 15:38:51 -080095
96 std::lock_guard lock(mInjector.mutex);
97 mInjector.connection = std::move(connection);
Ady Abraham55fa7272020-09-30 19:19:27 -070098}
99
100void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
101 ATRACE_CALL();
102 // Trace VSYNC-sf
103 mVsync.value = (mVsync.value + 1) % 2;
104
105 {
106 std::lock_guard lock(mVsync.mutex);
107 mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700108 mVsync.scheduledFrameTime.reset();
Ady Abraham55fa7272020-09-30 19:19:27 -0700109 }
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700110
111 const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
112 {targetWakeupTime, readyTime, vsyncTime});
113
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700114 mHandler->dispatchFrame(vsyncId, vsyncTime);
Ady Abraham55fa7272020-09-30 19:19:27 -0700115}
116
117void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
118 frametimeline::TokenManager& tokenManager,
119 std::chrono::nanoseconds workDuration) {
120 setDuration(workDuration);
121 mVsync.tokenManager = &tokenManager;
122 mVsync.registration = std::make_unique<
123 scheduler::VSyncCallbackRegistration>(dispatch,
124 std::bind(&MessageQueue::vsyncCallback, this,
125 std::placeholders::_1,
126 std::placeholders::_2,
127 std::placeholders::_3),
128 "sf");
129}
130
131void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) {
132 ATRACE_CALL();
133 std::lock_guard lock(mVsync.mutex);
134 mVsync.workDuration = workDuration;
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700135 if (mVsync.scheduledFrameTime) {
136 mVsync.scheduledFrameTime = mVsync.registration->schedule(
Ady Abraham562c2712021-05-07 15:10:42 -0700137 {mVsync.workDuration.get().count(),
138 /*readyDuration=*/0, mVsync.lastCallbackTime.count()});
Ady Abraham326ecde2020-11-06 15:05:53 -0800139 }
Ana Krulec98b5b242018-08-10 15:03:23 -0700140}
141
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800142void MessageQueue::waitMessage() {
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700143 do {
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800144 IPCThreadState::self()->flushCommands();
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800145 int32_t ret = mLooper->pollOnce(-1);
146 switch (ret) {
Brian Carlstromfe761ab2013-12-12 23:13:18 -0800147 case Looper::POLL_WAKE:
148 case Looper::POLL_CALLBACK:
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800149 continue;
Brian Carlstromfe761ab2013-12-12 23:13:18 -0800150 case Looper::POLL_ERROR:
151 ALOGE("Looper::POLL_ERROR");
Pablo Ceballos53390e12015-08-04 11:25:59 -0700152 continue;
Brian Carlstromfe761ab2013-12-12 23:13:18 -0800153 case Looper::POLL_TIMEOUT:
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800154 // timeout (should not happen)
155 continue;
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800156 default:
157 // should not happen
Steve Blocke6f43dd2012-01-06 19:20:56 +0000158 ALOGE("Looper::pollOnce() returned unknown status %d", ret);
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800159 continue;
160 }
161 } while (true);
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700162}
163
Dominik Laskowskidd4ef272020-04-23 14:02:12 -0700164void MessageQueue::postMessage(sp<MessageHandler>&& handler) {
165 mLooper->sendMessage(handler, Message());
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700166}
167
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700168void MessageQueue::scheduleFrame() {
Ady Abraham55fa7272020-09-30 19:19:27 -0700169 ATRACE_CALL();
Dominik Laskowski208235c2020-12-03 15:38:51 -0800170
171 {
172 std::lock_guard lock(mInjector.mutex);
173 if (CC_UNLIKELY(mInjector.connection)) {
174 ALOGD("%s while injecting VSYNC", __FUNCTION__);
175 mInjector.connection->requestNextVsync();
176 return;
177 }
Ady Abraham55fa7272020-09-30 19:19:27 -0700178 }
Dominik Laskowski208235c2020-12-03 15:38:51 -0800179
180 std::lock_guard lock(mVsync.mutex);
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700181 mVsync.scheduledFrameTime =
Ady Abraham562c2712021-05-07 15:10:42 -0700182 mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
183 .readyDuration = 0,
184 .earliestVsync = mVsync.lastCallbackTime.count()});
Mathias Agopian8aedd472012-01-24 16:39:14 -0800185}
186
Dominik Laskowski208235c2020-12-03 15:38:51 -0800187void MessageQueue::injectorCallback() {
Mathias Agopian8aedd472012-01-24 16:39:14 -0800188 ssize_t n;
189 DisplayEventReceiver::Event buffer[8];
Dominik Laskowski208235c2020-12-03 15:38:51 -0800190 while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) {
Lloyd Pique78ce4182018-01-31 16:39:51 -0800191 for (int i = 0; i < n; i++) {
Mathias Agopian8aedd472012-01-24 16:39:14 -0800192 if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700193 auto& vsync = buffer[i].vsync;
Rachel Leeb9c5a772022-02-04 21:17:37 -0800194 mHandler->dispatchFrame(vsync.vsyncData.preferredVsyncId(),
195 vsync.vsyncData.preferredExpectedPresentationTime());
Mathias Agopian8aedd472012-01-24 16:39:14 -0800196 break;
197 }
198 }
199 }
Mathias Agopian8aedd472012-01-24 16:39:14 -0800200}
201
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700202auto MessageQueue::getScheduledFrameTime() const -> std::optional<Clock::time_point> {
203 if (mHandler->isFramePending()) {
204 return Clock::now();
Ady Abraham562c2712021-05-07 15:10:42 -0700205 }
206
207 std::lock_guard lock(mVsync.mutex);
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700208 if (const auto time = mVsync.scheduledFrameTime) {
209 return Clock::time_point(std::chrono::nanoseconds(*time));
Ady Abraham562c2712021-05-07 15:10:42 -0700210 }
211
212 return std::nullopt;
213}
214
Dominik Laskowskidd4ef272020-04-23 14:02:12 -0700215} // namespace android::impl