blob: 881d6789b2bbd5a4967d047d3f25c8e59c46662b [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <android-base/thread_annotations.h>
#include <ThreadContext.h>
#include <ftl/enum.h>
#include <ftl/optional.h>
#include <ui/DisplayId.h>
#include <scheduler/Features.h>
#include <scheduler/IVsyncSource.h>
#include <scheduler/Time.h>
#include "ThreadContext.h"
#include "VSyncTracker.h"
namespace android {
class EventThreadTest;
class VsyncScheduleTest;
}
namespace android::fuzz {
class SchedulerFuzzer;
}
namespace android::scheduler {
// TODO(b/185535769): Rename classes, and remove aliases.
class VSyncDispatch;
class VSyncTracker;
class VsyncController;
using VsyncDispatch = VSyncDispatch;
using VsyncTracker = VSyncTracker;
// Schedule that synchronizes to hardware VSYNC of a physical display.
class VsyncSchedule final : public IVsyncSource {
public:
using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync);
~VsyncSchedule();
// IVsyncSource overrides:
Period period() const override;
TimePoint vsyncDeadlineAfter(TimePoint,
ftl::Optional<TimePoint> lastVsyncOpt = {}) const override;
Period minFramePeriod() const override;
// Inform the schedule that the display mode changed the schedule needs to recalibrate
// itself to the new vsync period. The schedule will end the period transition internally.
// This will enable hardware VSYNCs in order to calibrate.
//
// \param [in] DisplayModePtr The mode that the display is changing to.
// \param [in] force True to force a transition even if it is not a
// change.
void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force);
// Pass a VSYNC sample to VsyncController. Return true if
// VsyncController detected that the VSYNC period changed. Enable or disable
// hardware VSYNCs depending on whether more samples are needed.
bool addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod);
// TODO(b/185535769): Hide behind API.
VsyncTracker& getTracker() const { return *mTracker; }
VsyncTracker& getTracker() { return *mTracker; }
VsyncController& getController() { return *mController; }
// TODO(b/185535769): Once these are hidden behind the API, they may no
// longer need to be shared_ptrs.
using DispatchPtr = std::shared_ptr<VsyncDispatch>;
using TrackerPtr = std::shared_ptr<VsyncTracker>;
// TODO(b/185535769): Remove once VsyncSchedule owns all registrations.
DispatchPtr getDispatch() { return mDispatch; }
void dump(std::string&) const;
// Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which
// case this call is ignored.
void enableHardwareVsync() EXCLUDES(mHwVsyncLock);
// Disable hardware VSYNCs. If `disallow` is true, future calls to
// enableHardwareVsync are ineffective until isHardwareVsyncAllowed is
// called with `makeAllowed` set to true.
void disableHardwareVsync(bool disallow) EXCLUDES(mHwVsyncLock);
// If true, enableHardwareVsync can enable hardware VSYNC (if not already
// enabled). If false, enableHardwareVsync does nothing.
bool isHardwareVsyncAllowed(bool makeAllowed) EXCLUDES(mHwVsyncLock);
void setPendingHardwareVsyncState(bool enabled) REQUIRES(kMainThreadContext);
bool getPendingHardwareVsyncState() const REQUIRES(kMainThreadContext);
protected:
using ControllerPtr = std::unique_ptr<VsyncController>;
static void NoOpRequestHardwareVsync(PhysicalDisplayId, bool) {}
// For tests.
VsyncSchedule(PhysicalDisplayId, TrackerPtr, DispatchPtr, ControllerPtr,
RequestHardwareVsync = NoOpRequestHardwareVsync);
private:
friend class TestableScheduler;
friend class android::EventThreadTest;
friend class android::VsyncScheduleTest;
friend class android::fuzz::SchedulerFuzzer;
static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr);
static DispatchPtr createDispatch(TrackerPtr);
static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);
void enableHardwareVsyncLocked() REQUIRES(mHwVsyncLock);
mutable std::mutex mHwVsyncLock;
enum class HwVsyncState {
// Hardware VSYNCs are currently enabled.
Enabled,
// Hardware VSYNCs are currently disabled. They can be enabled by a call
// to `enableHardwareVsync`.
Disabled,
// Hardware VSYNCs are not currently allowed (e.g. because the display
// is off).
Disallowed,
ftl_last = Disallowed,
};
HwVsyncState mHwVsyncState GUARDED_BY(mHwVsyncLock) = HwVsyncState::Disallowed;
// Pending state, in case an attempt is made to set the state while the
// device is off.
HwVsyncState mPendingHwVsyncState GUARDED_BY(kMainThreadContext) = HwVsyncState::Disabled;
class PredictedVsyncTracer;
using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
const PhysicalDisplayId mId;
const RequestHardwareVsync mRequestHardwareVsync;
const TrackerPtr mTracker;
const DispatchPtr mDispatch;
const ControllerPtr mController;
const TracerPtr mTracer;
};
} // namespace android::scheduler