SUMMARY When using Firefox's WebRender Compositor, such as when enabling HDR, the window contents are severely corrupted. This code path makes extensive use of wayland subsurfaces, which the default Firefox settings avoid. This could well be a Wayland misuse by Firefox, but the same configuration used to work in KWin previously. STEPS TO REPRODUCE 1. Install Firefox Nightly 2. Set gfx.wayland.hdr to true and gfx.blocklist.all to -1 in about:config 3. Restart Firefox and maximize the window Note: gfx.blocklist.all is not required to reproduce, but Firefox is extremely unstable without it. Enabling HDR forces use of the WebRender Compositor. OBSERVED RESULT Severe graphical corruption EXPECTED RESULT Normal behavior SOFTWARE/OS VERSIONS Operating System: Arch Linux KDE Plasma Version: 6.5.90 KDE Frameworks Version: 6.22.0 Qt Version: 6.11.0 Kernel Version: 6.18.5-zen1-1-zen (64-bit) ADDITIONAL INFORMATION This is not a default configuration, but this setup was working in 6.5.5 and regressed in 6.6. Using Qt 6.11 since that's what Arch compiled the packages with.
That functionality is off by default in Firefox for a reason, it's known to be broken in several ways. I've never been able to use it without seeing some sort of glitches in it; it's very unlikely any of it is KWin's fault. If any specific problems can be narrowed down to be in KWin, that's worth a bug report, but at least as long as gfx.wayland.hdr is considered experimental, I don't think it makes sense to track any of its general problems here.
As I mentioned, I'm aware this is not enabled by default, and I also know the reputation of Firefox's Wayland support. However, the exact same configuration was working on 6.5.5, so some change in KWin was responsible for at least surfacing the issue. At any rate, I ran a git bisection and got this back: > 77eca9128d5402a0991e2e091e35532664ca3c18 is the first bad commit > commit 77eca9128d5402a0991e2e091e35532664ca3c18 > Author: Vlad Zahorodnii <> > Date: Sat Dec 6 11:31:21 2025 +0200 > > wayland: Port to Region I have no problem in doing more testing, but there's quite a lot of code in that class and I'd appreciate some pointers in debugging this further. For reference, this is the subsurface tree that Firefox is using: > Buffers > - wl_buffer@86 shm, width: 1, height: 1, format: 0, active: wl_surface@66 > - wl_buffer@170 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@262 > - wl_buffer@453 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@249 > - wl_buffer@412 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@114 > - wl_buffer@428 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@117 > - wl_buffer@82 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@419 > - wl_buffer@126 shm, width: 1524, height: 964, format: 0, active: wl_surface@69 > - wl_buffer@150 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@373 > - wl_buffer@461 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@103 > - wl_buffer@250 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@301 > - wl_buffer@417 linux-dmabuf, width: 1024, height: 512, format: 875708993, active: wl_surface@84 > Fractional scale > - wp_fractional_scale_v1@79, surface: wl_surface@66, scale: 1.000000 (120/120) > Outputs > - wl_output@19, scale: 1 > - wl_output@22, scale: 1 > - wl_output@53, scale: 1 > - wl_output@54, scale: 1 > Seats > - wl_seat@25 "seat0" > - wl_pointer@24, entered: <nil object>, x: 1484.97, y: 312.61, buttons held: 0 > - wl_keyboard@33, entered: <nil object>, keys held: 0 > - wl_seat@40 "seat0" > - wl_pointer@55, entered: <nil object>, x: 1484.97, y: 312.61, buttons held: 0 > - wl_keyboard@57, entered: <nil object>, keys held: 0 > Surfaces > - wl_surface@26, role: <unknown> > - wl_surface@29, role: <unknown> > - wl_surface@69, role: xdg_toplevel@71 of xdg_surface@70 > buffers: wl_buffer@126, total: 259 > active buffer: wl_buffer@126, scale: 1, frames: 185/185 > outputs: wl_output@53, wl_output@19 > app_id: firefox-nightly, title: Firefox Nightly > geom: x=45 y=45 w=1434 h=874, current: w=1434 h=874 > current states: > - wl_surface@66, role: wl_subsurface@77 > buffers: wl_buffer@86, total: 1 > active buffer: wl_buffer@86, frames: 2841/2841 > outputs: wl_output@53, wl_output@19 > desync: true, x: 45, y: 45 > - wl_surface@84, role: wl_subsurface@101 > buffers: wl_buffer@417, total: 361 > active buffer: wl_buffer@417, frames: 2406/2406 > outputs: wl_output@53, wl_output@19 > desync: false, x: 0, y: 0 > - wl_surface@114, role: wl_subsurface@102 > buffers: wl_buffer@412, total: 275 > active buffer: wl_buffer@412, frames: 2552/2552 > outputs: wl_output@53, wl_output@19 > desync: false, x: 0, y: 627 > - wl_surface@117, role: wl_subsurface@129 > buffers: wl_buffer@428, total: 271 > active buffer: wl_buffer@428, frames: 2547/2547 > outputs: wl_output@53, wl_output@19 > desync: false, x: 0, y: 115 > - wl_surface@103, role: wl_subsurface@139 > buffers: wl_buffer@461, total: 229 > active buffer: wl_buffer@461, frames: 2373/2373 > outputs: wl_output@53, wl_output@19 > desync: false, x: 267, y: 48 > - wl_surface@301, role: wl_subsurface@287 > buffers: wl_buffer@250, total: 129 > active buffer: wl_buffer@250, frames: 332/332 > outputs: wl_output@53, wl_output@19 > desync: false, x: 1024, y: 0 > - wl_surface@262, role: wl_subsurface@302 > buffers: wl_buffer@170, total: 74 > active buffer: wl_buffer@170, frames: 399/399 > outputs: wl_output@53, wl_output@19 > desync: false, x: 1024, y: 627 > - wl_surface@249, role: wl_subsurface@81 > buffers: wl_buffer@453, total: 74 > active buffer: wl_buffer@453, frames: 398/398 > outputs: wl_output@53, wl_output@19 > desync: false, x: 1024, y: 115 > - wl_surface@419, role: wl_subsurface@374 > buffers: wl_buffer@82, total: 20 > active buffer: wl_buffer@82, frames: 205/205 > outputs: wl_output@53, wl_output@19 > desync: false, x: 1368, y: 809 > - wl_surface@373, role: wl_subsurface@348 > buffers: wl_buffer@150, total: 13 > active buffer: wl_buffer@150, frames: 165/165 > outputs: wl_output@53, wl_output@19 > desync: false, x: 1024, y: 48 > - wl_surface@64, role: <unknown> > Viewports > - wp_viewport@80, surface: wl_surface@66, dest: w=1 h=1 > - wp_viewport@104, surface: wl_surface@84, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=1024 h=512 > - wp_viewport@122, surface: wl_surface@114, source: x=0.000000 y=0.000000 w=1024.000000 h=247.000000, dest: w=1024 h=247 > - wp_viewport@132, surface: wl_surface@117, source: x=0.000000 y=0.000000 w=1024.000000 h=512.000000, dest: w=1024 h=512 > - wp_viewport@142, surface: wl_surface@103, source: x=267.000000 y=48.000000 w=757.000000 h=32.000000, dest: w=757 h=32 > - wp_viewport@162, surface: wl_surface@301, source: x=0.000000 y=0.000000 w=410.000000 h=512.000000, dest: w=410 h=512 > - wp_viewport@118, surface: wl_surface@262, source: x=0.000000 y=0.000000 w=410.000000 h=247.000000, dest: w=410 h=247 > - wp_viewport@289, surface: wl_surface@249, source: x=0.000000 y=0.000000 w=410.000000 h=512.000000, dest: w=410 h=512 > - wp_viewport@100, surface: wl_surface@419, source: x=344.000000 y=297.000000 w=44.000000 h=44.000000, dest: w=44 h=44 > - wp_viewport@427, surface: wl_surface@373, source: x=0.000000 y=48.000000 w=179.000000 h=32.000000, dest: w=179 h=32
+1 For me its also very glitchy after upgrading to 6.6 Beta
> At any rate, I ran a git bisection and got this back Well, that is definitely such a "more specific" problem. Looking through the commit, nothing jumped out as wrong to me, but I tested partially reverting the patch bit by bit and found something... It actually looks like it fixed a bug though, rather than introducing it. This > target->bufferDamage = std::move(bufferDamage); didn't clear the bufferDamage region with QRegion, but it was supposed to. Running Firefox with WAYLAND_DEBUG shows that while it damages and uses really weird parts of some buffers (like 85, 0 5x368 on a 1024x512 buffer!), it seems to consistently damage the entire viewport of the surface every time before it commits. If I override the values passed to damage_buffer with an infinite region, the glitches still happen though, so something else is wrong.
I narrowed down the problem to this sequence of events: > damage_buffer(..) > attach(...) > commit(subsurface) > commit(subsurface) > commit(parent surface) The second commit on the subsurface overwrites the damage, and also some other critically important stuff.
A possibly relevant merge request was started @ https://invent.kde.org/plasma/kwin/-/merge_requests/8658
With the MR, it's back to a "normal" level of glitches for me (lines between the tiles Firefox renders)
Git commit d64f50b48bbc46f58d0178bd59cbd95318bd609f by Xaver Hugl. Committed on 15/01/2026 at 16:40. Pushed by zamundaaa into branch 'master'. wayland/surface: don't throw away damage on multiple sync subsurface commits Commits are always additive, even for sync subsurfaces. When the client commits damage on a subsurface and then commits on it again, before committing the parent surface, that damage must still be applied. M +3 -2 autotests/integration/CMakeLists.txt A +95 -0 autotests/integration/test_subsurface.cpp [License: GPL(v2.0+)] M +4 -2 src/wayland/surface.cpp https://invent.kde.org/plasma/kwin/-/commit/d64f50b48bbc46f58d0178bd59cbd95318bd609f
Git commit 7fc7987aa5b8534413e7a7216c474c2cbc702086 by Xaver Hugl. Committed on 15/01/2026 at 17:52. Pushed by zamundaaa into branch 'Plasma/6.6'. wayland/surface: don't throw away damage on multiple sync subsurface commits Commits are always additive, even for sync subsurfaces. When the client commits damage on a subsurface and then commits on it again, before committing the parent surface, that damage must still be applied. (cherry picked from commit d64f50b48bbc46f58d0178bd59cbd95318bd609f) Co-authored-by: Xaver Hugl <xaver.hugl@kde.org> M +3 -2 autotests/integration/CMakeLists.txt A +95 -0 autotests/integration/test_subsurface.cpp [License: GPL(v2.0+)] M +4 -2 src/wayland/surface.cpp https://invent.kde.org/plasma/kwin/-/commit/7fc7987aa5b8534413e7a7216c474c2cbc702086