RPi-Distro / repo

Issue tracking for the archive.raspberrypi.org repo
37 stars 1 forks source link

Screen resolution (arandr) is not working #281

Closed wagnerch closed 2 years ago

wagnerch commented 2 years ago

It appears when mutter is used as a WM it has it's own configuration to manage monitors & resolutions. Apparently GNOME Settings knows how to configure it. Basically lightdm is running the display setup script written by arandr (screen configuration) but mutter is changing it immediately after.

I managed to get a persistent resolution saved by creating this Python script:

#!/usr/bin/env python3
import sys
from gi.repository import Gio, GLib

bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
proxy = Gio.DBusProxy.new_sync(
    bus,
    Gio.DBusProxyFlags.NONE,
    None,
    "org.gnome.Mutter.DisplayConfig",
    "/org/gnome/Mutter/DisplayConfig",
    "org.gnome.Mutter.DisplayConfig",
    None
)

resources = proxy.call_sync(
    "org.gnome.Mutter.DisplayConfig.GetCurrentState",
    None,
    Gio.DBusCallFlags.NONE,
    1000,
    None
)

resources = resources.unpack()
serial = resources[0]
monitors = resources[1]
#print(resources)
print("serial:", serial)
print("monitors:")
for monitor in monitors:
  print(monitor[0][0:3])
  for mode in monitor[1]:
    print("  ", mode)

if len(sys.argv) != 4:
  sys.exit(1)

resolution = GLib.Variant("(uua(iiduba(ssa{sv}))a{sv})", (
    serial,
    2, # 0=verify, 1=temp, 2=persistent
    [ ( 0, 0, float(sys.argv[3]), 0, True, [ ( sys.argv[1], sys.argv[2], [] ) ] ) ],
    []
  )
)

result = proxy.call_sync(
    "org.gnome.Mutter.DisplayConfig.ApplyMonitorsConfig",
    resolution,
    Gio.DBusCallFlags.NONE,
    1000,
    None
)

print(result)

Usage: ./mutter-set-display-resolution

Should display monitors and modelines:

serial: 2
monitors:
('HDMI-1', 'ACR', 'ED347CKR')
   ('3440x1440@59.998870849609375', 3440, 1440, 59.998870849609375, 1.0, [1.0, 2
.0, 3.076923131942749], {'is-preferred': True})
   ('3440x1440@99.992500305175781', 3440, 1440, 99.99250030517578, 1.0, [1.0, 2.
0, 3.076923131942749], {})
   ('3440x1440@99.986869812011719', 3440, 1440, 99.98686981201172, 1.0, [1.0, 2.
0, 3.076923131942749], {})
   ('2560x1440@59.950550079345703', 2560, 1440, 59.9505500793457, 1.0, [1.0, 2.0, 3.076923131942749], {})
   ('2560x1080@59.994792938232422', 2560, 1080, 59.99479293823242, 1.0, [1.0, 2.0, 3.076923131942749], {'is-current': True})
...

The second run to set the mode is: ./mutter-set-display-resolution HDMI-1 2560x1080@59.994792938232422 1.0

1st arg: connector 2nd arg: mode line 3rd arg: scale (1.0)

The script will call the Mutter display config service over DBus and set a persistent configuration.

wagnerch commented 2 years ago

BTW, it seems that arandr writes /home/pi/.config/monitors.xml as well, but it uses a different vertical refresh frequency than what mutter is expecting/matching. Mutter seems pretty particular about it matching exactly.

2 entries are in monitors.xml now:

  1. I think this one is written by arandr (does not work):
        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.994998931884766</rate>
        </mode>

or this one in monitors.xml~

        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.995</rate>
        </mode>
  1. written by the script above via dbus (is working):
        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.994792938232422</rate>
        </mode>

This seems more than just rounding. Perhaps float vs double vs a more precise data type?

wagnerch commented 2 years ago

Full monitors.xml~, this this one is from just arandr:

