xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
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 
19 #include <deque>
20 #include <mutex>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include <android-base/thread_annotations.h>
25 #include <scheduler/FrameTime.h>
26 #include <scheduler/TimeKeeper.h>
27 #include <ui/DisplayId.h>
28 
29 #include "VSyncTracker.h"
30 
31 namespace android::scheduler {
32 
33 class VSyncPredictor : public VSyncTracker {
34 public:
35     /*
36      * \param [in] Clock The clock abstraction. Useful for unit tests.
37      * \param [in] PhysicalDisplayid The display this corresponds to.
38      * \param [in] modePtr  The initial display mode
39      * \param [in] historySize  The internal amount of entries to store in the model.
40      * \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
41      * predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
42      * samples that fall outlierTolerancePercent from an anticipated vsync event.
43      */
44     VSyncPredictor(std::unique_ptr<Clock>, ftl::NonNull<DisplayModePtr> modePtr, size_t historySize,
45                    size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
46     ~VSyncPredictor();
47 
48     bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
49     nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint,
50                                          std::optional<nsecs_t> lastVsyncOpt = {}) final
51             EXCLUDES(mMutex);
52     nsecs_t currentPeriod() const final EXCLUDES(mMutex);
53     Period minFramePeriod() const final EXCLUDES(mMutex);
54     void resetModel() final EXCLUDES(mMutex);
55 
56     /* Query if the model is in need of more samples to make a prediction.
57      * \return  True, if model would benefit from more samples, False if not.
58      */
59     bool needsMoreSamples() const final EXCLUDES(mMutex);
60 
61     struct Model {
62         nsecs_t slope;
63         nsecs_t intercept;
64     };
65 
66     VSyncPredictor::Model getVSyncPredictionModel() const EXCLUDES(mMutex);
67 
68     bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) final EXCLUDES(mMutex);
69 
70     void setDisplayModePtr(ftl::NonNull<DisplayModePtr>) final EXCLUDES(mMutex);
71 
isCurrentMode(const ftl::NonNull<DisplayModePtr> & modePtr)72     bool isCurrentMode(const ftl::NonNull<DisplayModePtr>& modePtr) const EXCLUDES(mMutex) {
73         std::lock_guard lock(mMutex);
74         return mDisplayModePtr->getId() == modePtr->getId() &&
75                 mDisplayModePtr->getVsyncRate().getPeriodNsecs() ==
76                 mRateMap.find(idealPeriod())->second.slope;
77     }
78 
79     void setRenderRate(Fps, bool applyImmediately) final EXCLUDES(mMutex);
80 
81     void onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) final
82             EXCLUDES(mMutex);
83     void onFrameMissed(TimePoint expectedPresentTime) final EXCLUDES(mMutex);
84 
85     void dump(std::string& result) const final EXCLUDES(mMutex);
86 
87 private:
88     struct VsyncSequence {
89         nsecs_t vsyncTime;
90         int64_t seq;
91     };
92 
93     struct MissedVsync {
94         TimePoint vsync = TimePoint::fromNs(0);
95         Duration fixup = Duration::fromNs(0);
96     };
97 
98     class VsyncTimeline {
99     public:
100         VsyncTimeline(TimePoint knownVsync, Period idealPeriod, std::optional<Fps> renderRateOpt);
101         std::optional<TimePoint> nextAnticipatedVSyncTimeFrom(
102                 Model model, std::optional<Period> minFramePeriodOpt, nsecs_t vsyncTime,
103                 MissedVsync lastMissedVsync, std::optional<nsecs_t> lastVsyncOpt = {});
104         void freeze(TimePoint lastVsync);
validUntil()105         std::optional<TimePoint> validUntil() const { return mValidUntil; }
106         bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate);
107         void shiftVsyncSequence(Duration phase, Period minFramePeriod);
setRenderRate(std::optional<Fps> renderRateOpt)108         void setRenderRate(std::optional<Fps> renderRateOpt) { mRenderRateOpt = renderRateOpt; }
109 
110         enum class VsyncOnTimeline {
111             Unique,  // Within timeline, not shared with next timeline.
112             Shared,  // Within timeline, shared with next timeline.
113             Outside, // Outside of the timeline.
114         };
115         VsyncOnTimeline isWithin(TimePoint vsync);
116 
117     private:
118         nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync);
119         VsyncSequence getVsyncSequenceLocked(Model, nsecs_t vsync);
120         std::optional<VsyncSequence> makeVsyncSequence(TimePoint knownVsync);
121 
122         const Period mIdealPeriod = Duration::fromNs(0);
123         std::optional<Fps> mRenderRateOpt;
124         std::optional<TimePoint> mValidUntil;
125         std::optional<VsyncSequence> mLastVsyncSequence;
126     };
127 
128     VSyncPredictor(VSyncPredictor const&) = delete;
129     VSyncPredictor& operator=(VSyncPredictor const&) = delete;
130     void clearTimestamps(bool clearTimelines) REQUIRES(mMutex);
131 
132     const std::unique_ptr<Clock> mClock;
133     const PhysicalDisplayId mId;
134 
135     inline void traceInt64If(const char* name, int64_t value) const;
136     inline void traceInt64(const char* name, int64_t value) const;
137 
138     size_t next(size_t i) const REQUIRES(mMutex);
139     bool validate(nsecs_t timestamp) const REQUIRES(mMutex);
140     Model getVSyncPredictionModelLocked() const REQUIRES(mMutex);
141     nsecs_t snapToVsync(nsecs_t timePoint) const REQUIRES(mMutex);
142     Period minFramePeriodLocked() const REQUIRES(mMutex);
143     Duration ensureMinFrameDurationIsKept(TimePoint, TimePoint) REQUIRES(mMutex);
144     void purgeTimelines(android::TimePoint now) REQUIRES(mMutex);
145 
146     nsecs_t idealPeriod() const REQUIRES(mMutex);
147 
148     bool const mTraceOn;
149     size_t const kHistorySize;
150     size_t const kMinimumSamplesForPrediction;
151     size_t const kOutlierTolerancePercent;
152     std::mutex mutable mMutex;
153 
154     std::optional<nsecs_t> mKnownTimestamp GUARDED_BY(mMutex);
155 
156     // Map between ideal vsync period and the calculated model
157     std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);
158 
159     size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
160     std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
161 
162     ftl::NonNull<DisplayModePtr> mDisplayModePtr GUARDED_BY(mMutex);
163     int mNumVsyncsForFrame GUARDED_BY(mMutex);
164 
165     std::deque<TimePoint> mPastExpectedPresentTimes GUARDED_BY(mMutex);
166 
167     MissedVsync mMissedVsync GUARDED_BY(mMutex);
168 
169     std::deque<VsyncTimeline> mTimelines GUARDED_BY(mMutex);
170     TimePoint mLastCommittedVsync GUARDED_BY(mMutex) = TimePoint::fromNs(0);
171     Period mIdealPeriod GUARDED_BY(mMutex) = Duration::fromNs(0);
172     std::optional<Fps> mRenderRateOpt GUARDED_BY(mMutex);
173 };
174 
175 } // namespace android::scheduler
176