1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include <cstdint>
20*38e8c45fSAndroid Build Coastguard Worker #include <future>
21*38e8c45fSAndroid Build Coastguard Worker #include <type_traits>
22*38e8c45fSAndroid Build Coastguard Worker #include <utility>
23*38e8c45fSAndroid Build Coastguard Worker
24*38e8c45fSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <android/gui/IDisplayEventConnection.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <private/gui/BitTube.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <utils/Looper.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <utils/StrongPointer.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h>
30*38e8c45fSAndroid Build Coastguard Worker
31*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/Time.h>
32*38e8c45fSAndroid Build Coastguard Worker #include <scheduler/VsyncId.h>
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker #include "EventThread.h"
35*38e8c45fSAndroid Build Coastguard Worker #include "TracedOrdinal.h"
36*38e8c45fSAndroid Build Coastguard Worker #include "VSyncDispatch.h"
37*38e8c45fSAndroid Build Coastguard Worker
38*38e8c45fSAndroid Build Coastguard Worker namespace android {
39*38e8c45fSAndroid Build Coastguard Worker
40*38e8c45fSAndroid Build Coastguard Worker struct ICompositor;
41*38e8c45fSAndroid Build Coastguard Worker
42*38e8c45fSAndroid Build Coastguard Worker template <typename F>
43*38e8c45fSAndroid Build Coastguard Worker class Task : public MessageHandler {
44*38e8c45fSAndroid Build Coastguard Worker template <typename G>
45*38e8c45fSAndroid Build Coastguard Worker friend auto makeTask(G&&);
46*38e8c45fSAndroid Build Coastguard Worker
47*38e8c45fSAndroid Build Coastguard Worker template <typename... Args>
48*38e8c45fSAndroid Build Coastguard Worker friend sp<Task<F>> sp<Task<F>>::make(Args&&... args);
49*38e8c45fSAndroid Build Coastguard Worker
Task(F && f)50*38e8c45fSAndroid Build Coastguard Worker explicit Task(F&& f) : mTask(std::move(f)) {}
51*38e8c45fSAndroid Build Coastguard Worker
handleMessage(const Message &)52*38e8c45fSAndroid Build Coastguard Worker void handleMessage(const Message&) override { mTask(); }
53*38e8c45fSAndroid Build Coastguard Worker
54*38e8c45fSAndroid Build Coastguard Worker using T = std::invoke_result_t<F>;
55*38e8c45fSAndroid Build Coastguard Worker std::packaged_task<T()> mTask;
56*38e8c45fSAndroid Build Coastguard Worker };
57*38e8c45fSAndroid Build Coastguard Worker
58*38e8c45fSAndroid Build Coastguard Worker template <typename F>
makeTask(F && f)59*38e8c45fSAndroid Build Coastguard Worker inline auto makeTask(F&& f) {
60*38e8c45fSAndroid Build Coastguard Worker sp<Task<F>> task = sp<Task<F>>::make(std::forward<F>(f));
61*38e8c45fSAndroid Build Coastguard Worker return std::make_pair(task, task->mTask.get_future());
62*38e8c45fSAndroid Build Coastguard Worker }
63*38e8c45fSAndroid Build Coastguard Worker
64*38e8c45fSAndroid Build Coastguard Worker class MessageQueue {
65*38e8c45fSAndroid Build Coastguard Worker public:
66*38e8c45fSAndroid Build Coastguard Worker virtual ~MessageQueue() = default;
67*38e8c45fSAndroid Build Coastguard Worker
68*38e8c45fSAndroid Build Coastguard Worker virtual void initVsyncInternal(std::shared_ptr<scheduler::VSyncDispatch>,
69*38e8c45fSAndroid Build Coastguard Worker frametimeline::TokenManager&,
70*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds workDuration) = 0;
71*38e8c45fSAndroid Build Coastguard Worker virtual void destroyVsync() = 0;
72*38e8c45fSAndroid Build Coastguard Worker virtual void setDuration(std::chrono::nanoseconds workDuration) = 0;
73*38e8c45fSAndroid Build Coastguard Worker virtual void waitMessage() = 0;
74*38e8c45fSAndroid Build Coastguard Worker virtual void postMessage(sp<MessageHandler>&&) = 0;
75*38e8c45fSAndroid Build Coastguard Worker virtual void postMessageDelayed(sp<MessageHandler>&&, nsecs_t uptimeDelay) = 0;
76*38e8c45fSAndroid Build Coastguard Worker virtual void scheduleConfigure() = 0;
77*38e8c45fSAndroid Build Coastguard Worker virtual void scheduleFrame(Duration workDurationSlack = Duration::fromNs(0)) = 0;
78*38e8c45fSAndroid Build Coastguard Worker
79*38e8c45fSAndroid Build Coastguard Worker virtual std::optional<scheduler::ScheduleResult> getScheduledFrameResult() const = 0;
80*38e8c45fSAndroid Build Coastguard Worker };
81*38e8c45fSAndroid Build Coastguard Worker
82*38e8c45fSAndroid Build Coastguard Worker namespace impl {
83*38e8c45fSAndroid Build Coastguard Worker
84*38e8c45fSAndroid Build Coastguard Worker class MessageQueue : public android::MessageQueue {
85*38e8c45fSAndroid Build Coastguard Worker protected:
86*38e8c45fSAndroid Build Coastguard Worker class Handler : public MessageHandler {
87*38e8c45fSAndroid Build Coastguard Worker MessageQueue& mQueue;
88*38e8c45fSAndroid Build Coastguard Worker std::atomic_bool mFramePending = false;
89*38e8c45fSAndroid Build Coastguard Worker
90*38e8c45fSAndroid Build Coastguard Worker std::atomic<VsyncId> mVsyncId;
91*38e8c45fSAndroid Build Coastguard Worker std::atomic<TimePoint> mExpectedVsyncTime;
92*38e8c45fSAndroid Build Coastguard Worker
93*38e8c45fSAndroid Build Coastguard Worker public:
Handler(MessageQueue & queue)94*38e8c45fSAndroid Build Coastguard Worker explicit Handler(MessageQueue& queue) : mQueue(queue) {}
95*38e8c45fSAndroid Build Coastguard Worker void handleMessage(const Message& message) override;
96*38e8c45fSAndroid Build Coastguard Worker
getExpectedVsyncTime()97*38e8c45fSAndroid Build Coastguard Worker virtual TimePoint getExpectedVsyncTime() const { return mExpectedVsyncTime.load(); }
98*38e8c45fSAndroid Build Coastguard Worker
99*38e8c45fSAndroid Build Coastguard Worker virtual bool isFramePending() const;
100*38e8c45fSAndroid Build Coastguard Worker
101*38e8c45fSAndroid Build Coastguard Worker virtual void dispatchFrame(VsyncId, TimePoint expectedVsyncTime);
102*38e8c45fSAndroid Build Coastguard Worker };
103*38e8c45fSAndroid Build Coastguard Worker
104*38e8c45fSAndroid Build Coastguard Worker friend class Handler;
105*38e8c45fSAndroid Build Coastguard Worker
106*38e8c45fSAndroid Build Coastguard Worker // For tests.
107*38e8c45fSAndroid Build Coastguard Worker MessageQueue(ICompositor&, sp<Handler>);
108*38e8c45fSAndroid Build Coastguard Worker
109*38e8c45fSAndroid Build Coastguard Worker void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker void onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch>) EXCLUDES(mVsync.mutex);
112*38e8c45fSAndroid Build Coastguard Worker
113*38e8c45fSAndroid Build Coastguard Worker private:
114*38e8c45fSAndroid Build Coastguard Worker virtual void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) = 0;
115*38e8c45fSAndroid Build Coastguard Worker
116*38e8c45fSAndroid Build Coastguard Worker ICompositor& mCompositor;
117*38e8c45fSAndroid Build Coastguard Worker const sp<Looper> mLooper;
118*38e8c45fSAndroid Build Coastguard Worker const sp<Handler> mHandler;
119*38e8c45fSAndroid Build Coastguard Worker
120*38e8c45fSAndroid Build Coastguard Worker struct Vsync {
121*38e8c45fSAndroid Build Coastguard Worker frametimeline::TokenManager* tokenManager = nullptr;
122*38e8c45fSAndroid Build Coastguard Worker
123*38e8c45fSAndroid Build Coastguard Worker mutable std::mutex mutex;
124*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<scheduler::VSyncCallbackRegistration> registration GUARDED_BY(mutex);
125*38e8c45fSAndroid Build Coastguard Worker TracedOrdinal<std::chrono::nanoseconds> workDuration
126*38e8c45fSAndroid Build Coastguard Worker GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
127*38e8c45fSAndroid Build Coastguard Worker TimePoint lastCallbackTime GUARDED_BY(mutex);
128*38e8c45fSAndroid Build Coastguard Worker std::optional<scheduler::ScheduleResult> scheduledFrameTimeOpt GUARDED_BY(mutex);
129*38e8c45fSAndroid Build Coastguard Worker TracedOrdinal<int> value = {"VSYNC-sf", 0};
130*38e8c45fSAndroid Build Coastguard Worker };
131*38e8c45fSAndroid Build Coastguard Worker
132*38e8c45fSAndroid Build Coastguard Worker Vsync mVsync;
133*38e8c45fSAndroid Build Coastguard Worker
134*38e8c45fSAndroid Build Coastguard Worker // Returns the old registration so it can be destructed outside the lock to
135*38e8c45fSAndroid Build Coastguard Worker // avoid deadlock.
136*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<scheduler::VSyncCallbackRegistration> onNewVsyncScheduleLocked(
137*38e8c45fSAndroid Build Coastguard Worker std::shared_ptr<scheduler::VSyncDispatch>) REQUIRES(mVsync.mutex);
138*38e8c45fSAndroid Build Coastguard Worker
139*38e8c45fSAndroid Build Coastguard Worker public:
140*38e8c45fSAndroid Build Coastguard Worker explicit MessageQueue(ICompositor&);
141*38e8c45fSAndroid Build Coastguard Worker
142*38e8c45fSAndroid Build Coastguard Worker void initVsyncInternal(std::shared_ptr<scheduler::VSyncDispatch>, frametimeline::TokenManager&,
143*38e8c45fSAndroid Build Coastguard Worker std::chrono::nanoseconds workDuration) override;
144*38e8c45fSAndroid Build Coastguard Worker void destroyVsync() override;
145*38e8c45fSAndroid Build Coastguard Worker void setDuration(std::chrono::nanoseconds workDuration) override;
146*38e8c45fSAndroid Build Coastguard Worker
147*38e8c45fSAndroid Build Coastguard Worker void waitMessage() override;
148*38e8c45fSAndroid Build Coastguard Worker void postMessage(sp<MessageHandler>&&) override;
149*38e8c45fSAndroid Build Coastguard Worker void postMessageDelayed(sp<MessageHandler>&&, nsecs_t uptimeDelay) override;
150*38e8c45fSAndroid Build Coastguard Worker
151*38e8c45fSAndroid Build Coastguard Worker void scheduleConfigure() override;
152*38e8c45fSAndroid Build Coastguard Worker void scheduleFrame(Duration workDurationSlack = Duration::fromNs(0)) override;
153*38e8c45fSAndroid Build Coastguard Worker
154*38e8c45fSAndroid Build Coastguard Worker std::optional<scheduler::ScheduleResult> getScheduledFrameResult() const override;
155*38e8c45fSAndroid Build Coastguard Worker };
156*38e8c45fSAndroid Build Coastguard Worker
157*38e8c45fSAndroid Build Coastguard Worker } // namespace impl
158*38e8c45fSAndroid Build Coastguard Worker } // namespace android
159