<monitors version="2">
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>HDMI-1</connector>
          <vendor>ACR</vendor>
          <product>ED347CKR</product>
          <serial>unknown</serial>
        </monitorspec>
        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.995</rate>
        </mode>
      </monitor>
      <transform>
        <rotation>normal</rotation>
      </transform>
    </logicalmonitor>
  </configuration>
</monitors>

Full monitors.xml after using the script above:

<monitors version="2">
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>HDMI-1</connector>
          <vendor>ACR</vendor>
          <product>ED347CKR</product>
          <serial>unknown</serial>
        </monitorspec>
        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.994998931884766</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
  <configuration>
    <logicalmonitor>
      <x>0</x>
      <y>0</y>
      <scale>1</scale>
      <primary>yes</primary>
      <monitor>
        <monitorspec>
          <connector>HDMI-1</connector>
          <vendor>ACR</vendor>
          <product>ED347CKR</product>
          <serial>0x00000000</serial>
        </monitorspec>
        <mode>
          <width>2560</width>
          <height>1080</height>
          <rate>59.994792938232422</rate>
        </mode>
      </monitor>
    </logicalmonitor>
  </configuration>
</monitors>

2nd entry is the one that is used. 1st entry might be caused by reading/writing the 2nd entry, guessing a conversion to a float/double. But it never worked with the entry from monitors.xml~ or entry 1 above.

XECDesign commented 2 years ago

@spl237

spl237 commented 2 years ago

It's not the rounding; mutter only needs 3dp. It is that your serial number is being reported as "unknown" by arandr, but is "0x0000000" in the version which works.

Something in the parsing of the EDID is failing to extract the serial number. Please post the output of "xrandr --verbose | edid-decode"

wagnerch commented 2 years ago

@spl237 Yep, your right. As a test, I modified the second entry to 59.995 and remove the first entry. Restarted lightdm, and it did set the display resolution correctly (it's just the dbus service that's super picky). I also removed the monitors.xml, restarted, and it went to the highest resolution 3440x1440.

As for the edid, it looks like it doesn't have a serial number, see below:

edid-decode (hex):

00 ff ff ff ff ff ff 00 04 72 48 06 00 00 00 00
1e 1d 01 03 80 50 22 78 bf ee 95 a3 54 4c 99 26
0f 50 54 a5 cb 00 81 c0 81 80 95 00 a9 c0 b3 00
d1 c0 01 01 01 01 f5 7c 70 a0 d0 a0 29 50 30 20
35 00 1b 4e 31 00 00 1a 3d d0 70 a0 d0 a0 29 50
58 40 45 00 1b 4e 31 00 00 1a 00 00 00 fd 00 30
64 a0 a0 36 00 0a 20 20 20 20 20 20 00 00 00 fc
00 45 44 33 34 37 43 4b 52 0a 20 20 20 20 01 11

02 03 39 f4 4c 01 02 03 04 05 07 90 12 13 14 16
1f 23 09 07 07 83 01 00 00 6a 03 0c 00 10 00 38
78 20 00 00 67 d8 5d c4 01 78 c0 00 68 1a 00 00
01 01 30 64 00 e3 05 03 01 40 d0 70 a0 d0 a0 29
50 58 40 45 00 fe 1f 11 00 00 1e 08 48 00 a0 a0
38 32 40 30 20 25 00 fe 1f 11 00 00 1e 56 5e 00
a0 a0 a0 29 50 30 20 25 00 fe 1f 11 00 00 1e 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 bf

----------------

