Skip to content

Add an opt-in power-saving mode for mpv video wallpapers - #37

Merged
CaptSilver merged 4 commits into
CaptSilver:mainfrom
Makoi66:perf/mpv-power-saving
Oct 13, 2026
Merged

CaptSilver merged 4 commits into
CaptSilver:mainfrom
Makoi66:perf/mpv-power-saving

Conversation

@Makoi66

@Makoi66 Makoi66 commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

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:

before after
CPU 30.4% 16.7%
GPU render busy 28.4% 6.4%

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-resample re-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-in fast profile, plus video-sync=audio.
  • It saves the previous values first and restores exactly those when switched off, because mpv's defaults differ between versions.
  • maxFps follows 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; the frameCapDelayMs table; maxFps clamping.
  • tst_backend_mpv.qml: the bindings.

(If P3 lands first, tests/tst_mpvbackend.cpp gets a trivial append-only conflict; I'll rebase.)

tools/scripts/preflight.sh passes (run inside a fedora-toolbox:latest container built from DEPS_FEDORA, WEK_IN_CI=1). One note: on this laptop the fuzz step times out on the checked-in seed tests/fuzz_corpus/WPShaderCompile/seed/58392d50… (~33 s per compile under ASAN+UBSAN, identical on clean main), so I ran preflight with --no-fuzz and 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.

Makoi66 and others added 3 commits September 30, 2026 15:22
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
CaptSilver merged commit 3807621 into CaptSilver:main Oct 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants