Investigate power management/DPMS flickering

When turning off a screen to save power, and using the "modern" approach of disabling CRTCs (via Smithay's DrmCompositor::clear()), on some hardware, all screens flicker for a bit when turning off one screen.

But when using the legacy DPMS method (which I believe doesn't touch the CRTC, just the connector), there's no flicker. The downside here is that this is a legacy method that could stop working at any time, and, worse, the DRM driver may not even raise an error if it doesn't work.

The current code uses the DPMS method, and if there's an explicit error (or if reading the property back after setting it shows the setting hasn't taken), it falls back to the CRTC method. But it would be good to investigate the CRTC method deeper and see if there's a way to improve that situation.

Ultimately this may not be so important: the common case will be for power management to kick in on all displays simultaneously when an idle timer fires. But it could be interesting to look into this more deeply anyway.

Some notes from @drakulix on matrix:

Hmm, this is curious. So what DrmCompositor::clear (or also DrmSurface::clear_state) does should be equal to DPMS. In case the DrmSurface is using the legacy api, it changes the DPMS property just like you would expect. For the atomic API the correct way to do the same is to set the ACTIVE property.

I wouldn't recommend in general to use the legacy api explicitly anymore and certainly not mixing it, which might be able to get the whole state into a weird state (though it shouldn't and that would be considered a kernel bug, but I don't think this is well tested).

No why using the atomic / smithay-built-in api is causing your remaining output to modeset, I cannot tell you. We clear some planes, I don't think that should affect it, but this might depend on your display hardware.

You can try messing with some of logic in src/backend/drm/surface/atomic.rs to see if skipping some stuff gives you a flicker-free experience and then we can try and figure out, if we can somehow make this the default.

Additionally you can try to enable drm-logging (see e.g. https://gitlab.freedesktop.org/wlroots/wlroots/-/wikis/DRM-Debugging) and see if the kernel tells us, why it is touching the internal connector.

@ids1024 mentioned they've seen that as well, and added a reference to https://github.com/pop-os/cosmic-comp/pull/2028 which may be related.

Edited by Brian Tarricone