Block 0, Base EDID:
  EDID Structure Version & Revision: 1.3
  Vendor & Product Identification:
    Manufacturer: ACR
    Model: 1608
    Made in: week 30 of 2019
  Basic Display Parameters & Features:
    Digital display
    Maximum image size: 80 cm x 34 cm
    Gamma: 2.20
    DPMS levels: Standby Off
    Undefined display color type
    Default (sRGB) color space is primary color space
    First detailed timing is the preferred timing
    Supports GTF timings within operating range
  Color Characteristics:
    Red  : 0.6396, 0.3300
    Green: 0.2998, 0.5996
    Blue : 0.1503, 0.0595
    White: 0.3134, 0.3291
  Established Timings I & II:
    IBM     :   720x400    70.082 Hz   9:5    31.467 kHz  28.320 MHz
    DMT 0x04:   640x480    59.940 Hz   4:3    31.469 kHz  25.175 MHz
    DMT 0x06:   640x480    75.000 Hz   4:3    37.500 kHz  31.500 MHz
    DMT 0x09:   800x600    60.317 Hz   4:3    37.879 kHz  40.000 MHz
    DMT 0x0a:   800x600    72.188 Hz   4:3    48.077 kHz  50.000 MHz
    DMT 0x0b:   800x600    75.000 Hz   4:3    46.875 kHz  49.500 MHz
    DMT 0x10:  1024x768    60.004 Hz   4:3    48.363 kHz  65.000 MHz
    DMT 0x12:  1024x768    75.029 Hz   4:3    60.023 kHz  78.750 MHz
    DMT 0x24:  1280x1024   75.025 Hz   5:4    79.976 kHz 135.000 MHz
  Standard Timings:
    DMT 0x55:  1280x720    60.000 Hz  16:9    45.000 kHz  74.250 MHz
    DMT 0x23:  1280x1024   60.020 Hz   5:4    63.981 kHz 108.000 MHz
    DMT 0x2f:  1440x900    59.887 Hz  16:10   55.935 kHz 106.500 MHz
    DMT 0x53:  1600x900    60.000 Hz  16:9    60.000 kHz 108.000 MHz (RB)
    DMT 0x3a:  1680x1050   59.954 Hz  16:10   65.290 kHz 146.250 MHz
    DMT 0x52:  1920x1080   60.000 Hz  16:9    67.500 kHz 148.500 MHz
  Detailed Timing Descriptors:
    DTD 1:  3440x1440   59.999 Hz  43:18   88.858 kHz 319.890 MHz (795 mm x 334 mm)
                 Hfront   48 Hsync  32 Hback  80 Hpol P
                 Vfront    3 Vsync   5 Vback  33 Vpol N
    DTD 2:  3440x1440   99.987 Hz  43:18  148.081 kHz 533.090 MHz (795 mm x 334 mm)
                 Hfront   88 Hsync  64 Hback   8 Hpol P
                 Vfront    4 Vsync   5 Vback  32 Vpol N
  Display Range Limits:
    Monitor ranges (GTF): 48-100 Hz V, 160-160 kHz H, max dotclock 540 MHz
    Display Product Name: 'ED347CKR'
  Extension blocks: 1
Checksum: 0x11

----------------

