Skip to content

slmcrs/nv-settings-wayland

 
 

Repository files navigation

nVibrant

Configure NVIDIA's Digital Vibrance on Wayland

Important

This repository is a proof of concept that will be improved over time, e.g. proper CLI and distro packaging are WIP. Contributions are welcome, as I'm not primarily a C/C++ developer 🙂

🔥 Description

NVIDIA GPUs have a nice feature called Digital Vibrance that increases the colors saturation of the display. The option is readily available on nvidia-settings in Linux, but is too coupled with libxnvctrl. Therefore, it's "exclusive" to the X11 display server and unavailable on Wayland; but I paid for them pixels to glow :^)

An interesting observation is that the setting persists after modifying it on X11 and then switching to Wayland. I theorized [1] [2] it was possible to call some shared library or interface to configure it directly in their driver, independently of the display server. And indeed, it is possible!

This repository uses nvidia-modeset and nvkms headers found at NVIDIA/open-gpu-kernel-modules to make ioctl calls in the /dev/nvidia-modeset device for configuring display attributes. These headers are synced with the proprietary releases, should work fine if you're on any of nvidia-dkms, nvidia-open or nvidia.

Note: A future (and intended) way to will be through NVML, as evident by some nvidia-settings comments.

🚀 Usage

Grab the latest Prebuilt Release, download from your Package Manager or Build it Yourself to get the binary. Remember to run chmod +x nvibrant* to mark the file as executable!

Note: You might need to set nvidia_drm.modeset=1 kernel parameter, but I think it's enabled by default on recent drivers.

Basic usage

Inputs: Vibrance Levels are numbers from -1024 to 1023 that determines the intensity of the effect. Zero being the default for all displays at boot, -1024 grayscale, and 1023 max saturation (200%).

The values are passed as arguments to nvibrant, and the order must match the physical outputs of the output ports in your GPU (not the index of the video server). For example, I have two monitors on DisplayPort and HDMI in an RTX 3060, and want to set the vibrance to 512 and 1023 respectively:

$ ./nvibrant 512 1023
Driver version: (570.133.07)

GPU 0:
• (0, HDMI) • Set Vibrance (  512) • Success
• (1, DP  ) • Set Vibrance ( 1023) • Success
• (2, DP  ) • Set Vibrance (    0) • None
• (3, DP  ) • Set Vibrance (    0) • None
• (4, DP  ) • Set Vibrance (    0) • None
• (5, DP  ) • Set Vibrance (    0) • None
• (6, DP  ) • Set Vibrance (    0) • None

If a value is not passed for the Nth physical output, nvibrant will default to zero. When no argument is passed, it will effectively clear the vibrance for all outputs. None means the output is disconnected.

⚠️ You might have a display only at the later ports, in which case use as:

$ ./nvibrant 0 0 0 1023
Driver version: (570.133.07)

GPU 0:
• (0, HDMI) • Set Vibrance (    0) • None
• (1, DP  ) • Set Vibrance (    0) • None
• (2, DP  ) • Set Vibrance (    0) • None
• (3, DP  ) • Set Vibrance ( 1023) • Success
• (4, DP  ) • Set Vibrance (    0) • None

Multiple Displays on Multiple GPUs

If you have multiple displays on multiple GPUs, it should work too:

$ ./nvibrant 0 100 512 1023
Driver version: (570.133.07)

GPU 0:
• (0, HDMI) • Set Vibrance (    0) • Success
• (1, DP  ) • Set Vibrance (  100) • Success

GPU 1:
• (0, HDMI) • Set Vibrance (  512) • Success
• (1, DP  ) • Set Vibrance ( 1023) • Success

Common issues

  • If you get a "Driver version mismatch" or ioctl errors, maybe try rebooting (if you haven't) since the last driver update. Otherwise, you can force the version with NVIDIA_DRIVER_VERSION=x.y.z. It must match what /dev/nvidia-modeset expects and is currently loaded in ther kernel.

  • It's possible that nVibrant may fail on future or older drivers due to differences between the internal structs and enums in the latest nvkms headers. Please report any issues you encounter!

❤️ Consider supporting my work, this took 16 hours to figure out and implement :)

📦 Compiling

Pre-requisites: Have git, uv and GCC Compiler installed, then run:

  • git clone https://github.com/Tremeschin/nVibrant && cd nVibrant
  • git submodule update --init --recursive
  • uv run nvibrant-build

You should have the executable located at release/nvibrant*

⭐️ Future work

Integrating this work directly in libvibrant would be the ideal solution, although matching the nvidia driver version could be annoying for a generalized solution. Feel free to base off this code for an upstream solution and PR, in the meantime, here's some local improvements that could be made:

  • Make an actual CLI interface with --help, --version, etc.
  • Package the binary in many linux distros (help needed!)
  • Save the current values to restore it later.
  • I am probably not doing safe-C code or mallocs right :^)

Contributions are welcome if you are more C/C++ savy than me! 🙂

About

Change nvidia settings in wayland

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 73.4%
  • Python 19.8%
  • Meson 6.8%