1 /* 2 * Copyright 2021 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 <functional> 20 #include <memory> 21 #include <string> 22 23 #include <android-base/thread_annotations.h> 24 #include <ThreadContext.h> 25 #include <ftl/enum.h> 26 #include <ftl/optional.h> 27 #include <ui/DisplayId.h> 28 29 #include <scheduler/Features.h> 30 #include <scheduler/IVsyncSource.h> 31 #include <scheduler/Time.h> 32 33 #include "ThreadContext.h" 34 #include "VSyncTracker.h" 35 36 namespace android { 37 class EventThreadTest; 38 class VsyncScheduleTest; 39 } 40 41 namespace android::fuzz { 42 class SchedulerFuzzer; 43 } 44 45 namespace android::scheduler { 46 47 // TODO(b/185535769): Rename classes, and remove aliases. 48 class VSyncDispatch; 49 class VSyncTracker; 50 51 class VsyncController; 52 using VsyncDispatch = VSyncDispatch; 53 using VsyncTracker = VSyncTracker; 54 55 // Schedule that synchronizes to hardware VSYNC of a physical display. 56 class VsyncSchedule final : public IVsyncSource { 57 public: 58 using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>; 59 60 VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync); 61 ~VsyncSchedule(); 62 63 // IVsyncSource overrides: 64 Period period() const override; 65 TimePoint vsyncDeadlineAfter(TimePoint, 66 ftl::Optional<TimePoint> lastVsyncOpt = {}) const override; 67 Period minFramePeriod() const override; 68 69 // Inform the schedule that the display mode changed the schedule needs to recalibrate 70 // itself to the new vsync period. The schedule will end the period transition internally. 71 // This will enable hardware VSYNCs in order to calibrate. 72 // 73 // \param [in] DisplayModePtr The mode that the display is changing to. 74 // \param [in] force True to force a transition even if it is not a 75 // change. 76 void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force); 77 78 // Pass a VSYNC sample to VsyncController. Return true if 79 // VsyncController detected that the VSYNC period changed. Enable or disable 80 // hardware VSYNCs depending on whether more samples are needed. 81 bool addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod); 82 83 // TODO(b/185535769): Hide behind API. getTracker()84 VsyncTracker& getTracker() const { return *mTracker; } getTracker()85 VsyncTracker& getTracker() { return *mTracker; } getController()86 VsyncController& getController() { return *mController; } 87 88 // TODO(b/185535769): Once these are hidden behind the API, they may no 89 // longer need to be shared_ptrs. 90 using DispatchPtr = std::shared_ptr<VsyncDispatch>; 91 using TrackerPtr = std::shared_ptr<VsyncTracker>; 92 93 // TODO(b/185535769): Remove once VsyncSchedule owns all registrations. getDispatch()94 DispatchPtr getDispatch() { return mDispatch; } 95 96 void dump(std::string&) const; 97 98 // Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which 99 // case this call is ignored. 100 void enableHardwareVsync() EXCLUDES(mHwVsyncLock); 101 102 // Disable hardware VSYNCs. If `disallow` is true, future calls to 103 // enableHardwareVsync are ineffective until isHardwareVsyncAllowed is 104 // called with `makeAllowed` set to true. 105 void disableHardwareVsync(bool disallow) EXCLUDES(mHwVsyncLock); 106 107 // If true, enableHardwareVsync can enable hardware VSYNC (if not already 108 // enabled). If false, enableHardwareVsync does nothing. 109 bool isHardwareVsyncAllowed(bool makeAllowed) EXCLUDES(mHwVsyncLock); 110 111 void setPendingHardwareVsyncState(bool enabled) REQUIRES(kMainThreadContext); 112 113 bool getPendingHardwareVsyncState() const REQUIRES(kMainThreadContext); 114 115 protected: 116 using ControllerPtr = std::unique_ptr<VsyncController>; 117 NoOpRequestHardwareVsync(PhysicalDisplayId,bool)118 static void NoOpRequestHardwareVsync(PhysicalDisplayId, bool) {} 119 120 // For tests. 121 VsyncSchedule(PhysicalDisplayId, TrackerPtr, DispatchPtr, ControllerPtr, 122 RequestHardwareVsync = NoOpRequestHardwareVsync); 123 124 private: 125 friend class TestableScheduler; 126 friend class android::EventThreadTest; 127 friend class android::VsyncScheduleTest; 128 friend class android::fuzz::SchedulerFuzzer; 129 130 static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr); 131 static DispatchPtr createDispatch(TrackerPtr); 132 static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags); 133 134 void enableHardwareVsyncLocked() REQUIRES(mHwVsyncLock); 135 136 mutable std::mutex mHwVsyncLock; 137 enum class HwVsyncState { 138 // Hardware VSYNCs are currently enabled. 139 Enabled, 140 141 // Hardware VSYNCs are currently disabled. They can be enabled by a call 142 // to `enableHardwareVsync`. 143 Disabled, 144 145 // Hardware VSYNCs are not currently allowed (e.g. because the display 146 // is off). 147 Disallowed, 148 149 ftl_last = Disallowed, 150 }; 151 HwVsyncState mHwVsyncState GUARDED_BY(mHwVsyncLock) = HwVsyncState::Disallowed; 152 153 // Pending state, in case an attempt is made to set the state while the 154 // device is off. 155 HwVsyncState mPendingHwVsyncState GUARDED_BY(kMainThreadContext) = HwVsyncState::Disabled; 156 157 class PredictedVsyncTracer; 158 using TracerPtr = std::unique_ptr<PredictedVsyncTracer>; 159 160 const PhysicalDisplayId mId; 161 const RequestHardwareVsync mRequestHardwareVsync; 162 const TrackerPtr mTracker; 163 const DispatchPtr mDispatch; 164 const ControllerPtr mController; 165 const TracerPtr mTracer; 166 }; 167 168 } // namespace android::scheduler 169