Created attachment 173023 [details] Firefox in overview BACKGROUND Firefox has support for wl_subsurface, which has not received much updates over last 3 years. At the time it was decided to let Firefox perform it's own compositing on Wayland instead, because system compositors were not good enough. As compositors improved in that time, this feature is getting relevant again because it's the only way to use power-efficient video overlays, otherwise Firefox force composites everything on it's own. The switch is gfx.webrender.compositor.force-enabled, unforunately it's heavily gated and hardcoded to be ignored unless the build is marked as Firefox Nightly. It may be possible to bring this feature back to life after testing, fixes and convincing upstream it's important because of power efficiency. SUMMARY KWin can randomly misplace part of the Firefox window while the proper place becomes transparent, I can't seem to replicate that on mutter. I also find it a little strange that even if the issue is proved to be on Firefox side, KWin doesn't intersect the subsurface with parent surface, which should eliminate it from view completely? Instead it creates this weird effect seen in the overview. STEPS TO REPRODUCE 1. Install Firefox nightly, go to about:config, gfx.webrender.compositor.force-enabled change to true 2. Open some website like YouTube 3. Resize the window multiple times, use F11 multiple times etc. OBSERVED RESULT Ultimately the window will bug out after some time, subsurface will be misplaced and it's proper place becomes transparent instead. In the overview you can see that the subsurface is rendered outside of window borders(the blue border once you focus the window) EXPECTED RESULT No bugs SOFTWARE/OS VERSIONS Linux/KDE Plasma: Fedora 40, KDE KDE Plasma Version: 6.1 KDE Frameworks Version: 6.5.0 Qt Version: 6.7.2 KWIN: 6.1.80/git master ADDITIONAL INFORMATION
Surface hierarchy at the time of the screenshot: Buffers - wl_buffer@47 shm, width: 32, height: 32, format: 0 - wl_buffer@61 shm, width: 1, height: 1, format: 0, active: wl_surface@55 - wl_buffer@64 shm, width: 64, height: 64, format: 0, active: wl_surface@23 - wl_buffer@45 shm, width: 64, height: 64, format: 0 - wl_buffer@69 shm, width: 64, height: 64, format: 0 - wl_buffer@68 shm, width: 64, height: 64, format: 0 - wl_buffer@180 shm, width: 64, height: 64, format: 0 - wl_buffer@192 shm, width: 64, height: 64, format: 0 - wl_buffer@294 shm, width: 64, height: 64, format: 0 - wl_buffer@170 shm, width: 64, height: 64, format: 0 - wl_buffer@375 shm, width: 64, height: 64, format: 0 - wl_buffer@1062 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@135 - wl_buffer@1397 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1321 - wl_buffer@1399 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1407 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1326 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1211 - wl_buffer@1439 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1384 - wl_buffer@1441 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1194 - wl_buffer@1443 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1435 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1328 - wl_buffer@1431 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@549 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1286 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1172 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1192 - wl_buffer@1083 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1329 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1333 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1190 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1323 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1390 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1458 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@421 - wl_buffer@1460 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1231 - wl_buffer@1462 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1464 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@438 - wl_buffer@1466 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1298 - wl_buffer@1468 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1470 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1405 - wl_buffer@1472 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1372 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1372 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1403 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@132 - wl_buffer@1236 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1199 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1491 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1419 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1240 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1300 - wl_buffer@1447 linux-dmabuf, width: 1024, height: 512, format: 875713089, active: wl_surface@1278 - wl_buffer@1411 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1393 linux-dmabuf, width: 1024, height: 512, format: 875713089 - wl_buffer@1345 shm, width: 2880, height: 1800, format: 0, active: wl_surface@51 Outputs - wl_output@16, scale: 2 Seats - wl_seat@19 - wl_pointer@18, entered: <nil object>, x: 804.84, y: 117.29, buttons held: 0 - wl_keyboard@27, entered: <nil object>, keys held: 0 - wl_seat@34 - wl_keyboard@41, entered: <nil object>, keys held: 0 Surfaces - wl_surface@20, role: <unknown> - wl_surface@23, role: wl_pointer@18 buffers: wl_buffer@64, total: 314 active buffer: wl_buffer@64, scale: 2 outputs: wl_output@16 - wl_surface@51, role: xdg_toplevel@53 of xdg_surface@52 buffers: wl_buffer@1345, total: 443 active buffer: wl_buffer@1345, scale: 2, frames: 401/402 outputs: wl_output@16 app_id: firefox-nightly, title: Firefox Nightly geom: x=0 y=0 w=1440 h=900, current: w=1440 h=900 current states: fullscreen, suspended - wl_surface@55, role: wl_subsurface@56 buffers: wl_buffer@61, total: 1 active buffer: wl_buffer@61, frames: 395/396 outputs: wl_output@16 desync: true, x: 0, y: 0 - wl_surface@438, role: wl_subsurface@419 buffers: wl_buffer@1464, total: 832 active buffer: wl_buffer@1464, frames: 5796/5798 outputs: wl_output@16 desync: false, x: 0, y: 84 - wl_surface@132, role: wl_subsurface@396 buffers: wl_buffer@1403, total: 761 active buffer: wl_buffer@1403, frames: 5138/5140 outputs: wl_output@16 desync: false, x: 0, y: 340 - wl_surface@135, role: wl_subsurface@406 buffers: wl_buffer@1062, total: 748 active buffer: wl_buffer@1062, frames: 5136/5138 outputs: wl_output@16 desync: false, x: 512, y: 340 outputs: wl_output@16 - wl_surface@421, role: wl_subsurface@81 buffers: wl_buffer@1458, total: 748 active buffer: wl_buffer@1458, frames: 5117/5119 outputs: wl_output@16 desync: false, x: 512, y: 84 - wl_surface@1321, role: wl_subsurface@1334 buffers: wl_buffer@1397, total: 55 active buffer: wl_buffer@1397, frames: 1208/1210 outputs: wl_output@16 desync: false, x: 1024, y: 596 - wl_surface@1328, role: wl_subsurface@1274 buffers: wl_buffer@1435, total: 55 active buffer: wl_buffer@1435, frames: 1207/1209 outputs: wl_output@16 desync: false, x: 512, y: 596 - wl_surface@1278, role: wl_subsurface@1244 buffers: wl_buffer@1447, total: 55 active buffer: wl_buffer@1447, frames: 1204/1206 outputs: wl_output@16 desync: false, x: 1024, y: 84 - wl_surface@1211, role: wl_subsurface@1376 buffers: wl_buffer@1326, total: 55 active buffer: wl_buffer@1326, frames: 1198/1200 outputs: wl_output@16 desync: false, x: 1024, y: 340 - wl_surface@1300, role: wl_subsurface@489 buffers: wl_buffer@1240, total: 55 active buffer: wl_buffer@1240, frames: 1193/1195 outputs: wl_output@16 desync: false, x: 1024, y: 852 - wl_surface@1192, role: wl_subsurface@78 buffers: wl_buffer@1172, total: 55 active buffer: wl_buffer@1172, frames: 1192/1194 outputs: wl_output@16 desync: false, x: 512, y: 852 - wl_surface@1384, role: wl_subsurface@1415 buffers: wl_buffer@1439, total: 55 active buffer: wl_buffer@1439, frames: 1187/1189 outputs: wl_output@16 desync: false, x: 0, y: 852 - wl_surface@1194, role: wl_subsurface@1337 buffers: wl_buffer@1441, total: 55 active buffer: wl_buffer@1441, frames: 1182/1184 outputs: wl_output@16 desync: false, x: 0, y: 596 - wl_surface@1405, role: wl_subsurface@1487 buffers: wl_buffer@1470, total: 87 active buffer: wl_buffer@1470, frames: 257/258 outputs: wl_output@16 desync: false, x: 1024, y: 0 - wl_surface@1231, role: wl_subsurface@1478 buffers: wl_buffer@1460, total: 87 active buffer: wl_buffer@1460, frames: 257/258 outputs: wl_output@16 desync: false, x: 512, y: 0 - wl_surface@1298, role: wl_subsurface@1482 buffers: wl_buffer@1466, total: 87 active buffer: wl_buffer@1466, frames: 257/258 outputs: wl_output@16 desync: false, x: 0, y: 0 - wl_surface@65, role: <unknown> - wl_surface@60, role: <unknown> - wl_surface@67, role: <unknown> - wl_surface@58, role: <unknown> - wl_surface@123, role: <unknown> - wl_surface@337, role: <unknown> - wl_surface@411, role: <unknown> - wl_surface@903, role: <unknown> Viewports - wp_viewport@420, surface: wl_surface@438, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@394, surface: wl_surface@132, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@113, surface: wl_surface@421, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@77, surface: wl_surface@135, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@1182, surface: wl_surface@1300, source: x=0.000000 y=0.000000 w=832.000000 h=95.000000, dest: w=416 h=48 - wp_viewport@1341, surface: wl_surface@1278, source: x=0.000000 y=0.000000 w=832.000000 h=512.000000, dest: w=416 h=256 - wp_viewport@1413, surface: wl_surface@1328, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@1421, surface: wl_surface@1211, source: x=0.000000 y=0.000000 w=832.000000 h=512.000000, dest: w=416 h=256 - wp_viewport@1316, surface: wl_surface@1194, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@1310, surface: wl_surface@1192, source: x=0.000000 y=0.000000 w=1024.000000 h=95.000000, dest: w=512 h=48 - wp_viewport@1151, surface: wl_surface@1321, source: x=0.000000 y=0.000000 w=832.000000 h=512.000000, dest: w=416 h=256 - wp_viewport@1359, surface: wl_surface@1384, source: x=0.000000 y=0.000000 w=1024.000000 h=95.000000, dest: w=512 h=48 - wp_viewport@1499, surface: wl_surface@1298, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@1455, surface: wl_surface@1231, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=512 h=256 - wp_viewport@1484, surface: wl_surface@1405, source: x=0.000000 y=0.000000 w=832.000000 h=512.000000, dest: w=416 h=256
WAYLAND_DEBUG=1 ./firefox may be used to print Wayland calls, and the suspicious API calls that Firefox uses are (in no specific order): [3175848.494] {Default Queue} -> wl_subcompositor#38.get_subsurface(new id wl_subsurface#853, wl_surface#748, wl_surface#55) [3175848.498] {Default Queue} -> wl_subsurface#853.place_above(wl_surface#898) [3175848.503] {Default Queue} -> wl_subsurface#853.set_position(1435, 86) [3175848.719] {Default Queue} -> wl_subsurface#773.destroy()
Is firefox ok when not in the overview?
Created attachment 173028 [details] second variant of the bug A second "variant" of the bug. Moving cursor over the bugged transparent area results in duplicate visible cursors or sometimes unrelated content from another window. That suggest, along with damage tracking and buffer aging, that one part of KWin may see the subsurface in it's proper place and the other one does not.
Created attachment 173029 [details] second variant of the bug #2 and the screenshout of bugs happening in transparent area to above question: no, outside of the overview Firefox is also not OK
gfx.webrender.compositor.force-enabled used to have bugs last time I tested it and I won't be surprised if those issues still persist up to this day because the clients often get subsurface wrong way. > KWin doesn't intersect the subsurface with parent surface It must not do that, subsurfaces can stick outside their parent surface.
The layer compositor option doesn't work for me in Firefox Nightly. Either way, please report this issue to firefox developers.
some investigation would be nice, if not for Firefox, at least for the fact that the transparent area renders garbage breaking damage/buffer age tracking. if Firefox really sends wrong data (even though I see nothing suspicious from the surface dump I pasted earlier), new asserts could be added to reject it one way or another
> the transparent area renders garbage breaking damage/buffer age tracking ff sets the opaque region for the main surface (it mainly contains the client side drop shadow). if a subsurface is translucent or not covering that part of the main surface, you're going to see visual artifacts as on one of the screenshots
hm, are you saying the corruption would trigger for every app where the application lies about effective opaque region? I think that would make sense, and there's no way to reasonably protect against that without scanning pixels every frame. that btw. reminded me of another app that lies about opaque regions - Telegram fullscreen viewer of image attachments. it does a direct scanout, but as soon as you press Meta and open the KDE menu, it starts underlaying other windows in unused areas. but this one can't be turned into corruption in any way I can think of, so just a fun fact
Git commit 7431ea1f8a5f08d412e447a3ddd3d668a7c1ca28 by David Edmundson. Committed on 19/09/2024 at 13:28. Pushed by cullmann into branch 'master'. kdbusservice: Don't unregister service name slightly before exit The DBus service name will be revoked when the application closes automatically by the daemon. Doing so early just means that the original service has not fully cleaned up yet. When using "plasmashell --replace" it means the new instance launches slightly before the old one has fully quit saving files and before it the old instance unregisters it's own keyboard shortcuts, which breaks the new one. M +0 -6 src/kdbusservice.cpp M +2 -7 src/kdbusservice.h https://invent.kde.org/frameworks/kdbusaddons/-/commit/7431ea1f8a5f08d412e447a3ddd3d668a7c1ca28
Whoops, that was meant for Bug 493200, not this one.