Bug 477985 - Regression on VMware setting screen resolution (Wayland)
Summary: Regression on VMware setting screen resolution (Wayland)
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: platform-drm (other bugs)
Version First Reported In: 5.90.0
Platform: Fedora RPMs Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
: 478421 (view as bug list)
Depends on:
Blocks:
 
Reported: 2023-12-03 12:48 UTC by Stefan Hoffmeister
Modified: 2025-06-23 12:53 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Stefan Hoffmeister 2023-12-03 12:48:05 UTC
SUMMARY

Setting the screen resolution of a virtualized Fedora Rawhide / Plasma 6.0 dev master via VMware Workstation / Player tooling fails to update the screen resolution of the KDE 6 desktop, on Wayland.

This breaks, for instance, "full screen" support in VMware Workstation.

This is a regression relative to Fedora Linux 39 with KDE 5.27.x on Wayland.

This seems to work fine on X11.

STEPS TO REPRODUCE
1. have VMware Workstation or VMware Player running as a virtualization solution
2. install and up-to-date Fedora Rawhide (which includes Plasma 6.0 dev master) as a fresh VM

// no additional steps are required to get VMware tools in - Fedora Rawhide does this out of the box
// observe that this generally works

3. `sudo vmwgfxctrl --set-topology 1920x1080+0+0`

OBSERVED RESULT

Nothing happens

EXPECTED RESULT

Virtual screen gets resized to 1920x1080. 

This applies to setting any screen resolution; above I am using `vmwgfxctrl` for the sake of simplicity, but the same code path (on the VMware side? Linux kernel side?) is most likely taken by
* resizing the host virtualized window with "Autofit Guest" feature enabled
* putting the VM into full-screen mode (or back)

In all cases, the "virtual" screen resolution never changes.

Note that setting the screen resolution from _within_ KDE, via "Display Configuration" works (almost always - have not found a reliable way to repro). The drawback of doing that, though, is that this does not allow enabling the peculiar (good) behaviour of "Full-screen mode" in VMware Workstation, where all input is redirected into the VM. The regression therefore does hurt quite a bit in real use of the KDE desktop environment.

I do not see any log output, neither in journalctl nor in dmesg, which seem to apply to this scenario.
Comment 1 Stefan Hoffmeister 2023-12-03 19:03:13 UTC
I added 
```
export QT_LOGGING_RULES="kwin*=true"
```
and whenever I resize the virtual screen from the host, I get

```
Dec 03 19:50:30 fedora kwin_wayland[7208]: kwin_wayland_drm: Received change event for monitored drm device "/dev/dri/card0"
Dec 03 19:50:30 fedora kwin_wayland[7208]: kwin_wayland_drm: Could not find edid for connector DrmConnector(id=38, gpu=KWin::DrmGpu(0x558b1858c490), name="Virtual-1-unknown", connection="Connected", countMode=25)
Dec 03 19:50:30 fedora systemd[1]: vboxclient.service - VirtualBox guest VMSVGA resize client was skipped because no trigger condition checks were met.
```
The last log entry I just left in to show that the Oracle VirtualBox resize client is being skipped (as expected).

`drm_info` has this to say:

