/* * 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. */ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include #include #include "VsyncSchedule.h" #include "VSyncDispatchTimerQueue.h" #include "VSyncPredictor.h" #include "VSyncReactor.h" #include "../TracedOrdinal.h" namespace android::scheduler { class VsyncSchedule::PredictedVsyncTracer { // Invoked from the thread of the VsyncDispatch owned by this VsyncSchedule. constexpr auto makeVsyncCallback() { return [this](nsecs_t, nsecs_t, nsecs_t) { mParity = !mParity; schedule(); }; } public: explicit PredictedVsyncTracer(VsyncDispatch& dispatch) : mRegistration(dispatch, makeVsyncCallback(), __func__) { schedule(); } private: void schedule() { mRegistration.schedule({0, 0, 0}); } TracedOrdinal mParity = {"VSYNC-predicted", 0}; VSyncCallbackRegistration mRegistration; }; VsyncSchedule::VsyncSchedule(FeatureFlags features) : mTracker(createTracker()), mDispatch(createDispatch(*mTracker)), mController(createController(*mTracker, features)) { if (features.test(Feature::kTracePredictedVsync)) { mTracer = std::make_unique(*mDispatch); } } VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller) : mTracker(std::move(tracker)), mDispatch(std::move(dispatch)), mController(std::move(controller)) {} VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default; VsyncSchedule::~VsyncSchedule() = default; void VsyncSchedule::dump(std::string& out) const { out.append("VsyncController:\n"); mController->dump(out); out.append("VsyncDispatch:\n"); mDispatch->dump(out); } VsyncSchedule::TrackerPtr VsyncSchedule::createTracker() { // TODO(b/144707443): Tune constants. constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs(); constexpr size_t kHistorySize = 20; constexpr size_t kMinSamplesForPrediction = 6; constexpr uint32_t kDiscardOutlierPercent = 20; return std::make_unique(kInitialPeriod, kHistorySize, kMinSamplesForPrediction, kDiscardOutlierPercent); } VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(VsyncTracker& tracker) { using namespace std::chrono_literals; // TODO(b/144707443): Tune constants. constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us; constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms; return std::make_unique(std::make_unique(), tracker, kGroupDispatchWithin.count(), kSnapToSameVsyncWithin.count()); } VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& tracker, FeatureFlags features) { // TODO(b/144707443): Tune constants. constexpr size_t kMaxPendingFences = 20; const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer); auto reactor = std::make_unique(std::make_unique(), tracker, kMaxPendingFences, hasKernelIdleTimer); reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences)); return reactor; } } // namespace android::scheduler