srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/winit
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-02-17 22:04:00 +0200
committersrdusr <[email protected]>2025-02-17 22:04:00 +0200
commit78d889c48e5b1336c73f28a2e2d5c8a571c7dd43 (patch)
tree4f930c85e79f5f37a3c4e515de885cf1f80f2314 /crates/wayland/src/winit
parent0a4c4b5941fe982ccb3d3175e26d9d83f0025ffd (diff)
parentf7c6e9c607742ed373752aadf5761e99ec3eb64a (diff)
downloadsrdwm-78d889c48e5b1336c73f28a2e2d5c8a571c7dd43.tar.gz
srdwm-78d889c48e5b1336c73f28a2e2d5c8a571c7dd43.zip
Merge branch 'main' into rust-rewrite
# Conflicts: # crates/config/src/engine/general.rs # crates/wayland/src/udev/drm.rs # crates/wayland/src/udev/mod.rs # crates/wayland/src/udev/render.rs # crates/wayland/src/winit/render.rs
Diffstat (limited to 'crates/wayland/src/winit')
-rw-r--r--crates/wayland/src/winit/render.rs71
1 files changed, 60 insertions, 11 deletions
diff --git a/crates/wayland/src/winit/render.rs b/crates/wayland/src/winit/render.rs
index 60cccb4..5784520 100644
--- a/crates/wayland/src/winit/render.rs
+++ b/crates/wayland/src/winit/render.rs
@@ -20,7 +20,41 @@ impl WaylandPlatform {
layer_map_for_output(&self.output).arrange();
}
- let age = self.backend.buffer_age().unwrap_or(0);
+ // Always `0` ("contents undefined, damage everything"), not
+ // `self.backend.buffer_age()` - deliberately never trusted here,
+ // confirmed live to actually be the source of a real corruption
+ // bug, not just a missed optimization. `age` tells
+ // `damage_tracker.render_output` how many past frames' worth of
+ // damage history it can trust the *current* target buffer to
+ // already reflect, so it can skip repainting regions nothing has
+ // touched since. That guarantee depends on the platform's own
+ // buffer-age report being an honest account of this exact backing
+ // buffer's real history - which this backend cannot get from a
+ // nested `winit`/EGL surface hosted inside another Wayland
+ // session: reproduced live, stable, not a one-frame race --
+ // raising one floating window (Firefox) above another (a plain
+ // terminal) left a rectangular patch of the terminal's own old
+ // pixels sitting untouched at one edge of Firefox's new, larger,
+ // fully-opaque topmost window, persisting indefinitely across
+ // many further frames with no damage anywhere near it to explain
+ // clearing it. Forcing `age = 0` here (full redraw, every frame)
+ // made the corruption disappear completely and immediately, and
+ // nothing else about the scene changed - narrowing the cause to
+ // exactly this value being wrong, not a geometry, occlusion, or
+ // z-order bug elsewhere in this file (all independently verified
+ // correct against the same repro: the window's own border and
+ // content elements were logged as computed with the right full
+ // geometry and zero occluders on every single one of the frames
+ // that still rendered the stale patch). Real hardware's udev
+ // backend is not affected - it never queries a platform buffer
+ // age at all, only its own hand-tracked `UdevHead::ages`, advanced
+ // deterministically from this codebase's own strict two-buffer
+ // page-flip alternation, not borrowed trust in an outer
+ // compositor's EGL implementation. This backend exists for nested
+ // development/testing, not as the real compositor, so paying a
+ // full software-composited redraw every frame here is the safe
+ // trade against silently wrong pixels persisting on screen.
+ let age = 0;
let (renderer, mut framebuffer) = self.backend.bind().map_err(err)?;
// Locked: srdwm's own native lock UI, or an external locker's
@@ -285,18 +319,33 @@ impl WaylandPlatform {
// "spacing before the border". Positioned from `geom`, not
// `w.geometry`, same reasoning as the border above (a stale-
// position shadow during an animated tween looks as detached
- // as the border did before that fix). Not fragment-clipped
- // against `occluders` like the titlebar/border above: at
- // `SHADOW_MAX_ALPHA`'s low opacity, a shadow bleeding slightly
- // onto a window stacked in front of this one reads as a soft
- // edge, not the hard-line bleed-through that made the
- // titlebar/border need it.
+ // as the border did before that fix).
+ //
+ // Fragment-clipped against `occluders` now, same as the
+ // titlebar/border above - this used to skip that on the
+ // reasoning that `SHADOW_MAX_ALPHA`'s low opacity would read
+ // as a soft edge, not the hard-line bleed-through that made
+ // the titlebar/border need it. True along a shadow's straight
+ // edges, false at its corners: `shadow_bitmap` falls off by
+ // Chebyshev (square-ring) distance, not radial, so each corner
+ // is a hard-edged square block at up to ~35% opacity, not a
+ // soft vignette - reported live as a small dark rectangular
+ // patch sitting on top of whatever window a floating/cascaded
+ // window's own corner happened to overlap, most visible
+ // exactly where two windows' corners nearly meet, which this
+ // compositor's default cascade placement does constantly.
if let Some(shadow) = self.state.shadow_buffers.get(&id) {
let rect = decoration::shadow_rect(frame);
- let pos = (rect.x as f64, rect.y as f64);
- match MemoryRenderBufferRenderElement::from_buffer(renderer, pos, shadow, None, None, None, Kind::Unspecified) {
- Ok(elem) => custom_elements.push(crate::rounded_corners::WinitElement::Base(crate::elements::OverlayElement::Memory(elem))),
- Err(e) => log::warn!("failed to import shadow buffer for window {id}: {e}"),
+ for fragment in crate::elements::visible_border_fragments(rect, &occluders) {
+ let pos = (fragment.x as f64, fragment.y as f64);
+ let src = Rectangle::new(
+ Point::from(((fragment.x - rect.x) as f64, (fragment.y - rect.y) as f64)),
+ Size::from((fragment.width as f64, fragment.height as f64)),
+ );
+ match MemoryRenderBufferRenderElement::from_buffer(renderer, pos, shadow, None, Some(src), None, Kind::Unspecified) {
+ Ok(elem) => custom_elements.push(crate::rounded_corners::WinitElement::Base(crate::elements::OverlayElement::Memory(elem))),
+ Err(e) => log::warn!("failed to import shadow buffer for window {id}: {e}"),
+ }
}
}
// The window's own content, at its own `opacity` - see the