Bug 492924

Summary: Buffers not released when window occluded but not marked as obscured
Product: [Plasma] kwin Reporter: orko <orko>
Component: wayland-genericAssignee: KWin default assignee <kwin-bugs-null>
Status: RESOLVED UPSTREAM    
Severity: normal CC: kde, nate, xaver.hugl
Priority: HI    
Version First Reported In: 6.1.4   
Target Milestone: ---   
Platform: Other   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description orko 2024-09-09 22:34:51 UTC
SUMMARY
KDE does not send suspended xdg_toplevel state

STEPS TO REPRODUCE
1. With WAYLAND_DEBUG=1 env var set, start a wayland app that binds to xdg-shell (wm_base) version 6.
2. Check xdg-toplevel configure events.

OBSERVED RESULT
No "suspended" state is received.

EXPECTED RESULT
"suspended" state is received via xdg_toplevel configure event.

SOFTWARE/OS VERSIONS
KDE Plasma Version: 6.1.4

ADDITIONAL INFORMATION
suspended state was added to the protocol as per https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/201
Comment 1 orko 2024-09-09 22:37:25 UTC
Correction. The following step should be included:

3. Cover the app window with another window.
Comment 2 David Edmundson 2024-09-15 13:29:53 UTC
>3. Cover the app window with another window.

That will not send suspended, but we also still ack frame callbacks in this state so clients should behave.
Moving to another desktop or minimizing or locking the screen will send the suspended state and not ack frame callbacks.

This is working as *we* expect based on what was needed to make apps work correctly enough at the time.

Given your email address, I do want to know why you're asking. Is it affecting Chrome negatively?
Comment 3 orko 2024-09-16 21:32:13 UTC
> Is it affecting Chrome negatively?

Yes you're right it still continues sending frame callbacks but it appears it somehow ends up not releasing buffers when the window gets occluded.

For example, initially with an animation running in a chrome window, I see 3 buffers (53, 52, 51) being attached and released:
```
[2792322.937] wl_buffer#53.release()
[2792613.077]  -> wl_surface#31.attach(wl_buffer#51, 0, 0)
[2792617.577] wl_buffer#52.release()
[2792796.449]  -> wl_surface#31.attach(wl_buffer#53, 0, 0)
[2792801.144] wl_buffer#51.release()
[2793102.328]  -> wl_surface#31.attach(wl_buffer#52, 0, 0)
[2793107.900] wl_buffer#53.release()
[2793311.867]  -> wl_surface#31.attach(wl_buffer#51, 0, 0)
[2793317.832] wl_buffer#52.release()
[2793622.481]  -> wl_surface#31.attach(wl_buffer#53, 0, 0)
[2793628.009] wl_buffer#51.release()
[2793805.902]  -> wl_surface#31.attach(wl_buffer#52, 0, 0)
```

But then when the window is fully covered 2 of the buffers remain unreleased, which halts chromium rendering:
```
[2794624.698] wl_buffer#53.release()
[2794803.251]  -> wl_surface#31.attach(wl_buffer#51, 0, 0)
[2794816.491] wl_buffer#52.release()
[2795106.495]  -> wl_surface#31.attach(wl_buffer#53, 0, 0)
[2795111.186] wl_buffer#51.release()
[2795317.602]  -> wl_surface#31.attach(wl_buffer#52, 0, 0)
[2795323.820] wl_buffer#53.release()
[2795349.909]  -> wl_surface#31.attach(wl_buffer#51, 0, 0)
[2795409.049]  -> wl_surface#31.attach(wl_buffer#53, 0, 0)
[2795409.159] wl_buffer#51.release()
... This is where the animation and the logs stop. Note #53 and #52 are not returned ...
```

While this doesn't affect normal use cases, there is a use case in chrome that is broken when a window is put in background, viz. the tab capture feature where a tab is internally captured within chromium as opposed to capturing an entire window or screen. If the window containing the tab that is being captured is occluded the capture stops. So for instance sharing a slideshow tab containing animations will freeze when the window is covered by another window.

Logs and videos attached here: https://cloud.igalia.com/s/CewK5bS6oyB9gjM

I did notice that firefox for instance works around this issue by creating new buffers when previous buffers are blocked and continues to render. I could explore something like that on the chromium-side as well. But I am also interested to know if this is something that is unexpected in kwin and if it could be addressed there, e.g. by not doing any throttling at all or using `suspended` and throttling frame callbacks instead.
Comment 4 Zamundaaa 2024-09-19 20:41:24 UTC
Making KWin set the suspended state and stop sending frame callbacks on occluded windows is planned, but won't happen soon, and isn't sufficient to fix your problem in all situations. Applications have to handle the compositor keeping two buffers, that's a thing that can happen in many unavoidable situations, like direct scanout.