6

I can set the display scaling mode for the internal laptop panel with:

xrandr --output LVDS1 --set "scaling mode" "Full aspect" This however does not work for external displays (DP1, VGA1, DP1) because the scaling mode property is not supported:

$> xrandr --output HDMI1 --set "scaling mode" "Full aspect"
X Error of failed request:  BadName (named color or font does not exist)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  11 (RRQueryOutputProperty)
  Serial number of failed request:  47
  Current serial number in output stream:  47

How can I preserve the aspect ratio when displaying a lower resolution content?

2 Answers 2

8

The Scaling mode property is not yet implemented in the intel driver (see here). It is implemented in the proprietary AMD and NVIDIA drivers and since recentlty in the open source radeon driver (here).

However you can work around this limitation by performing the scaling manually with xrandr:

Assume your screen has a native resolution of 1920x1080 and you want to display an unstretched 1024x768 resolution. The proportion of the aspect ratios is 16/9 to 4/3. so 1.333333 to 1.

xrandr --output HDMI1 --mode 1024x768 --scale 1.33333333x1 --panning 1024x768

This puts the screen in the right resolution with the right aspect ratio. But it is not centered. To achieve this we need to use the transform option to put it (roughly) in the center of the screen (1024*1.3333333 - 1024 = 342 / 2 = 171):

xrandr --output HDMI1 --mode 1024x768 --panning 1024x768 --transform 1.33333333,0,-171,0,1,0,0,0,1

Unfortunately the unused screen background is gray and or garbled and not black.

3
  • It seems this sort of scaling cause a lot of tearing when watching videos.
    – Kun
    Jan 22, 2017 at 23:31
  • I believe scaling should be possible on Intel hardware, provided that's found on laptops or other "embedded" environments. Nouveau.. should work I reckon (if any devs seem unsure on the defaults)? The only other meaningful thing missing it should be very old ATi cards.
    – mirh
    Nov 9, 2019 at 0:45
  • Is there any update? Can we set lower resolution without stretching
    – Anwar
    Feb 10, 2021 at 7:15
2

The accepted answer was almost what I needed to render a lower resolution with black borders using an Intel GPU. My goal was to render a 1920x1080 framebuffer in a 5120x1440 super ultrawide native resolution, centered with black borders (for screencasting):

xrandr \
    --output DP-1 \
    --mode 5120x1440 \
    --fb 1920x1080 \
    --transform 2.666666667,0,1600,0,1.33333333333,180,0,0,1 \
    --panning 1920x1080

A detailed explanation of the parameters:

  • output: output port (eg. DP-1, HDMI-1, etc.)
  • mode: monitor display mode (eg. native resolution)
  • fb: framebuffer size
  • transform: 3x3 affine transformation matrix describing how to transform the geometry of the rendered output within the monitor geometry; in other words, "how" to position the framebuffer on the display
  • panning: the total area available to the window manager

The main difference for me is that the order of the parameters was crucial. For my hardware it was necessary to ensure panning occurs after transform.

The transform matrix has this shape (ignoring rotation):

sx 0  tx      tx = translation x (x pos)
 0 sy ty      ty = translation y (y pos)
 0  0 1       sx = scale x
              sy = scale y

Which translates to xrandr parameter: sx,0,tx,0,sy,ty,0,0,1

The calculations are as follows:

sx = 5120/1920 = 2.66666666667
sy = 1440/1080 = 1.33333333333
tx = (5120 / 2) - (1920 / 2) = 1600
ty = (1440 / 2) - (1080 / 2) = 180

Using that matrix we instruct the display server to scale the framebuffer by (2.66666666667, 1.33333333333) and then center it by translating 1600x180 units.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .