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

Commit 14956dc4 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Reset VsyncModulator on active display change

Between VsyncModulator::onRefreshRateChange{Initiated,Completed}, if the
active display changes, the newly active display's VsyncConfiguration is
propagated to VsyncModulator via updatePhaseConfiguration, which selects
VsyncConfigType::Early due to the `mRefreshRateChangePending` of the now
inactive display.

Clear `mRefreshRateChangePending` and let `onRefreshRateChangeInitiated`
set it for the newly active display if needed.

In practice, the end result is the same due to the forced modeset for an
active display that was just powered on. However, this will no longer be
true with concurrent displays when the new pacesetter is already powered
on.

Bug: 255635821
Test: DisplayModeSwitchingTest.multiDisplay
Change-Id: If264742a107cf5839d2c820eab23712778c1ae2e
parent 360ae785
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -165,7 +165,7 @@ public:
    void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
                     std::chrono::nanoseconds readyDuration);

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

    // In some cases, we should only modulate for the pacesetter display. In those
    // cases, the caller should pass in the relevant display, and the method
+2 −2
Original line number Diff line number Diff line
@@ -187,9 +187,9 @@ void VsyncModulator::binderDied(const wp<IBinder>& who) {
    static_cast<void>(updateVsyncConfigLocked());
}

bool VsyncModulator::isVsyncConfigDefault() const {
bool VsyncModulator::isVsyncConfigEarly() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return getNextVsyncConfigType() == VsyncConfigType::Late;
    return getNextVsyncConfigType() != VsyncConfigType::Late;
}

} // namespace android::scheduler
+4 −2
Original line number Diff line number Diff line
@@ -53,8 +53,12 @@ public:

    explicit VsyncModulator(const VsyncConfigSet&, Now = Clock::now);

    bool isVsyncConfigEarly() const EXCLUDES(mMutex);

    VsyncConfig getVsyncConfig() const EXCLUDES(mMutex);

    void cancelRefreshRateChange() { mRefreshRateChangePending = false; }

    [[nodiscard]] VsyncConfig setVsyncConfigSet(const VsyncConfigSet&) EXCLUDES(mMutex);

    // Changes offsets in response to transaction flags or commit.
@@ -72,8 +76,6 @@ public:

    [[nodiscard]] VsyncConfigOpt onDisplayRefresh(bool usedGpuComposition);

    [[nodiscard]] bool isVsyncConfigDefault() const;

protected:
    // Called from unit tests as well
    void binderDied(const wp<IBinder>&) override EXCLUDES(mMutex);
+9 −7
Original line number Diff line number Diff line
@@ -3452,7 +3452,7 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,

            // TODO(b/175678251) Call a listener instead.
            if (currentState.physical->hwcDisplayId == getHwComposer().getPrimaryHwcDisplayId()) {
                updateActiveDisplayVsyncLocked(*display);
                resetPhaseConfiguration(display->getActiveMode().fps);
            }
        }
        return;
@@ -3486,9 +3486,11 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
    }
}

void SurfaceFlinger::updateActiveDisplayVsyncLocked(const DisplayDevice& activeDisplay) {
void SurfaceFlinger::resetPhaseConfiguration(Fps refreshRate) {
    // Cancel the pending refresh rate change, if any, before updating the phase configuration.
    mScheduler->vsyncModulator().cancelRefreshRateChange();

    mVsyncConfiguration->reset();
    const Fps refreshRate = activeDisplay.getActiveMode().fps;
    updatePhaseConfiguration(refreshRate);
    mRefreshRateStats->setRefreshRate(refreshRate);
}
@@ -4303,9 +4305,8 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const sp<Layer>& layer, const layer_s
        // We don't want to latch unsignaled if are in early / client composition
        // as it leads to jank due to RenderEngine waiting for unsignaled buffer
        // or window animations being slow.
        const auto isDefaultVsyncConfig = mScheduler->vsyncModulator().isVsyncConfigDefault();
        if (!isDefaultVsyncConfig) {
            ALOGV("%s: false (LatchUnsignaledConfig::AutoSingleLayer; !isDefaultVsyncConfig)",
        if (mScheduler->vsyncModulator().isVsyncConfigEarly()) {
            ALOGV("%s: false (LatchUnsignaledConfig::AutoSingleLayer; isVsyncConfigEarly)",
                  __func__);
            return false;
        }
@@ -7692,7 +7693,8 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD
    mActiveDisplayId = activeDisplay.getPhysicalId();
    activeDisplay.getCompositionDisplay()->setLayerCachingTexturePoolEnabled(true);

    updateActiveDisplayVsyncLocked(activeDisplay);
    resetPhaseConfiguration(activeDisplay.getActiveMode().fps);

    mScheduler->setModeChangePending(false);
    mScheduler->setPacesetterDisplay(mActiveDisplayId);

+2 −3
Original line number Diff line number Diff line
@@ -736,6 +736,8 @@ private:
    void updateCursorAsync();

    void initScheduler(const sp<const DisplayDevice>&) REQUIRES(kMainThreadContext, mStateLock);

    void resetPhaseConfiguration(Fps) REQUIRES(mStateLock, kMainThreadContext);
    void updatePhaseConfiguration(Fps) REQUIRES(mStateLock);

    /*
@@ -1120,9 +1122,6 @@ private:
                                               std::chrono::nanoseconds presentLatency);
    int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;

    void updateActiveDisplayVsyncLocked(const DisplayDevice& activeDisplay)
            REQUIRES(mStateLock, kMainThreadContext);

    bool isHdrLayer(const frontend::LayerSnapshot& snapshot) const;

    ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const
Loading