Repository navigation
Add an opt-in power-saving mode for mpv video wallpapers - #37
Merged
Merged
Conversation
A 1080p60 video wallpaper costs a lot on a laptop with a high-refresh panel. Measured on a 2520x1680@120 Hz Intel Iris Xe laptop with a separate mpv on the same file: CPU 30.4% -> 16.7% and GPU render busy 28.4% -> 6.4% with the settings below; inside plasmashell the video wallpaper went from 22-30% to ~7.5% CPU. Most of it is two defaults: display-resample re-renders on every vblank (120/s for a 60 fps file), and the default lanczos-class scaler chain is expensive for a picture nobody inspects up close. Both defaults are deliberate here (display-resample hides loop-wrap judder), so this is an opt-in switch, MpvPowerSaving, default off, in the Mpv section of the settings page. When on: - MpvObject::setPowerSaving applies mpv's built-in `fast` profile options (bilinear scale/dscale, no dither, no linear/sigmoid/correct downscaling, no HDR peak detection) and video-sync=audio, which with no audio track presents frames at the video's own rate. It saves the previous values first and puts exactly those back when switched off, since mpv's own defaults for them vary by version. - Mpv.qml sets the new MpvObject.maxFps to the scene Fps setting, so a 60 fps file is drawn at most that many times a second: a redraw requested inside the frame interval is folded into one deferred redraw (frameCapDelayMs), which then shows mpv's newest frame. With the switch off nothing changes: no options are touched and maxFps stays 0 (every frame drawn, as before). Tests: tst_mpvbackend checks that the options are applied and restored to their previous values, that nothing changes by default, the frameCapDelayMs table and maxFps clamping; tst_backend_mpv checks the QML bindings (off by default, cap follows the Fps setting live).
During a wallpaper handoff the old backend stays on screen while its settings already describe the next wallpaper. Mpv.qml's freezeOptions() now also pins the player's powerSaving and maxFps, so toggling power saving or moving the Fps slider mid-handoff no longer reaches a player that prepareDestroy() is already stopping. tst_backend_mpv.qml: test_freezeOptions_keeps_power_saving changes both settings after freezeOptions() and checks the player kept its values.
CaptSilver
approved these changes
Oct 13, 2026
CaptSilver
approved these changes
Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Measurements
A 1080p60 video wallpaper is expensive on a high-refresh laptop panel. With the settings below, on the same file in a separate mpv:
Inside plasmashell, with the frame cap below as well, the video wallpaper went from 22-30% to about 7.5% CPU (on a build based on an older
main, 5c3d184).Most of the cost comes from two defaults:
display-resamplere-renders on every vblank (120/s for a 60 fps file), and the lanczos-class scaler chain is expensive.Change
Both defaults are deliberate (display-resample hides loop-wrap judder), so this is an opt-in switch,
MpvPowerSaving, default off, in the Mpv section of the settings page.When on:
setPowerSaving()applies the options of mpv's built-infastprofile, plusvideo-sync=audio.maxFpsfollows the scene Fps setting. Redraw requests inside the frame interval are folded into one deferred redraw (frameCapDelayMs).With the switch off, nothing changes.
Tests
tst_mpvbackend: options applied and restored; nothing changes by default; theframeCapDelayMstable;maxFpsclamping.tst_backend_mpv.qml: the bindings.(If P3 lands first,
tests/tst_mpvbackend.cppgets a trivial append-only conflict; I'll rebase.)tools/scripts/preflight.shpasses (run inside afedora-toolbox:latestcontainer built fromDEPS_FEDORA,WEK_IN_CI=1). One note: on this laptop the fuzz step times out on the checked-in seedtests/fuzz_corpus/WPShaderCompile/seed/58392d50…(~33 s per compile under ASAN+UBSAN, identical on cleanmain), so I ran preflight with--no-fuzzand then all fuzz targets with the same settings except-timeout=60: no findings.Setup: Plasma 6 (Wayland), KWin, Intel Iris Xe (RPL-P), 2520x1680 @ 120 Hz laptop panel, Manjaro.