blob: 2c908a698365b3c23af266a14a355298685509de [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
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070017#pragma once
Mathias Agopianf1d8e872009-04-20 19:39:12 -070018
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070019#include <cstdint>
20#include <future>
21#include <type_traits>
22#include <utility>
Mathias Agopianf1d8e872009-04-20 19:39:12 -070023
Dominik Laskowski208235c2020-12-03 15:38:51 -080024#include <android-base/thread_annotations.h>
Lloyd Pique3fcdef12018-01-22 17:14:00 -080025#include <gui/IDisplayEventConnection.h>
Lloyd Pique78ce4182018-01-31 16:39:51 -080026#include <private/gui/BitTube.h>
Dominik Laskowski208235c2020-12-03 15:38:51 -080027#include <utils/Looper.h>
28#include <utils/Timers.h>
Mathias Agopian8aedd472012-01-24 16:39:14 -080029
Dominik Laskowskif654d572018-12-20 11:03:06 -080030#include "EventThread.h"
Ady Abraham55fa7272020-09-30 19:19:27 -070031#include "TracedOrdinal.h"
32#include "VSyncDispatch.h"
Mathias Agopianf1d8e872009-04-20 19:39:12 -070033
34namespace android {
35
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070036struct ICompositor {
37 virtual bool commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) = 0;
38 virtual void composite(nsecs_t frameTime) = 0;
39 virtual void sample() = 0;
40
41protected:
42 ~ICompositor() = default;
43};
Mathias Agopian8aedd472012-01-24 16:39:14 -080044
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070045template <typename F>
46class Task : public MessageHandler {
47 template <typename G>
48 friend auto makeTask(G&&);
Mathias Agopianf1d8e872009-04-20 19:39:12 -070049
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070050 explicit Task(F&& f) : mTask(std::move(f)) {}
Lloyd Pique78ce4182018-01-31 16:39:51 -080051
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070052 void handleMessage(const Message&) override { mTask(); }
Mathias Agopianbb641242010-05-18 17:06:55 -070053
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070054 using T = std::invoke_result_t<F>;
55 std::packaged_task<T()> mTask;
Mathias Agopianf61c57f2011-11-23 16:49:10 -080056};
Mathias Agopianf1d8e872009-04-20 19:39:12 -070057
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070058template <typename F>
59inline auto makeTask(F&& f) {
60 sp<Task<F>> task = new Task<F>(std::move(f));
61 return std::make_pair(task, task->mTask.get_future());
62}
Mathias Agopianf1d8e872009-04-20 19:39:12 -070063
Mathias Agopianf61c57f2011-11-23 16:49:10 -080064class MessageQueue {
Lloyd Pique3fcdef12018-01-22 17:14:00 -080065public:
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070066 virtual ~MessageQueue() = default;
Lloyd Pique3fcdef12018-01-22 17:14:00 -080067
Ady Abraham55fa7272020-09-30 19:19:27 -070068 virtual void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
69 std::chrono::nanoseconds workDuration) = 0;
70 virtual void setDuration(std::chrono::nanoseconds workDuration) = 0;
Dominik Laskowski208235c2020-12-03 15:38:51 -080071 virtual void setInjector(sp<EventThreadConnection>) = 0;
Lloyd Pique3fcdef12018-01-22 17:14:00 -080072 virtual void waitMessage() = 0;
Dominik Laskowskidd4ef272020-04-23 14:02:12 -070073 virtual void postMessage(sp<MessageHandler>&&) = 0;
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070074 virtual void scheduleCommit() = 0;
75 virtual void scheduleComposite() = 0;
Lloyd Pique3fcdef12018-01-22 17:14:00 -080076
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070077 using Clock = std::chrono::steady_clock;
78 virtual std::optional<Clock::time_point> getScheduledFrameTime() const = 0;
79};
Lloyd Pique3fcdef12018-01-22 17:14:00 -080080
81namespace impl {
82
Ady Abraham55fa7272020-09-30 19:19:27 -070083class MessageQueue : public android::MessageQueue {
84protected:
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080085 class Handler : public MessageHandler {
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070086 static constexpr uint32_t kCommit = 0b1;
87 static constexpr uint32_t kComposite = 0b10;
88
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080089 MessageQueue& mQueue;
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070090 std::atomic<uint32_t> mEventMask = 0;
91 std::atomic<int64_t> mVsyncId = 0;
92 std::atomic<nsecs_t> mExpectedVsyncTime = 0;
Lloyd Pique78ce4182018-01-31 16:39:51 -080093
Mathias Agopian99ce5cd2012-01-31 18:24:27 -080094 public:
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070095 explicit Handler(MessageQueue& queue) : mQueue(queue) {}
Ady Abraham55fa7272020-09-30 19:19:27 -070096 void handleMessage(const Message& message) override;
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -070097
98 bool isFramePending() const;
99
100 virtual void dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime);
101 void dispatchComposite();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800102 };
103
104 friend class Handler;
105
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700106 // For tests.
107 MessageQueue(ICompositor&, sp<Handler>);
108
109 void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);
110
111private:
112 ICompositor& mCompositor;
113 const sp<Looper> mLooper;
114 const sp<Handler> mHandler;
Ady Abraham55fa7272020-09-30 19:19:27 -0700115
116 struct Vsync {
117 frametimeline::TokenManager* tokenManager = nullptr;
118 std::unique_ptr<scheduler::VSyncCallbackRegistration> registration;
119
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700120 mutable std::mutex mutex;
Ady Abraham55fa7272020-09-30 19:19:27 -0700121 TracedOrdinal<std::chrono::nanoseconds> workDuration
122 GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
123 std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0};
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700124 std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex);
Ady Abraham55fa7272020-09-30 19:19:27 -0700125 TracedOrdinal<int> value = {"VSYNC-sf", 0};
126 };
127
Dominik Laskowski208235c2020-12-03 15:38:51 -0800128 struct Injector {
129 gui::BitTube tube;
130 std::mutex mutex;
131 sp<EventThreadConnection> connection GUARDED_BY(mutex);
132 };
Ady Abraham55fa7272020-09-30 19:19:27 -0700133
Dominik Laskowski208235c2020-12-03 15:38:51 -0800134 Vsync mVsync;
135 Injector mInjector;
136
Dominik Laskowski208235c2020-12-03 15:38:51 -0800137 void injectorCallback();
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700138
Mathias Agopianf61c57f2011-11-23 16:49:10 -0800139public:
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700140 explicit MessageQueue(ICompositor&);
141
Ady Abraham55fa7272020-09-30 19:19:27 -0700142 void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
143 std::chrono::nanoseconds workDuration) override;
144 void setDuration(std::chrono::nanoseconds workDuration) override;
Dominik Laskowski208235c2020-12-03 15:38:51 -0800145 void setInjector(sp<EventThreadConnection>) override;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800146
Lloyd Pique3fcdef12018-01-22 17:14:00 -0800147 void waitMessage() override;
Dominik Laskowskidd4ef272020-04-23 14:02:12 -0700148 void postMessage(sp<MessageHandler>&&) override;
Mathias Agopian9eb1f052013-04-10 16:27:17 -0700149
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700150 void scheduleCommit() override;
151 void scheduleComposite() override;
Ana Krulec7d1d6832018-12-27 11:10:09 -0800152
Dominik Laskowskie0e0cde2021-07-30 10:42:05 -0700153 std::optional<Clock::time_point> getScheduledFrameTime() const override;
Mathias Agopianf1d8e872009-04-20 19:39:12 -0700154};
155
Lloyd Pique3fcdef12018-01-22 17:14:00 -0800156} // namespace impl
157} // namespace android