```
stefan@fedora:~/.config/plasma-workspace/env$ drm_info 
drmModeGetFB2: No such device
drmModeGetFB2: No such device
Node: /dev/dri/card0
├───Driver: vmwgfx (Linux drm driver for VMware graphics devices) version 2.20.0 (20211206)
│   ├───DRM_CLIENT_CAP_STEREO_3D supported
│   ├───DRM_CLIENT_CAP_UNIVERSAL_PLANES supported
│   ├───DRM_CLIENT_CAP_ATOMIC supported
│   ├───DRM_CLIENT_CAP_ASPECT_RATIO supported
│   ├───DRM_CLIENT_CAP_WRITEBACK_CONNECTORS supported
│   ├───DRM_CAP_DUMB_BUFFER = 1
│   ├───DRM_CAP_VBLANK_HIGH_CRTC = 1
│   ├───DRM_CAP_DUMB_PREFERRED_DEPTH = 32
│   ├───DRM_CAP_DUMB_PREFER_SHADOW = 0
│   ├───DRM_CAP_PRIME = 3
│   ├───DRM_CAP_TIMESTAMP_MONOTONIC = 1
│   ├───DRM_CAP_ASYNC_PAGE_FLIP = 0
│   ├───DRM_CAP_CURSOR_WIDTH = 64
│   ├───DRM_CAP_CURSOR_HEIGHT = 64
│   ├───DRM_CAP_ADDFB2_MODIFIERS = 1
│   ├───DRM_CAP_PAGE_FLIP_TARGET = 0
│   ├───DRM_CAP_CRTC_IN_VBLANK_EVENT = 1
│   ├───DRM_CAP_SYNCOBJ = 0
│   └───DRM_CAP_SYNCOBJ_TIMELINE = 0
├───Device: PCI 15ad:0405 VMware SVGA II Adapter
│   └───Available nodes: primary, render
├───Framebuffer size
│   ├───Width: [1, 16384]
│   └───Height: [1, 16384]
├───Connectors
│   ├───Connector 0
│   │   ├───Object ID: 38
│   │   ├───Type: virtual
│   │   ├───Status: connected
│   │   ├───Physical size: 0x0 mm
│   │   ├───Subpixel: unknown
│   │   ├───Encoders: {0}
│   │   ├───Modes
│   │   │   ├───2139x1454@60.00 preferred driver nhsync pvsync 
│   │   │   ├───3840x2400@59.97 driver phsync nvsync 
│   │   │   ├───3840x2160@59.97 driver phsync nvsync 
│   │   │   ├───2880x1800@59.95 driver phsync nvsync 
│   │   │   ├───2560x1600@59.99 driver nhsync pvsync 
│   │   │   ├───2560x1440@59.95 driver phsync nvsync 
│   │   │   ├───1920x1440@60.00 driver nhsync pvsync 
│   │   │   ├───1856x1392@59.99 driver nhsync pvsync 
│   │   │   ├───1792x1344@60.00 driver nhsync pvsync 
│   │   │   ├───1920x1200@59.88 driver nhsync pvsync 
│   │   │   ├───1920x1080@59.96 driver nhsync pvsync 
│   │   │   ├───1600x1200@60.00 driver phsync pvsync 
│   │   │   ├───1680x1050@59.95 driver nhsync pvsync 
│   │   │   ├───1400x1050@59.98 driver nhsync pvsync 
│   │   │   ├───1280x1024@60.02 driver phsync pvsync 
│   │   │   ├───1440x900@59.89 driver nhsync pvsync 
│   │   │   ├───1280x960@60.00 driver phsync pvsync 
│   │   │   ├───1360x768@60.02 driver phsync pvsync 
│   │   │   ├───1280x800@59.81 driver phsync nvsync 
│   │   │   ├───1152x864@75.00 driver phsync pvsync 
│   │   │   ├───1280x768@59.87 driver nhsync pvsync 
│   │   │   ├───1280x720@59.85 driver nhsync pvsync 
│   │   │   ├───1024x768@60.00 driver nhsync nvsync 
│   │   │   ├───800x600@60.32 driver phsync pvsync 
│   │   │   └───640x480@59.94 driver nhsync nvsync 
│   │   └───Properties
│   │       ├───"DPMS": enum {On, Standby, Suspend, Off} = On
│   │       ├───"link-status": enum {Good, Bad} = Good
│   │       ├───"non-desktop" (immutable): range [0, 1] = 0
│   │       ├───"TILE" (immutable): blob = 0
│   │       ├───"CRTC_ID" (atomic): object CRTC = 40
│   │       ├───"hotplug_mode_update" (immutable): range [0, 1] = 1
│   │       ├───"suggested X" (immutable): range [0, UINT32_MAX] = 0
│   │       └───"suggested Y" (immutable): range [0, UINT32_MAX] = 0
```

