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: CONFIRMED
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
: 511823 (view as bug list)
Depends on:
Blocks:
 
Reported: 2025-09-19 09:14 UTC by fililip
Modified: 2025-12-16 17:30 UTC (History)
14 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented 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
cursor workaround patch (2.85 KB, patch)
2025-10-26 12:47 UTC, fililip
Details
improved cursor workaround patch (2.17 KB, patch)
2025-10-31 01:43 UTC, fililip
Details
improved cursor workaround patch 2 (2.00 KB, patch)
2025-11-08 15:43 UTC, fililip
Details
Video recording of a bug with "workaround patch 2" (1.90 MB, video/mp4)
2025-11-09 14:03 UTC, valdikss
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.
Comment 19 Zamundaaa 2025-10-07 13:00:03 UTC
Cursor movements have much lower latency than compositing, and we composite on every image update. The dropped frame is afaict really just from that change in latency, and pretty much expected.

Making cursor and overlay image updates async (again) will happen at some point, but doing them correctly while also avoiding clients going crazy with cursor surface rendering is not all that trivial.

(In reply to fililip from comment #15)
> 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).
The software cursor cannot be affected by the commit you linked. Are you sure you applied it correctly? You can check with drm_info.
Comment 20 fililip 2025-10-07 13:02:29 UTC
Yes, I did check with drm_info to be sure (I saw that no cursor planes were in use with that envvar), because I also thought it would be kind of weird if both were affected, but they unfortunately are.
Comment 21 Zamundaaa 2025-10-07 14:42:26 UTC
Okay. Are you sure the same commit introduced the issue with the software cursor too?
Comment 22 fililip 2025-10-07 15:01:24 UTC
Yes. I think something within that commit causes cursor image changes / repaints to stall for ~1-2 frames, as if they're just momentarily ignored. For me, this reproduces very consistently and is easy to spot, especially at 4K@160Hz.

Would it be possible (at least for the hardware cursor) to somehow decouple position updates from image updates? That might still result in delayed image updates, but the movement itself could remain consistent.
Comment 23 fililip 2025-10-15 11:49:14 UTC
Is there any more information I can provide to assist with this? Hopefully this is actionable before the stable release
Comment 24 Aleksander 2025-10-24 18:39:54 UTC
I can confirm that after updating my system to KDE 4.5.0, my mouse feels laggy after it changes its texture to something else, it's quite noticeable on higher refresh rates. Is there any viable workaround yet?
Comment 25 fililip 2025-10-25 11:31:43 UTC
I was able to come up with a workaround that simply repaints the cursor in its movement callback and it seems to resolve the issue for me, but I'll keep testing it before I post it here. (Notably, it must not break things like VRR for example)
Comment 26 fililip 2025-10-26 12:47:02 UTC
Created attachment 186184 [details]
cursor workaround patch

