Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c99a001 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Move ownership of VsyncModulator to Scheduler

...as a prerequisite for calculating the VSYNC deadline of the leader
display (and deriving per-display state from it, e.g. present fences,
traces) in the Scheduler.

Bug: 241285475
Bug: 241285191
Test: Boot
Change-Id: Ieea136616435464dd0756525f94441b8e82ad06a
parent 933f8ded
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
namespace android {

class Layer;
class Scheduler;
class SurfaceFlinger;
struct SamplingOffsetCallback;

+33 −13
Original line number Diff line number Diff line
@@ -60,8 +60,12 @@

namespace android::scheduler {

Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
      : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
                     sp<VsyncModulator> modulatorPtr)
      : impl::MessageQueue(compositor),
        mFeatures(features),
        mVsyncModulator(std::move(modulatorPtr)),
        mSchedulerCallback(callback) {}

Scheduler::~Scheduler() {
    // MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -186,17 +190,19 @@ impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction(
    };
}

ConnectionHandle Scheduler::createConnection(const char* connectionName,
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
                                              frametimeline::TokenManager* tokenManager,
                                              std::chrono::nanoseconds workDuration,
                                              std::chrono::nanoseconds readyDuration) {
    auto throttleVsync = makeThrottleVsyncCallback();
    auto getVsyncPeriod = makeGetVsyncPeriodFunction();
    auto eventThread =
            std::make_unique<impl::EventThread>(connectionName, *mVsyncSchedule, tokenManager,
                                                std::move(throttleVsync), std::move(getVsyncPeriod),
    auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
                                                           *mVsyncSchedule, tokenManager,
                                                           makeThrottleVsyncCallback(),
                                                           makeGetVsyncPeriodFunction(),
                                                           workDuration, readyDuration);
    return createConnection(std::move(eventThread));

    auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
    handle = createConnection(std::move(eventThread));
    return handle;
}

ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
@@ -356,6 +362,20 @@ void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds wo
    thread->setDuration(workDuration, readyDuration);
}

void Scheduler::setVsyncConfigSet(const VsyncConfigSet& configs, Period vsyncPeriod) {
    setVsyncConfig(mVsyncModulator->setVsyncConfigSet(configs), vsyncPeriod);
}

void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
    setDuration(mAppConnectionHandle,
                /* workDuration */ config.appWorkDuration,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(mSfConnectionHandle,
                /* workDuration */ vsyncPeriod,
                /* readyDuration */ config.sfWorkDuration);
    setDuration(config.sfWorkDuration);
}

void Scheduler::enableHardwareVsync() {
    std::lock_guard<std::mutex> lock(mHWVsyncLock);
    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
+30 −4
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <ftl/optional.h>
#include <scheduler/Features.h>
#include <scheduler/Time.h>
#include <scheduler/VsyncConfig.h>
#include <ui/DisplayId.h>

#include "Display/DisplayMap.h"
@@ -47,6 +48,7 @@
#include "OneShotTimer.h"
#include "RefreshRateSelector.h"
#include "Utils/Dumper.h"
#include "VsyncModulator.h"
#include "VsyncSchedule.h"

namespace android::scheduler {
@@ -104,7 +106,7 @@ class Scheduler : android::impl::MessageQueue {
    using Impl = android::impl::MessageQueue;

public:
    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags);
    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>);
    virtual ~Scheduler();

    void startTimers();
@@ -146,7 +148,12 @@ public:
        return std::move(future);
    }

    ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*,
    enum class Cycle {
        Render,       // Surface rendering.
        LastComposite // Ahead of display compositing by one refresh period.
    };

    ConnectionHandle createEventThread(Cycle, frametimeline::TokenManager*,
                                       std::chrono::nanoseconds workDuration,
                                       std::chrono::nanoseconds readyDuration);

@@ -168,6 +175,18 @@ public:
    void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
                     std::chrono::nanoseconds readyDuration);

    const VsyncModulator& vsyncModulator() const { return *mVsyncModulator; }

    template <typename... Args,
              typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
    void modulateVsync(Handler handler, Args... args) {
        if (const auto config = (*mVsyncModulator.*handler)(args...)) {
            setVsyncConfig(*config, getLeaderVsyncPeriod());
        }
    }

    void setVsyncConfigSet(const VsyncConfigSet&, Period vsyncPeriod);

    // Sets the render rate for the scheduler to run at.
    void setRenderRate(Fps);

@@ -270,6 +289,7 @@ private:
    void displayPowerTimerCallback(TimerState);

    void setVsyncPeriod(nsecs_t period);
    void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);

    // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new
    // `mLeaderDisplayId` is never `std::nullopt`.
@@ -330,6 +350,9 @@ private:
    mutable std::mutex mConnectionsLock;
    std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock);

    ConnectionHandle mAppConnectionHandle;
    ConnectionHandle mSfConnectionHandle;

    mutable std::mutex mHWVsyncLock;
    bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false;
    bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false;
@@ -339,6 +362,9 @@ private:
    const FeatureFlags mFeatures;
    std::optional<VsyncSchedule> mVsyncSchedule;

    // Shifts the VSYNC phase during certain transactions and refresh rate changes.
    const sp<VsyncModulator> mVsyncModulator;

    // Used to choose refresh rate if content detection is enabled.
    LayerHistory mLayerHistory;

+1 −9
Original line number Diff line number Diff line
@@ -25,21 +25,13 @@
#include <binder/IBinder.h>
#include <utils/Timers.h>

#include <scheduler/TransactionSchedule.h>
#include <scheduler/VsyncConfig.h>

#include "../WpHash.h"

namespace android::scheduler {

// State machine controlled by transaction flags. VsyncModulator switches to early phase offsets
// when a transaction is flagged EarlyStart or Early, lasting until an EarlyEnd transaction or a
// fixed number of frames, respectively.
enum class TransactionSchedule {
    Late,  // Default.
    EarlyStart,
    EarlyEnd
};

// Modulates VSYNC phase depending on transaction schedule and refresh rate changes.
class VsyncModulator : public IBinder::DeathRecipient {
public:
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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

namespace android::scheduler {

// State machine controlled by transaction flags. VsyncModulator switches to early phase offsets
// when a transaction is flagged EarlyStart or Early, lasting until an EarlyEnd transaction or a
// fixed number of frames, respectively.
enum class TransactionSchedule {
    Late, // Default.
    EarlyStart,
    EarlyEnd
};

} // namespace android::scheduler
Loading