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

Commit 9ba25125 authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: HWVsync when display is off

HWC expects that HWVsync will not be turned on if display if off.
To ensure that we move enabling/disabling of HWVsync to the main thread
and caching the latest request in case the display is off. When the
display is turned on again we apply the latest state of HWVsync.

Bug: 134050982
Test: Toggle screen on/off in a loop
Change-Id: Ib87f885f95195b8bb402d5a5b2c75f20e213d2aa
parent 2eeb9c63
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -1537,10 +1537,25 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDispl

void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
    ATRACE_CALL();
    Mutex::Autolock lock(mStateLock);

    // Enable / Disable HWVsync from the main thread to avoid race conditions with
    // display power state.
    postMessageAsync(new LambdaMessage(
            [=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
}

void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
    ATRACE_CALL();

    if (const auto displayId = getInternalDisplayIdLocked()) {
        sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
        if (display && display->isPoweredOn()) {
            getHwComposer().setVsyncEnabled(*displayId,
                                            enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
        } else {
            // Cache the latest vsync state and apply it when screen is on again
            mEnableHWVsyncScreenOn = enabled;
        }
    }
}

@@ -4438,6 +4453,11 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int
        // Turn on the display
        getHwComposer().setPowerMode(*displayId, mode);
        if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
            if (mEnableHWVsyncScreenOn) {
                setPrimaryVsyncEnabledInternal(mEnableHWVsyncScreenOn);
                mEnableHWVsyncScreenOn = false;
            }

            mScheduler->onScreenAcquired(mAppConnectionHandle);
            mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
        }
+6 −0
Original line number Diff line number Diff line
@@ -293,6 +293,9 @@ public:
    // TODO: this should be made accessible only to EventThread
    void setPrimaryVsyncEnabled(bool enabled);

    // main thread function to enable/disable h/w composer event
    void setPrimaryVsyncEnabledInternal(bool enabled);

    // called on the main thread by MessageQueue when an internal message
    // is received
    // TODO: this should be made accessible only to MessageQueue
@@ -1166,6 +1169,9 @@ private:
    // The Layer pointer is removed from the set when the destructor is called so there shouldn't
    // be any issues with a raw pointer referencing an invalid object.
    std::unordered_set<Layer*> mOffscreenLayers;

    // Flag to indicate whether to re-enable HWVsync when screen is on
    bool mEnableHWVsyncScreenOn = false;
};

} // namespace android