Here's that workaround patch, I've been running it for 2 days on my laptop and desktop and it seems to work correctly :D
Comment 27 Aleksander 2025-10-26 17:14:22 UTC
(In reply to fililip from comment #26)
> Created attachment 186184 [details]
> cursor workaround patch
> 
> Here's that workaround patch, I've been running it for 2 days on my laptop
> and desktop and it seems to work correctly :D

Yeah, looks like it works now!
Comment 28 Nate Graham 2025-10-27 17:42:26 UTC
Is that patch suitable for submitting to KWin?
Comment 29 fililip 2025-10-27 18:01:08 UTC
I doubt it, there's probably a reason cursor image changes were made synchronous, i.e. the fact that it can work for me (and possibly someone else with a high refresh rate screen) doesn't mean it's going to be flawless for everyone. This patch is just the best I could do to try to mitigate this problem and the real solution might be something different.
Comment 30 fililip 2025-10-27 19:59:49 UTC
Oh, I have noticed something: when the GPU hangs for any reason (in my case, for testing), the cursor stops rendering after its first repaint since the timeout until a reset/recovery. Is the cursor rendered on the GPU? If so, maybe it's a good idea not to actually repaint it every time it changes, but to store some kind of cache in memory of already painted cursor images and simply switch between them. I think that if this is done, especially in combination with the hardware cursor being used, there shouldn't be problems with async painting(?) I'm not sure though.

Other OSes seem to handle it this way; there, even during a GPU hang, the cursor still moves and changes its image without a hitch.
Comment 31 Zamundaaa 2025-10-28 17:41:05 UTC
Recovering from GPU resets is a blocking operation in KWin, everything freezes until it's complete. But yes, the cursor image is rendered on the GPU.
Rendering on every update is not a good idea, as some apps unfortunately take that as a reason to render animations as fast as KWin can render them. Maybe it could be special cased for when the app didn't request a frame callback, but doing that nicely isn't so simple.

Caching images could be done in principle, at least for when apps use the cursor shape protocol... but that too is a lot more complicated than it might sound. I don't think it's worth pursuing right now tbh.
Comment 32 fililip 2025-10-28 23:24:22 UTC
> everything freezes until it's complete

What I meant is when you try to move the mouse while the GPU is stuck (while below the timeout threshold, still prior to a reset), the cursor will respond, so the movement part by itself is fine, it's just that when it needs a repaint (ie when you hover over a window's border) it will stop until the GPU is recovered.

There is a merit to it, I think, making this work might make it look better and more reassuring for users who get a GPU hang, since at least their cursor would be 100% operational (and right now most hangs should be recoverable without a reset).
Comment 33 fililip 2025-10-31 01:43:25 UTC
Created attachment 186350 [details]
improved cursor workaround patch