Block 1, CTA-861 Extension Block:
  Revision: 3
  Underscans IT Video Formats by default
  Basic audio support
  Supports YCbCr 4:4:4
  Supports YCbCr 4:2:2
  Native detailed modes: 4
  Video Data Block:
    VIC   1:   640x480    59.940 Hz   4:3    31.469 kHz  25.175 MHz
    VIC   2:   720x480    59.940 Hz   4:3    31.469 kHz  27.000 MHz
    VIC   3:   720x480    59.940 Hz  16:9    31.469 kHz  27.000 MHz
    VIC   4:  1280x720    60.000 Hz  16:9    45.000 kHz  74.250 MHz
    VIC   5:  1920x1080i  60.000 Hz  16:9    33.750 kHz  74.250 MHz
    VIC   7:  1440x480i   59.940 Hz  16:9    15.734 kHz  27.000 MHz
    VIC  16:  1920x1080   60.000 Hz  16:9    67.500 kHz 148.500 MHz (native)
    VIC  18:   720x576    50.000 Hz  16:9    31.250 kHz  27.000 MHz
    VIC  19:  1280x720    50.000 Hz  16:9    37.500 kHz  74.250 MHz
    VIC  20:  1920x1080i  50.000 Hz  16:9    28.125 kHz  74.250 MHz
    VIC  22:  1440x576i   50.000 Hz  16:9    15.625 kHz  27.000 MHz
    VIC  31:  1920x1080   50.000 Hz  16:9    56.250 kHz 148.500 MHz
  Audio Data Block:
    Linear PCM:
      Max channels: 2
      Supported sample rates (kHz): 48 44.1 32
      Supported sample sizes (bits): 24 20 16
  Speaker Allocation Data Block:
    FL/FR - Front Left/Right
  Vendor-Specific Data Block (HDMI), OUI 00-0C-03:
    Source physical address: 1.0.0.0
    DC_36bit
    DC_30bit
    DC_Y444
    Maximum TMDS clock: 600 MHz
    Extended HDMI video details:
  Vendor-Specific Data Block (HDMI Forum), OUI C4-5D-D8:
    Version: 1
    Maximum TMDS Character Rate: 600 MHz
    SCDC Present
    SCDC Read Request Capable
  Vendor-Specific Data Block (AMD), OUI 00-00-1A:
    01 01 30 64 00                                  '..0d.'
  Colorimetry Data Block:
    xvYCC601
    xvYCC709
  Detailed Timing Descriptors:
    DTD 3:  3440x1440   99.992 Hz  43:18  148.089 kHz 533.120 MHz (510 mm x 287 mm)
                 Hfront   88 Hsync  64 Hback   8 Hpol P
                 Vfront    4 Vsync   5 Vback  32 Vpol P
    DTD 4:  2560x1080   59.995 Hz  64:27   67.794 kHz 184.400 MHz (510 mm x 287 mm)
                 Hfront   48 Hsync  32 Hback  80 Hpol P
                 Vfront    2 Vsync   5 Vback  43 Vpol P
    DTD 5:  2560x1440   59.951 Hz  16:9    88.787 kHz 241.500 MHz (510 mm x 287 mm)
                 Hfront   48 Hsync  32 Hback  80 Hpol P
                 Vfront    2 Vsync   5 Vback  34 Vpol P
Checksum: 0xbf
spl237 commented 2 years ago

OK, that's the problem. arandr uses xrandr and edid-decode to find the vendor, model and serial, but it's not reporting the serial that mutter is finding, so the data doesn't match and gets rejected.

For now, you'll have to manually set the serial number - when I am back at work in the New Year, I'll try and see if I can work out where mutter is getting the serial from, as it seems not to be the EDID.

wagnerch commented 2 years ago

It looks like mutter just blindly pulls bytes 12-15 from the EDID.

in src/backends/edid-parse.c:decode_vendor_and_product_identification(): info->serial_number = edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;

I guess edid-decode probably checks if it is 0 and just omits it from the output. This is an Acer ED347CKR monitor. I guess this is why some folks have no issue. :)

spl237 commented 2 years ago

That's going to be tedious to fix, because DSI displays genuinely have no serial number and so "unknown" is what mutter uses for that field, I think. Thanks for the additional information - I'll have a look into this in January and see if I can come up with something which will work in all cases.

spl237 commented 2 years ago

I've made a change to arandr which I think should fix this - https://github.com/raspberrypi-ui/arandr-bullseye/commit/3f2ae388d1e413cf477fe1956b010f7b1cef7929 It's only that one file which has changed - if you could try pulling that change into your system (/usr/lib/python3/dist-packages/screenlayout/xrandr.py) and see if it now works, that would be really helpful! Many thanks.

wagnerch commented 2 years ago

@spl237 Yep, applied that patch and that is working as expected.

spl237 commented 2 years ago

Brilliant - many thanks for testing. I'll close this issue in that case; we'll get that patch out in the New Year.