Bug 509669 - The cursor drops frames when its image changes (bisected to fd068d10)
Summary: The cursor drops frames when its image changes (bisected to fd068d10)
Status: REPORTED
Alias: None
Product: kwin
Classification: Plasma
Component: wayland-generic (other bugs)
Version First Reported In: 6.4.90
Platform: Arch Linux Linux
: NOR minor
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords: regression
Depends on:
Blocks:
 
Reported: 2025-09-19 09:14 UTC by fililip
Modified: 2025-10-01 21:29 UTC (History)
6 users (show)

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


Attachments
Slow mo video: moving pointer in circles at edge of Konsole window (2.33 MB, video/mp4)
2025-09-23 18:39 UTC, tempqd
Details
circle example (11.57 KB, image/png)
2025-09-23 18:58 UTC, fililip
Details

Note You need to log in before you can comment on or make changes to this bug.
Description fililip 2025-09-19 09:14:09 UTC
SUMMARY
When moving the mouse in a quick circular fashion over different types of UI elements, when the mouse cursor image changes (i.e. from regular pointer to the resize, text or hand cursor), it appears as though the cursor is "lagging" via persistence of vision; the persisting 'changed' cursor appears too late for example. This did not happen on 6.4, where it is always smooth no matter how many times the cursor changes.

STEPS TO REPRODUCE
1. Log into a session
2. Open a Konsole window
3. Move the mouse in rapid circular motion so that the resulting 'circle' borders on both the desktop and the Konsole window's borders to trigger the resize cursor image

(or open a website with lots of text on it and similarly circle around the mouse over the background and the text)

OBSERVED RESULT
Some images retained by persistence of vision appear 'laggy' and are not spaced out evenly (especially visible at 120Hz+)

EXPECTED RESULT
All cursor images should always appear evenly spaced out when moving the mouse

SOFTWARE/OS VERSIONS
Operating System: Arch Linux 
KDE Plasma Version: 6.4.90
KDE Frameworks Version: 6.18.0
Qt Version: 6.10.0
Kernel Version: 6.16.7-arch1-1 (64-bit)
Graphics Platform: Wayland
Processors: 20 × AMD Ryzen AI 9 365 w/ Radeon 880M
Memory: 32 GiB of RAM (27.2 GiB usable)
Graphics Processor: AMD Radeon 880M Graphics

ADDITIONAL INFORMATION
A high polling rate mouse is required(?) Unsure if this reproduces below 1000Hz. I did not enable overlay planes.
Comment 1 Nate Graham 2025-09-19 13:57:56 UTC
I can't reproduce this with my Logitech Lift mouse, though admittedly its polling rate is only 125Hz.
Comment 2 fililip 2025-09-19 17:56:47 UTC
I've bisected the change to:

fd068d10b6559ce94b77508b267e1370274be729 is the first bad commit
commit fd068d10b6559ce94b77508b267e1370274be729
Author: Xaver Hugl <xaver.hugl@kde.org>
Date:   Thu Jun 5 17:35:08 2025 +0200

    compositor: paint, enable and disable the cursor only in composite()
    
    (only) doing it asynchronously has disadvantages:
    - we can easily miss some situations in which the layer needs repainting
    - when moving the cursor plane fails, we can have some time between hiding
      the cursor plane and showing the software cursor, or likewise, some time
      between showing the cursor plane and hiding the software cursor
    - it requires special casing presentation feedback for the cursor
    
    With this change, the cursor is still moved asynchronously, so primary plane
    updates still can't slow cursor movement down or affect its latency.
    
    BUG: 504890

 src/compositor.cpp       | 239 ++++++++++++++++++++++++++++++++++++++++--------------------------------------------
 src/core/outputlayer.cpp |   2 +
 src/core/outputlayer.h   |   3 ++
 src/scene/cursoritem.cpp |  10 ++++
 src/scene/cursoritem.h   |   1 +
 src/scene/imageitem.cpp  |   1 +
 src/scene/item.cpp       |   6 +++
 src/scene/item.h         |   1 +
 src/scene/scene.cpp      |  21 ++++++++
 src/scene/scene.h        |   2 +
 10 files changed, 160 insertions(+), 126 deletions(-)