The DRM context for this is
```
stefan@fedora:~/.config/plasma-workspace/env$ cat /sys/class/drm/card0-Virtual-1/status
connected
stefan@fedora:~/.config/plasma-workspace/env$ cat /sys/class/drm/card0-Virtual-1/modes
2139x1454
3840x2400
3840x2160
2880x1800
2560x1600
2560x1440
1920x1440
1856x1392
1792x1344
1920x1200
1920x1080
1600x1200
1680x1050
1400x1050
1280x1024
1440x900
1280x960
1360x768
1280x800
1152x864
1280x768
1280x720
1024x768
800x600
640x480
stefan@fedora:~/.config/plasma-workspace/env$ cat /sys/class/drm/card0-Virtual-1/edid
stefan@fedora:~/.config/plasma-workspace/env$ 
stefan@fedora:~/.config/plasma-workspace/env$ 
```
highlighting that there indeed is no EDID data.
Comment 2 Stefan Hoffmeister 2023-12-03 19:23:57 UTC
Looking at the code at https://invent.kde.org/plasma/kwin/-/blob/3cc8e9f13bd011670c3a763bdaf3a508b5270a1d/src/backends/drm/drm_connector.cpp#L267 I am not sure how missing EDID data could result in this functional problem?

Resizing seems to leave the number of modes unchanged, but changes the content of the _preferred_ mode, so the modes probably are detected as `!equal`, so the mode list gets updated.

I do not see why that new / updated preferred mode (at the same position as before) does not get activated.

Is there special casing required for "virtual" connectors? Or is "mode has not changed" detection too aggressive?

Unfortunately, there is no additional debug logging in that area.
Comment 3 Stefan Hoffmeister 2023-12-03 19:36:24 UTC
More debug output suggests
```
Dec 03 20:30:30 fedora kwin_wayland[1674]: kwin_xwl: Setting primary KWin::DrmOutput(0x55c476dd1b00, name="Virtual-1", geometry=QRect(0,0 1664x1154), scale=1) 33
```
But ... it does not. The QRect appears correct (and changes with each resize), but ... nothing happens to the screen resolution itself.
Comment 4 Stefan Hoffmeister 2023-12-10 12:44:42 UTC
In a different failure mode, the whole desktop becomes unusable due to kwin getting stuck on
```
Dec 10 13:38:31 fedora kwin_wayland[79391]: kwin_wayland_drm: Page flip failed: No space left on device                 
Dec 10 13:38:31 fedora kwin_wayland[79391]: kwin_wayland_drm: Presentation failed! No space left on device  
```

To reproduce, have the virtual machine running in "full screen" mode (at 4k), then issue  `sudo vmwgfxctrl --set-topology 1920x1080+0+0`

At least that shouldn't hang the desktop.
Comment 5 Stefan Hoffmeister 2023-12-10 12:48:21 UTC
Hunting around on the net found https://bugzilla.redhat.com/show_bug.cgi?id=1986240#c32 where Zack Rusin comments in 2021
```
The KDE issue is a little different. KDE had (it still might, as I haven't tested the latest kwin code) a bug in the kwin wayland code where it wouldn't correct resize the fb dimensions its rendering to after the resize, i.e. looking at https://www.kernel.org/doc/html/latest/gpu/drm-kms.html the drm_framebuffer objects used by kwin aren't correctly resized (recreated with the new dimensions) after udev sends a change event for the new mode on drm_crtc.

So while vmwgfx has set the new mode, the userspace is still rendering into old dimensioned framebuffer.
```

