blob: f978016c9e151748856b22f8ba92e6942a5b3071 [file] [log] [blame]
Kevin DuBois305bef12019-10-09 13:23:27 -07001/*
2 * Copyright 2019 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
17#pragma once
18
Kevin DuBois305bef12019-10-09 13:23:27 -070019#include <functional>
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070020#include <optional>
Kevin DuBois305bef12019-10-09 13:23:27 -070021#include <string>
Kevin DuBois305bef12019-10-09 13:23:27 -070022
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080023#include <utils/Timers.h>
24
Kevin DuBois305bef12019-10-09 13:23:27 -070025#include "StrongTyping.h"
26
27namespace android::scheduler {
Kevin DuBois305bef12019-10-09 13:23:27 -070028
Ady Abrahamb5d3afa2021-05-07 11:22:23 -070029using ScheduleResult = std::optional<nsecs_t>;
30
Kevin DuBois305bef12019-10-09 13:23:27 -070031enum class CancelResult { Cancelled, TooLate, Error };
32
Kevin DuBois305bef12019-10-09 13:23:27 -070033/*
34 * VSyncDispatch is a class that will dispatch callbacks relative to system vsync events.
35 */
36class VSyncDispatch {
37public:
Ady Abraham2139f732019-11-13 18:56:40 -080038 using CallbackToken = StrongTyping<size_t, class CallbackTokenTag, Compare, Hash>;
Kevin DuBois305bef12019-10-09 13:23:27 -070039
Kevin DuBoise4f27a82019-11-12 11:41:41 -080040 virtual ~VSyncDispatch();
Kevin DuBois305bef12019-10-09 13:23:27 -070041
42 /*
Kevin DuBois2968afc2020-01-14 09:48:50 -080043 * A callback that can be registered to be awoken at a given time relative to a vsync event.
Ady Abraham9c53ee72020-07-22 21:16:18 -070044 * \param [in] vsyncTime: The timestamp of the vsync the callback is for.
45 * \param [in] targetWakeupTime: The timestamp of intended wakeup time of the cb.
46 * \param [in] readyTime: The timestamp of intended time where client needs to finish
47 * its work by.
Kevin DuBois2968afc2020-01-14 09:48:50 -080048 */
Ady Abraham9c53ee72020-07-22 21:16:18 -070049 using Callback =
50 std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime)>;
Kevin DuBois2968afc2020-01-14 09:48:50 -080051
52 /*
Kevin DuBois305bef12019-10-09 13:23:27 -070053 * Registers a callback that will be called at designated points on the vsync timeline.
54 * The callback can be scheduled, rescheduled targeting vsync times, or cancelled.
55 * The token returned must be cleaned up via unregisterCallback.
56 *
57 * \param [in] callbackFn A function to schedule for callback. The resources needed to invoke
58 * callbackFn must have lifetimes encompassing the lifetime of the
59 * CallbackToken returned.
60 * \param [in] callbackName A human-readable, unique name to identify the callback.
61 * \return A token that can be used to schedule, reschedule, or cancel the
62 * invocation of callbackFn.
63 *
64 */
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -080065 virtual CallbackToken registerCallback(Callback, std::string callbackName) = 0;
Kevin DuBois305bef12019-10-09 13:23:27 -070066
67 /*
68 * Unregisters a callback.
69 *
70 * \param [in] token The callback to unregister.
71 *
72 */
Kevin DuBoise4f27a82019-11-12 11:41:41 -080073 virtual void unregisterCallback(CallbackToken token) = 0;
Kevin DuBois305bef12019-10-09 13:23:27 -070074
75 /*
Ady Abraham9c53ee72020-07-22 21:16:18 -070076 * Timing information about a scheduled callback
77 *
78 * @workDuration: The time needed for the client to perform its work
79 * @readyDuration: The time needed for the client to be ready before a vsync event.
80 * For external (non-SF) clients, not only do we need to account for their
81 * workDuration, but we also need to account for the time SF will take to
82 * process their buffer/transaction. In this case, readyDuration will be set
83 * to the SF duration in order to provide enough end-to-end time, and to be
84 * able to provide the ready-by time (deadline) on the callback.
85 * For internal clients, we don't need to add additional padding, so
86 * readyDuration will typically be 0.
Ady Abraham4335afd2023-12-18 19:10:47 -080087 * @lastVsync: The targeted display time. This will be snapped to the closest
88 * predicted vsync time after lastVsync.
Ady Abraham9c53ee72020-07-22 21:16:18 -070089 *
90 * callback will be dispatched at 'workDuration + readyDuration' nanoseconds before a vsync
91 * event.
92 */
93 struct ScheduleTiming {
94 nsecs_t workDuration = 0;
95 nsecs_t readyDuration = 0;
Ady Abraham4335afd2023-12-18 19:10:47 -080096 nsecs_t lastVsync = 0;
Ady Abraham55fa7272020-09-30 19:19:27 -070097
98 bool operator==(const ScheduleTiming& other) const {
99 return workDuration == other.workDuration && readyDuration == other.readyDuration &&
Ady Abraham4335afd2023-12-18 19:10:47 -0800100 lastVsync == other.lastVsync;
Ady Abraham55fa7272020-09-30 19:19:27 -0700101 }
102
103 bool operator!=(const ScheduleTiming& other) const { return !(*this == other); }
Ady Abraham9c53ee72020-07-22 21:16:18 -0700104 };
105
106 /*
Kevin DuBois305bef12019-10-09 13:23:27 -0700107 * Schedules the registered callback to be dispatched.
108 *
Ady Abraham9c53ee72020-07-22 21:16:18 -0700109 * The callback will be dispatched at 'workDuration + readyDuration' nanoseconds before a vsync
110 * event.
Kevin DuBois305bef12019-10-09 13:23:27 -0700111 *
Ady Abraham4335afd2023-12-18 19:10:47 -0800112 * The caller designates the earliest vsync event that should be targeted by the lastVsync
Kevin DuBois305bef12019-10-09 13:23:27 -0700113 * parameter.
Ady Abraham9c53ee72020-07-22 21:16:18 -0700114 * The callback will be scheduled at (workDuration + readyDuration - predictedVsync), where
Ady Abraham4335afd2023-12-18 19:10:47 -0800115 * predictedVsync is the first vsync event time where ( predictedVsync >= lastVsync ).
Kevin DuBois305bef12019-10-09 13:23:27 -0700116 *
Ady Abraham4335afd2023-12-18 19:10:47 -0800117 * If (workDuration + readyDuration - lastVsync) is in the past, or if a callback has
Ady Abraham9c53ee72020-07-22 21:16:18 -0700118 * already been dispatched for the predictedVsync, an error will be returned.
Kevin DuBois305bef12019-10-09 13:23:27 -0700119 *
120 * It is valid to reschedule a callback to a different time.
121 *
122 * \param [in] token The callback to schedule.
Ady Abraham9c53ee72020-07-22 21:16:18 -0700123 * \param [in] scheduleTiming The timing information for this schedule call
Ady Abrahamb5d3afa2021-05-07 11:22:23 -0700124 * \return The expected callback time if a callback was scheduled.
125 * std::nullopt if the callback is not registered.
Kevin DuBois305bef12019-10-09 13:23:27 -0700126 */
Ady Abraham9c53ee72020-07-22 21:16:18 -0700127 virtual ScheduleResult schedule(CallbackToken token, ScheduleTiming scheduleTiming) = 0;
Kevin DuBois305bef12019-10-09 13:23:27 -0700128
Ady Abraham011f8ba2022-11-22 15:09:07 -0800129 /*
130 * Update the timing information for a scheduled callback.
131 * If the callback is not scheduled, then this function does nothing.
132 *
133 * \param [in] token The callback to schedule.
134 * \param [in] scheduleTiming The timing information for this schedule call
135 * \return The expected callback time if a callback was scheduled.
136 * std::nullopt if the callback is not registered.
137 */
138 virtual ScheduleResult update(CallbackToken token, ScheduleTiming scheduleTiming) = 0;
139
Kevin DuBois305bef12019-10-09 13:23:27 -0700140 /* Cancels a scheduled callback, if possible.
141 *
142 * \param [in] token The callback to cancel.
143 * \return A CancelResult::TooLate if the callback was already dispatched.
144 * A CancelResult::Cancelled if the callback was successfully cancelled.
145 * A CancelResult::Error if there was an pre-condition violation.
146 */
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800147 virtual CancelResult cancel(CallbackToken token) = 0;
Kevin DuBois305bef12019-10-09 13:23:27 -0700148
Ady Abraham5e7371c2020-03-24 14:47:24 -0700149 virtual void dump(std::string& result) const = 0;
150
Kevin DuBoise4f27a82019-11-12 11:41:41 -0800151protected:
152 VSyncDispatch() = default;
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800153
154 VSyncDispatch(const VSyncDispatch&) = delete;
155 VSyncDispatch& operator=(const VSyncDispatch&) = delete;
Kevin DuBois305bef12019-10-09 13:23:27 -0700156};
157
Kevin DuBois305bef12019-10-09 13:23:27 -0700158class VSyncCallbackRegistration {
159public:
Leon Scroggins III67388622023-02-06 20:36:20 -0500160 VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch>, VSyncDispatch::Callback,
161 std::string callbackName);
Dominik Laskowski4e0d20d2021-12-06 11:31:02 -0800162 ~VSyncCallbackRegistration();
163
Kevin DuBois305bef12019-10-09 13:23:27 -0700164 VSyncCallbackRegistration(VSyncCallbackRegistration&&);
165 VSyncCallbackRegistration& operator=(VSyncCallbackRegistration&&);
Kevin DuBois305bef12019-10-09 13:23:27 -0700166
167 // See documentation for VSyncDispatch::schedule.
Ady Abraham9c53ee72020-07-22 21:16:18 -0700168 ScheduleResult schedule(VSyncDispatch::ScheduleTiming scheduleTiming);
Kevin DuBois305bef12019-10-09 13:23:27 -0700169
Ady Abraham011f8ba2022-11-22 15:09:07 -0800170 // See documentation for VSyncDispatch::update.
171 ScheduleResult update(VSyncDispatch::ScheduleTiming scheduleTiming);
172
Kevin DuBois305bef12019-10-09 13:23:27 -0700173 // See documentation for VSyncDispatch::cancel.
174 CancelResult cancel();
175
176private:
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400177 friend class VSyncCallbackRegistrationTest;
178
Leon Scroggins III67388622023-02-06 20:36:20 -0500179 std::shared_ptr<VSyncDispatch> mDispatch;
Leon Scroggins III6c440ae2023-04-21 15:01:03 -0400180 std::optional<VSyncDispatch::CallbackToken> mToken;
Kevin DuBois305bef12019-10-09 13:23:27 -0700181};
182
183} // namespace android::scheduler