I apologize, the first version of that workaround was incorrect - it could freeze display presentation when the cursor image changed immediately after switching to a VRR/tearing controlled fullscreen application. This new workaround does not have this issue and still makes cursor motion smooth.
Comment 34 valdikss 2025-11-08 15:27:11 UTC
(In reply to fililip from comment #33)
> Created attachment 186350 [details]
> improved cursor workaround patch
> 
> I apologize, the first version of that workaround was incorrect - it could
> freeze display presentation when the cursor image changed immediately after
> switching to a VRR/tearing controlled fullscreen application. This new
> workaround does not have this issue and still makes cursor motion smooth.

Running this version right now, on Intel Iris (i5-1340P). So far so good.
I have UHD display with 200% scaling. 60 Hz.
Initially reported in https://bugs.kde.org/show_bug.cgi?id=511823
Comment 35 valdikss 2025-11-08 15:27:35 UTC
*** Bug 511823 has been marked as a duplicate of this bug. ***
Comment 36 fililip 2025-11-08 15:43:23 UTC
Created attachment 186621 [details]
improved cursor workaround patch 2

Right, this reminds me, I ran into an issue with FurMark where cursor motion stops being smooth with high GPU utilization even when the cursor image doesn't change, which was caused by my misunderstanding of the use of resetRepaints() in composite().

This (even more simplified) version of the workaround doesn't have this problem on my setups.
Comment 37 bastimeyer123 2025-11-08 16:03:31 UTC
(In reply to fililip from comment #36)
> Created attachment 186621 [details]
> improved cursor workaround patch 2

Thanks for your efforts of trying to fix this.

I've been running my own kwin builds with your first patch applied for a couple of days now (comment #33), and that did fix the issue. Well, the blatant ones at least, but there was still a very rare but noticable hickup from time to time, but I'm not too sure if this was cursor related.

That second patch doesn't seem to work and there's not much difference compared to the current state in upstream kwin. For example, in Chromium, when I move the cursor over lots of links stacked above each other (e.g. on old.reddit.com), then the lag when the cursor shapes change is super easily noticable.
Comment 38 fililip 2025-11-08 16:10:20 UTC
Thanks for letting me know, that's why I kept both in case the second one does re-introduce something weird (I don't see the issue anymore with either patch on my systems though).

Ideally there wouldn't be this tradeoff between GPU-heavy stutter and GPU-lightweight smoothness, but I unfortunately don't see any obvious way to truly fix this other than reintroducing full async cursor handling, which I'm not really sure how to do properly :(
Comment 39 valdikss 2025-11-09 14:03:19 UTC
Created attachment 186647 [details]
Video recording of a bug with "workaround patch 2"

(In reply to fililip from comment #36)
> Created attachment 186621 [details]
> improved cursor workaround patch 2
> 
> Right, this reminds me, I ran into an issue with FurMark where cursor motion
> stops being smooth with high GPU utilization even when the cursor image
> doesn't change, which was caused by my misunderstanding of the use of
> resetRepaints() in composite().
> 
> This (even more simplified) version of the workaround doesn't have this
> problem on my setups.

Now running this patch for the whole day, and it has unfortunate issue: the icon is not positioned correctly for one frame.
Please watch the attached video.
Comment 40 fililip 2025-11-09 15:46:07 UTC
(In reply to valdikss from comment #39)
> Now running this patch for the whole day, and it has unfortunate issue: the
> icon is not positioned correctly for one frame.
> Please watch the attached video.

Okay, this means you'll have to use the previous version (comment #33) then. (Unless it also has this issue, which I hope it doesn't)
Comment 41 valdikss 2025-11-09 16:30:07 UTC
(In reply to fililip from comment #40)
> Okay, this means you'll have to use the previous version (comment #33) then.
> (Unless it also has this issue, which I hope it doesn't)

That version also does have the issue, but it happens less frequent. I'm running it now.
This bug is probably caused not by the recent change, I remember seeing it previously. But with the latest "workaround patch 3" it becomes annoying compared to "workaround patch 2".
Comment 42 Błażej Szczygieł 2025-11-11 20:41:17 UTC
There's another issue, when something is painting on screen (e.g. small animation or visual changes on mouse hover) and cursor moves in the same time - on AMD less visible, but on Nvidia frames drops are very visible sometimes.
Comment 43 Błażej Szczygieł 2025-11-12 19:49:36 UTC
Patch v2 seems to be more smooth to me, too, but instead of fixed 256x256 region, use "cursorView->collectDamage()" (it's full repaint anyway). Maybe you could create a MR?
Comment 44 fililip 2025-11-12 20:05:38 UTC
> use "cursorView->collectDamage()"

Oh, thanks! Didn't know I could do that.

> Maybe you could create a MR?

I doubt it would get accepted due to potential problems it may cause (comment #19) so I think it's better to leave it as a workaround here in case someone notices this issue until it's properly addressed.
Comment 45 Błażej Szczygieł 2025-11-13 23:10:02 UTC
> I doubt it would get accepted due to potential problems it may cause (comment #19) so I think it's better to leave it as a workaround here in case someone notices this issue until it's properly addressed.

Ok, it doesn't fix the issue anyway, only some cases (e.g. firefox).

The worst is on nvidia with 4k screen - sometimes it feels like 80386 with a serial mouse (e.g. on hovers or when raster window is updating its contents). I understand compositing may not be smooth, but cursor?
Comment 46 fililip 2025-11-14 00:47:33 UTC
Yeah, this is why I'm of the opinion that the cursor plane should be special cased in that it should be reusing images rendered only once for each display scale and only actually repaint them when the display configuration changes, and all of this should be controlled by another thread (which has actually been done already, I think). Redrawing the cursor on the GPU every time is risky if a stable frame time can't be achieved or the GPU is stuck/hung. It's precisely why stuff like FurMark will stall cursor repaints, and this was a problem even back on 6.4 and prior versions.

Maybe it's possible to just force a CPU image blit instead here and that would be a better workaround? Not sure how bad that would be for laptop or power constrained use long-term though :/

(By the way, I have always been able to notice unstable vblank intervals on Nvidia display hardware; it was simply never as stable as AMD or Intel iGPUs/dGPUs. I even reported it here thinking KWin could do something about it but it just seems to be an Nvidia issue: https://bugs.kde.org/show_bug.cgi?id=481716)
Comment 47 valdikss 2025-12-16 17:30:07 UTC
Still the issue as of Fedora 43 kwin-6.5.4-2.fc43.x86_64