[WORKAROUND] Doesn't work if using custom xrandr refresh rates/resolutions
UPDATE: You can use a pretty simple xorg.conf to work around the issue by simply adding refresh rates to existing resolutions.
Create a new text file named "xorg.conf" located in /etc/X11 (you will need to be root in order to write to that location) and add the following to the text file:
Section "Monitor"
Identifier "[TYPE_DISPLAY_OUTPUT_CONNECTION_HERE]"
Modeline [PASTE_CVT_MODELINE_WITHOUT_REFRESH-RATE_HERE]
EndSection
Open the terminal and type xrandr
to find out the name of the video connection for your desired display output - it may be something like HDMI0
, eDP
, DisplayPort-1
etc. Regardless of what it is, replace the text [TYPE_DISPLAY_OUTPUT_CONNECTION_HERE]
in the xorg.conf file with the name in question (at least on the Cinnamon desktop environment, its "Display" program actually shows these names without the need to use the terminal); in my case it was DisplayPort-1
.
Now get the modeline and timing information for your desired custom resolution like normal via cvt in the terminal, e.g. cvt 1280 1024 75
for 1280x1024 @ 75Hz which results in:
# 1280x1024 74.90 Hz (CVT 1.31M4) hsync: 80.30 kHz; pclk: 138.75 MHz
Modeline "1280x1024_75.00" 138.75 1280 1368 1504 1728 1024 1027 1034 1072 -hsync +vsync
Copy and paste the part after Modeline
into the xorg.conf file in-place of the text that says[PASTE_CVT_MODELINE_WITHOUT_REFRESH-RATE_HERE]
and then remove the part of the modeline that usually contains the refresh rate e.g. the _75.00
part of my example. You can also optionally add a line above the Modeline
beginning with # to help note what each modeline is, and you can even add multiple Modeline
lines.
The result should be the following - in my case adding Modeline
lines for both 75Hz and 50Hz:
Section "Monitor"
Identifier "DisplayPort-1"
# 1280x1024 @ 75Hz
Modeline "1280x1024" 138.69 1280 1368 1504 1725 1024 1027 1034 1072 -hsync +vsync
# 1280x1024 @ 50Hz
Modeline "1280x1024" 88.55 1280 1368 1496 1666 1024 1027 1034 1063 -hsync +vsync
EndSection
After that, simply log out and log back in and everything, including this xrandr.lua script, should "just work". If you run xrandr
in the terminal you should now see the existing resolution (in my case 1280x1024) but now with your additionally-added custom refresh rate (in my case 75Hz).
As a side benefit, the OS will actually remember your custom refresh rate the next time you log back in and you don't need to have it automatically run a command to switch refresh rates every single time.
Also, to be clear, you can use this method to create custom resolutions that didn't exist before-hand as well, such as the below-mentioned 1082p example.
UPDATE 2: The following may no longer be applicable to the newest version as of 2024, but in the previous version(s) I found that the default precision for selecting refresh rates was a bit too precise, sometimes making it difficult for mpv-plugin-xrandr to select the correct refresh rate since custom resolutions do not always have super-exact refresh rates.
So, in the older version of xrandr.lua, you'd simply change line 162 from:
if (math.abs(r-(m * fps)) < 0.002) then
To:
if (math.abs(r-(m * fps)) < 0.01) then
(0.01 being slightly less than half of the difference between 24.000 and 23.976 which itself is a difference of 0.024)
ORIGINAL POST
For reference, this was tested on both Linux Mint 20.3 Cinnamon and Linux Mint 20.3 XFCE and, hardware-wise, was tested on both a Ryzen 4800U (with AMD integrated graphics) over DisplayPort and an Intel 4th gen Haswell G3258 (with Intel integrated graphics) over VGA and HDMI.
Custom resolutions were created by running the following in a .sh bash script on startup since xorg.conf has been depreciated for a while now (I'm using an example of a basic 1280x1024@75Hz, but any custom resolution should do it):
xrandr --newmode "1280x1024_75.00" 138.75 1280 1368 1504 1728 1024 1027 1034 1072 -hsync +vsync
xrandr --addmode DisplayPort-1 1280x1024_75.00
xrandr --output DisplayPort-1 --mode 1280x1024_75.00
Anyway, this script simply doesn't seem to know how to handle custom xrandr refresh rates/resolutions and seemingly straight-up ignores and never selects them.
Furthermore, if your currently-active refresh rate/resolution is a custom one, then this script will straight-up do nothing.
If your currently-active refresh rate/resolution is a custom one and you have script-opts=xrandr-ignore_unknown_oldrate=true
in your mpv.conf file, then this script will instead just always change to a non-custom refresh rate/resolution (even if the refresh rate you were running before launching mpv was actually the best fit) and will not revert back to the previous refresh rate once mpv closes.
This is particularly problematic for me as I have multiple displays that are "dumb" in terms of their EDIDs; e.g. the LCD monitor I'm typing this from only lists 75Hz at legacy VESA resolutions like 1024x768 yet when actually running at the monitor's native resolution, it only lists 60Hz...despite a custom resolution of 75Hz working without issue.
Furthermore, I have a second monitor that only lists 60Hz and 75Hz in its default EDID but, with a custom refresh rate, I've been able to set rates like 72Hz, 90Hz, etc.
I also have a couple laptops that similarly only list 60Hz and yet I've been able to make custom refresh rates from 48Hz all the way to 100Hz.
(and yes, I've confirmed that all of the displays I've tested these custom refresh rates on do not skip frames)
Lastly, while I've not yet tested the following with this script, I know that there at least used to be long-standing issues with getting full 0-255 color range as well as full 4:4:4 chroma if you were outputting a 1080p video signal, and the workaround I know of that works on AMD GPUs is to instead use a custom resolution with a slightly-different vertical resolution such as 1078p, 1082p, etc. I would imagine this would similarly straight-up break this script's functionality which would be a shame as my HTPC is the last desktop PC that I've yet to move over to Linux (I'm just waiting on Linux Mint 21.0 as well as Rusticl).
EDIT
After looking at some xrandr and mpv logs and such, I can't help but notice that custom refresh rates, even at an existing resolution, are treated by xrandr as completely separate resolutions.
So even if I make a custom refresh rate of 1280x1024 @ 75Hz on a 60Hz 1280x1024 monitor, this script still sees that there's only 60Hz available for the resolution of 1280x1024 because 75Hz is under the different resolution of "1280x1024_75.00".
And if you were currently running the custom refresh rate, the script reports not touching output DisplayPort-1 because xrandr did not indicate a used refresh rate for it - use --script-opts=xrandr-ignore_unknown_oldrate=true if that is not what you want.
...but because the monitor's built-in EDID only lists 60Hz as the only refresh rate, script-opts=xrandr-ignore_unknown_oldrate=true
always just makes mpv switch to 60Hz no matter what (even for 25fps videos) and then it'll remain at 60Hz even when mpv is closed.
It may also be worth noting that script-opts=xrandr-output-mode=
doesn't work with custom resolutions either, e.g. "1280x1024_75.00"