Comment 3 tempqd 2025-09-23 18:39:33 UTC
Created attachment 185199 [details]
Slow mo video: moving pointer in circles at edge of Konsole window

I think I see this (extremely subtly) sometimes on git master, 165hz and high precision touchpad.

I've attached a slow mo video -- I think I'm seeing that the first transition (top of the circle) is fine, but the second one (bottom of the circle) shows a delayed transition to the resize cursor, i.e. the text cursor is shown outside the window.

Is this the bug in question?
Comment 4 fililip 2025-09-23 18:58:47 UTC
Created attachment 185200 [details]
circle example

Yes, that looks like it. For me though it's very consistently reproducible for some reason, both on my laptop and desktop (6600 XT), that's how I managed to bisect it reliably.

For more testing, try going to https://jisho.org/ and do a small circle over the search bar and the search button rapidly; there should be three cursor images (pointer, hand, text) and it should be more apparent. I attached an example.

I should add that I have a 4K screen running at 120 and 160Hz with 200% scaling in both cases, maybe that configuration triggers it more often, but I'm not sure.

It's very weird that it triggers on cursor image change and is otherwise stable.
Comment 5 tempqd 2025-09-23 19:13:35 UTC
Could it maybe be related to amdgpu cursor plane stuff? We're on the same kernel (aside from Arch vs Tumbleweed) "6.16.7-1-default" and my Mesa version is "25.2.2-1699.425.pm.1" on a Radeon 680M

Might be worth testing if there's any difference between hardware cursor and software cursor?

It doesn't look any more frequent for me on jisho.org (cool site btw!) but good test bed
Comment 6 fililip 2025-09-23 19:22:14 UTC
KWIN_FORCE_SW_CURSOR=1 does the same thing on my machine. The same thing happens on 6.16.8.

(As for Mesa, I'm using 25.3-dev from master built today but it does the same thing on 25.2)
Comment 7 Akseli Lahtinen 2025-09-24 08:37:03 UTC
I am unable to reproduce this

Operating System: Fedora Linux 42
KDE Plasma Version: 6.5.80
KDE Frameworks Version: 6.19.0
Qt Version: 6.9.2
Kernel Version: 6.16.7-200.fc42.x86_64 (64-bit)
Graphics Platform: Wayland
Processors: 12 × AMD Ryzen 5 3600 6-Core Processor
Memory: 16 GiB of RAM (15.5 GiB usable)
Graphics Processor: AMD Radeon RX 6600
Comment 8 fililip 2025-09-24 16:23:44 UTC
I tried going back to Qt 6.9.2 and rebuilding everything, thinking it was a Qt 6.10 regression, yet the problem unfortunately remains.
Comment 9 fililip 2025-09-24 17:30:26 UTC
I tested it a bit more, it seems to be a larger issue at 200% scaling. At 100% it appears less pronounced, even in 4K and even after making the cursor 2x larger.
Comment 10 fililip 2025-09-24 18:16:59 UTC
I managed to grab a video recording, this is from a 4K 240Hz display with 150% scaling and a 1kHz polling rate mouse. The commit removing async image updates seems to cause these delays. Hopefully it's more noticeable here.

Here's the video (I couldn't upload it here due to size restrictions): https://www.youtube.com/watch?v=BRfYCN5I7_s
Comment 11 Akseli Lahtinen 2025-09-25 09:20:56 UTC
(In reply to fililip from comment #10)
> I managed to grab a video recording, this is from a 4K 240Hz display with
> 150% scaling and a 1kHz polling rate mouse. The commit removing async image
> updates seems to cause these delays. Hopefully it's more noticeable here.
> 
> Here's the video (I couldn't upload it here due to size restrictions):
> https://www.youtube.com/watch?v=BRfYCN5I7_s

Okay I believe it's happening. The problem is that is it our bug or a driver bug.

I still can't get the bug to happen though, I have 3440x1440 monitor, and I tried with both 150% and 200% scaling, and couldn't notice any issues.