The defective "dynamic resize behaviour" that I am reporting seems to be consistent with such a defect: the abstract screen resolution changes, but the buffer which is being painted does not change (i.e. the whole desktop continues to paint into the previous area).
Comment 6 Stefan Hoffmeister 2023-12-10 14:24:44 UTC
Running `~/kde/build/kwin/bin/kwin_wayland --replace` from a separate session (ssh) recovers fine for the KDE Plasma Desktop world, and brings the complete desktop back with the expected (updated!) screen resolution.

Alas (obviously) this takes Firefox and friends as victims.
Comment 7 Neal Gompa 2023-12-11 07:56:37 UTC
I can verify this occurs with Plasma Beta on VMware Fusion.
Comment 8 Stefan Hoffmeister 2023-12-12 16:54:18 UTC
The root cause of this seems to be a well-intentioned, but eventually inapplicable, assertion of configuration change, resulting in faulty suppression of updating:

The implementation tries hard to _not_ change the mode via `drmModeSetCrtc`. Alas, in the case of resizing of the window ("connector"? "crtc"?) of the virtual machine, the _mode_ does not appear to change, but the _resolution_ (width, height) changes.

With at least the following crude hack in place, I get a nicely resizing desktop under KDE Plasma 6 git master on Wayland:
```
        const bool modeHasChanged = true || m_pending.mode != m_next.mode;
        const bool crtcHasChanged = m_pending.crtc != m_next.crtc;
        
        if (crtcHasChanged || modeHasChanged) {
            Error err = legacyModeset();
            if (err != Error::None) {
                return err;
            }
        }
```

I currently have a couple more experiments, hacks and log statements in place, so I am not sure whether the above alone is sufficient - but it is very much necessary indeed.

Now, obviously, 
```
        const bool modeHasChanged = true || m_pending.mode != m_next.mode;
```
is just ... crass.

In a different location, I poked 
```
const bool isVirtual = (m_conn->connector_type == DRM_MODE_CONNECTOR_VIRTUAL);
```
which may be slight more viable than a simple `true`.

I'd be thrilled to receive suggestions on how to _correctly_ handle "only the dimensions have changed, but not the mode" scenarios within KDE - I have been exposed to the combined source code of the Linux DRM kernel subsystem, libdrm, kwin, Wayland protocols, and QT for only a handful of hours.
Comment 9 Stefan Hoffmeister 2023-12-13 19:48:59 UTC
And then there are

* https://github.com/swaywm/wlroots/issues/2188
* https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2188

referring to https://drmdb.emersion.fr/properties/3233857728/hotplug_mode_update which is all about the "hotplug_mode_update" property.

GNOME / Mutter is aware of this, https://gitlab.gnome.org/GNOME/mutter/-/blob/main/NEWS#L3132
Comment 10 Nate Graham 2023-12-14 17:04:25 UTC
*** Bug 478421 has been marked as a duplicate of this bug. ***
Comment 11 Stefan Hoffmeister 2023-12-14 21:59:50 UTC
Somehow gitlab did not auto-tag https://invent.kde.org/plasma/kwin/-/merge_requests/4790 ...
Comment 12 Stefan Hoffmeister 2023-12-16 11:07:13 UTC
Another MR with a different change detection strategy: https://invent.kde.org/plasma/kwin/-/merge_requests/4799
Comment 13 Zamundaaa 2023-12-18 14:32:51 UTC
Git commit 3887542240a882dd44c7d392900f8cc3ed2b59f6 by Xaver Hugl, on behalf of Stefan Hoffmeister.
Committed on 18/12/2023 at 15:23.
Pushed by zamundaaa into branch 'master'.

backends/drm: Detect mode content change instead of comparing mode pointers

This fixes Plasma Desktop / kwin resizing problems at least for virtual
machines running off the vmwgfx Linux kernel driver

M  +10   -5    src/backends/drm/drm_connector.cpp
M  +1    -0    src/backends/drm/drm_connector.h
M  +3    -1    src/backends/drm/drm_pipeline_legacy.cpp

https://invent.kde.org/plasma/kwin/-/commit/3887542240a882dd44c7d392900f8cc3ed2b59f6