It could be a driver bug. Do you get any messages related to the GPU if you have `journalctl -ef` open in a terminal while doing this? Or in `sudo dmesg` ?
Comment 12 fililip 2025-09-25 09:35:38 UTC
No, there are no kernel log errors, nothing in the journal, just the cursor refusing to move after it changes for a frame or two. I've tried it on a few other PCs and laptops so far to be sure, and fair enough, it happens there as well.

The only thing I was able to ascertain is that it worked wonderfully prior to https://invent.kde.org/plasma/kwin/-/commit/fd068d10b6559ce94b77508b267e1370274be729 no matter what happened in the session.

I had this thought of amdgpu being the culprit, but then why would it work again after compiling the KWin master branch prior to that commit or on 6.4.5? The rest of the session doesn't lag or freeze when these cursor stutter events happen, so I really doubt this is a display bug.
Comment 13 tempqd 2025-09-25 20:13:25 UTC
I wonder if https://docs.kernel.org/gpu/amdgpu/display/dc-debug.html#multiple-planes-debug or similar debugging could reveal anything?
Comment 14 tempqd 2025-09-25 20:17:40 UTC
Or https://invent.kde.org/plasma/kwin/-/wikis/Debugging/Debugging-DRM-issues (this produces huge logs though)
Comment 15 fililip 2025-09-25 21:41:03 UTC
This issue manifests itself in the same manner regardless of whether or not the hardware cursor is in use (I tried KWIN_FORCE_SW_CURSOR=1 as per my comment above).

As such it can't be caused by DRM or amdgpu, especially when session content presentation is otherwise stable (when the cursor position stutters there are no desktop-wide freezes/mini-lockups), hardware cursor image changes work fine prior to the regression commit on the same kernel version, and the problem happens across multiple AMD Display Core Next ASIC versions.

Ideally I'd test this on an Intel machine as well, but I am unfortunately no longer in possession of any. (NVIDIA has a hardware cursor position change + presentation consistency issue so that is not a feasible option here)

It's not tied to overlay planes either, since I have both two active screens and KWIN_USE_OVERLAYS set to 0 (and it's exactly the same even with overlays enabled anyway).

My question is: is it possible to temporarily force KWin to perform these cursor updates asynchronously again? How should I go about trying to fix it myself (ie if it makes sense to somehow bring back connect() for Cursor::positionChanged in compositor.cpp)?

I realize this issue is a bit nitpicky (in contrast to https://bugs.kde.org/show_bug.cgi?id=504321 for example), and that there are more pressing matters to attend to (and I do apologize for the noise), but there's a chance that if this ends up in the release version, people will notice it on their 1kHz/8kHz mice and highres + high refresh rate setups. I caught this in around an hour after grabbing 6.4.90 packages.
Comment 16 tempqd 2025-09-26 01:18:21 UTC
Ah I see, so it does seem like specifically KWin's cursor handling then. I also don't have an Intel machine to test atm either. Hmm.

> My question is: is it possible to temporarily force KWin to perform these cursor
> updates asynchronously again? How should I go about trying to fix it myself
> (ie if it makes sense to somehow bring back connect() for Cursor::positionChanged
> in compositor.cpp)?

I'm not sure about these myself currently, but hopefully others might have some thoughts?
Comment 17 Arjen Hiemstra 2025-09-30 10:23:07 UTC
(In reply to fililip from comment #10)
> I managed to grab a video recording, this is from a 4K 240Hz display with
> 150% scaling and a 1kHz polling rate mouse. The commit removing async image
> updates seems to cause these delays. Hopefully it's more noticeable here.
> 
> Here's the video (I couldn't upload it here due to size restrictions):
> https://www.youtube.com/watch?v=BRfYCN5I7_s

I can see the difference from this video, with 6.5 there's a visible stutter when the cursor image needs to change. What I can't pinpoint is whether it's just a failed position update or the entire compositing pipeline stalls. Any chance you could test with something continuously updating next to it? If that continues to update correctly it's probably a position issue rather than a pipeline stall.
Comment 18 fililip 2025-09-30 14:42:22 UTC
I just tested this again with an SDL/Vulkan vsync tester of mine (with odd-even frame flickering based on https://www.vsynctester.com/) and it's perfectly flat while the color is uniform when the cursor does this. So it's probably a cursor position issue, since the rest of the session is otherwise perfectly stable.