Invalidate blur from per-output sampled backdrop damage
This commit is contained in:
1 parent
3d6cee125d
commit
325835f40a
13 files changed
+273
-82
No files matched your search
@@ -14,29 +14,6 @@ use super::{layer_shell, xdg_shell};
|
|||||||
use crate::Ferese;
|
use crate::Ferese;
|
||||||
use crate::state::ClientState;
|
use crate::state::ClientState;
|
||||||
|
|
||||||
fn layer_affects_backdrop(layer: smithay::wayland::shell::wlr_layer::Layer) -> bool {
|
|
||||||
matches!(
|
|
||||||
layer,
|
|
||||||
smithay::wayland::shell::wlr_layer::Layer::Background | smithay::wayland::shell::wlr_layer::Layer::Bottom
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ferese {
|
|
||||||
fn surface_affects_backdrop(&self, surface: &WlSurface) -> bool {
|
|
||||||
let mut root = surface.clone();
|
|
||||||
while let Some(parent) = get_parent(&root) {
|
|
||||||
root = parent;
|
|
||||||
}
|
|
||||||
if matches!(&self.cursor_status, smithay::input::pointer::CursorImageStatus::Surface(cursor) if cursor == &root)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
self.space
|
|
||||||
.layer_for_surface(&root, smithay::desktop::WindowSurfaceType::ALL)
|
|
||||||
.is_none_or(|layer| layer_affects_backdrop(layer.cached_state().layer))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompositorHandler for Ferese {
|
impl CompositorHandler for Ferese {
|
||||||
fn compositor_state(&mut self) -> &mut CompositorState {
|
fn compositor_state(&mut self) -> &mut CompositorState {
|
||||||
&mut self.compositor_state
|
&mut self.compositor_state
|
||||||
@@ -60,9 +37,6 @@ impl CompositorHandler for Ferese {
|
|||||||
fn commit(&mut self, surface: &WlSurface) {
|
fn commit(&mut self, surface: &WlSurface) {
|
||||||
self.update_surface_preferences(surface);
|
self.update_surface_preferences(surface);
|
||||||
self.capture_resize_before_commit(surface);
|
self.capture_resize_before_commit(surface);
|
||||||
if self.surface_affects_backdrop(surface) {
|
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
}
|
|
||||||
on_commit_buffer_handler::<Self>(surface);
|
on_commit_buffer_handler::<Self>(surface);
|
||||||
if !is_sync_subsurface(surface) {
|
if !is_sync_subsurface(surface) {
|
||||||
let mut root = surface.clone();
|
let mut root = surface.clone();
|
||||||
@@ -109,7 +83,7 @@ impl CompositorHandler for Ferese {
|
|||||||
.retain(|_, lock| lock.wl_surface() != surface);
|
.retain(|_, lock| lock.wl_surface() != surface);
|
||||||
self.focus_lock_surface();
|
self.focus_lock_surface();
|
||||||
}
|
}
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
crate::backends::direct::render_surface(self, surface);
|
crate::backends::direct::render_surface(self, surface);
|
||||||
if self.idle_inhibitors.remove(surface).is_some() {
|
if self.idle_inhibitors.remove(surface).is_some() {
|
||||||
self.refresh_idle_inhibition();
|
self.refresh_idle_inhibition();
|
||||||
@@ -142,17 +116,3 @@ impl ShmHandler for Ferese {
|
|||||||
&self.shm_state
|
&self.shm_state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use smithay::wayland::shell::wlr_layer::Layer;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
#[test]
|
|
||||||
fn panel_commits_do_not_invalidate_their_own_backdrop() {
|
|
||||||
assert!(!layer_affects_backdrop(Layer::Top));
|
|
||||||
assert!(!layer_affects_backdrop(Layer::Overlay));
|
|
||||||
assert!(layer_affects_backdrop(Layer::Bottom));
|
|
||||||
assert!(layer_affects_backdrop(Layer::Background));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -115,9 +115,6 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
// The decoder wakes the loop after publishing its result, including
|
// The decoder wakes the loop after publishing its result, including
|
||||||
// when no output has a pending frame.
|
// when no output has a pending frame.
|
||||||
let wallpaper_changed = state.wallpaper.poll();
|
let wallpaper_changed = state.wallpaper.poll();
|
||||||
if wallpaper_changed {
|
|
||||||
state.backdrop_generation = state.backdrop_generation.wrapping_add(1);
|
|
||||||
}
|
|
||||||
// All input/Wayland callbacks have returned, releasing seat locks.
|
// All input/Wayland callbacks have returned, releasing seat locks.
|
||||||
if state.focus_cycle.is_some() && (state.session_lock.active || state.input_capture.captures(1)) {
|
if state.focus_cycle.is_some() && (state.session_lock.active || state.input_capture.captures(1)) {
|
||||||
state.cancel_focus_cycle();
|
state.cancel_focus_cycle();
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub(super) struct Backdrop {
|
||||||
|
pub commit: CommitCounter,
|
||||||
|
sources: Vec<Source>,
|
||||||
|
region: Option<Rectangle<i32, Physical>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Source {
|
||||||
|
id: Id,
|
||||||
|
commit: CommitCounter,
|
||||||
|
geometry: Rectangle<i32, Physical>,
|
||||||
|
alpha: f32,
|
||||||
|
src: Rectangle<f64, Buffer>,
|
||||||
|
transform: Transform,
|
||||||
|
visible: Vec<Rectangle<i32, Physical>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backdrop {
|
||||||
|
fn update<E: Element>(
|
||||||
|
&mut self,
|
||||||
|
elements: &[E],
|
||||||
|
region: Rectangle<i32, Physical>,
|
||||||
|
scale: RenderScale<f64>,
|
||||||
|
) -> bool {
|
||||||
|
let mut uncovered = vec![region];
|
||||||
|
let mut sources = Vec::new();
|
||||||
|
let mut changed = self.region != Some(region);
|
||||||
|
|
||||||
|
for element in elements {
|
||||||
|
let geometry = element.geometry(scale);
|
||||||
|
let visible = uncovered
|
||||||
|
.iter()
|
||||||
|
.filter_map(|rect| rect.intersection(geometry))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if visible.is_empty() || element.alpha() == 0.0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let previous = self.sources.iter().find(|source| &source.id == element.id());
|
||||||
|
changed |= previous.is_none_or(|source| {
|
||||||
|
source.geometry != geometry
|
||||||
|
|| source.alpha != element.alpha()
|
||||||
|
|| source.src != element.src()
|
||||||
|
|| source.transform != element.transform()
|
||||||
|
|| source.visible != visible
|
||||||
|
});
|
||||||
|
if let Some(previous) = previous {
|
||||||
|
changed |= element.damage_since(scale, Some(previous.commit)).iter().any(|damage| {
|
||||||
|
let damage = Rectangle::new(damage.loc + geometry.loc, damage.size);
|
||||||
|
visible.iter().any(|rect| rect.overlaps(damage))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sources.push(Source {
|
||||||
|
id: element.id().clone(),
|
||||||
|
commit: element.current_commit(),
|
||||||
|
geometry,
|
||||||
|
alpha: element.alpha(),
|
||||||
|
src: element.src(),
|
||||||
|
transform: element.transform(),
|
||||||
|
visible,
|
||||||
|
});
|
||||||
|
if element.alpha() == 1.0 {
|
||||||
|
for opaque in element.opaque_regions(scale).iter() {
|
||||||
|
let opaque = Rectangle::new(opaque.loc + geometry.loc, opaque.size);
|
||||||
|
uncovered = uncovered
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|rect| rect.subtract_rect(opaque))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Membership and stacking changes matter even without buffer damage.
|
||||||
|
changed |= !self
|
||||||
|
.sources
|
||||||
|
.iter()
|
||||||
|
.map(|source| &source.id)
|
||||||
|
.eq(sources.iter().map(|source| &source.id));
|
||||||
|
self.sources = sources;
|
||||||
|
self.region = Some(region);
|
||||||
|
if changed {
|
||||||
|
self.commit.increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn update(elements: &[AnimatedWindowRenderElement], scale: f64) {
|
||||||
|
// Resolve lower blurs first so their damage propagates to higher materials.
|
||||||
|
for (index, element) in elements.iter().enumerate().rev() {
|
||||||
|
if let AnimatedWindowRenderElement::Blur(blur) = element {
|
||||||
|
let changed =
|
||||||
|
blur.backdrop
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.update(&elements[index + 1..], blur.geometry(scale.into()), scale.into());
|
||||||
|
if changed {
|
||||||
|
blur.capture_dirty.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct TestElement {
|
||||||
|
id: Id,
|
||||||
|
commit: CommitCounter,
|
||||||
|
rect: Rectangle<i32, Physical>,
|
||||||
|
damage: Vec<Rectangle<i32, Physical>>,
|
||||||
|
opaque: bool,
|
||||||
|
alpha: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestElement {
|
||||||
|
fn new(rect: Rectangle<i32, Physical>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: Id::new(),
|
||||||
|
commit: CommitCounter::default(),
|
||||||
|
rect,
|
||||||
|
damage: vec![],
|
||||||
|
opaque: false,
|
||||||
|
alpha: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn repaint(&mut self, damage: Vec<Rectangle<i32, Physical>>) {
|
||||||
|
self.commit.increment();
|
||||||
|
self.damage = damage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Element for TestElement {
|
||||||
|
fn id(&self) -> &Id {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
fn current_commit(&self) -> CommitCounter {
|
||||||
|
self.commit
|
||||||
|
}
|
||||||
|
fn src(&self) -> Rectangle<f64, Buffer> {
|
||||||
|
Rectangle::from_size((100.0, 100.0).into())
|
||||||
|
}
|
||||||
|
fn geometry(&self, _: RenderScale<f64>) -> Rectangle<i32, Physical> {
|
||||||
|
self.rect
|
||||||
|
}
|
||||||
|
fn damage_since(&self, _: RenderScale<f64>, commit: Option<CommitCounter>) -> DamageSet<i32, Physical> {
|
||||||
|
if commit == Some(self.commit) {
|
||||||
|
DamageSet::default()
|
||||||
|
} else {
|
||||||
|
DamageSet::from_slice(&self.damage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn opaque_regions(&self, _: RenderScale<f64>) -> OpaqueRegions<i32, Physical> {
|
||||||
|
if self.opaque {
|
||||||
|
OpaqueRegions::from_slice(&[Rectangle::from_size(self.rect.size)])
|
||||||
|
} else {
|
||||||
|
OpaqueRegions::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn alpha(&self) -> f32 {
|
||||||
|
self.alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect(x: i32, y: i32, w: i32, h: i32) -> Rectangle<i32, Physical> {
|
||||||
|
Rectangle::new((x, y).into(), (w, h).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn only_damage_intersecting_the_sample_invalidates_its_output() {
|
||||||
|
let mut first = Backdrop::default();
|
||||||
|
let mut second = Backdrop::default();
|
||||||
|
let region = rect(20, 20, 30, 30);
|
||||||
|
let mut a = TestElement::new(rect(0, 0, 100, 100));
|
||||||
|
let b = TestElement::new(rect(0, 0, 100, 100));
|
||||||
|
assert!(first.update(&[&a], region, 1.0.into()));
|
||||||
|
assert!(second.update(&[&b], region, 1.0.into()));
|
||||||
|
|
||||||
|
a.repaint(vec![]);
|
||||||
|
assert!(!first.update(&[&a], region, 1.0.into()));
|
||||||
|
a.repaint(vec![rect(60, 60, 10, 10)]);
|
||||||
|
assert!(!first.update(&[&a], region, 1.0.into()));
|
||||||
|
a.repaint(vec![rect(25, 25, 1, 1)]);
|
||||||
|
assert!(first.update(&[&a], region, 1.0.into()));
|
||||||
|
assert!(!second.update(&[&b], region, 1.0.into()));
|
||||||
|
assert!(!first.update(&[&a], region, 1.0.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn opaque_occlusion_hides_damage_but_fading_and_moving_reveal_it() {
|
||||||
|
let mut backdrop = Backdrop::default();
|
||||||
|
let region = rect(0, 0, 100, 100);
|
||||||
|
let mut front = TestElement::new(rect(0, 0, 50, 100));
|
||||||
|
front.opaque = true;
|
||||||
|
let mut back = TestElement::new(region);
|
||||||
|
assert!(backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
|
||||||
|
back.repaint(vec![rect(10, 10, 10, 10)]);
|
||||||
|
assert!(!backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
front.alpha = 0.5;
|
||||||
|
assert!(backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
back.repaint(vec![rect(10, 10, 10, 10)]);
|
||||||
|
assert!(backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
front.rect.loc.x = 20;
|
||||||
|
assert!(backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
assert!(!backdrop.update(&[&front, &back], region, 1.0.into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn membership_and_stacking_changes_invalidate_without_buffer_damage() {
|
||||||
|
let mut backdrop = Backdrop::default();
|
||||||
|
let region = rect(0, 0, 100, 100);
|
||||||
|
let a = TestElement::new(region);
|
||||||
|
let b = TestElement::new(region);
|
||||||
|
assert!(backdrop.update(&[&a, &b], region, 1.0.into()));
|
||||||
|
assert!(backdrop.update(&[&b, &a], region, 1.0.into()));
|
||||||
|
assert!(backdrop.update(&[&a], region, 1.0.into()));
|
||||||
|
assert!(backdrop.update(&[&a, &b], region, 1.0.into()));
|
||||||
|
assert!(!backdrop.update(&[&a, &b], region, 1.0.into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,8 @@ pub(super) fn append_material_surface(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(buffers) = state.render.surfaces.get_mut(surface) {
|
if let Some(buffers) = state.render.surfaces.get_mut(surface) {
|
||||||
buffers.contexts.retain(|(_, index), _| *index < targets.len());
|
buffers.contexts.retain(|(_, _, index), _| *index < targets.len());
|
||||||
|
buffers.captures.retain(|(_, _, index), _| *index < targets.len());
|
||||||
}
|
}
|
||||||
let material = (!materials.is_empty() && regions.is_none()).then_some(());
|
let material = (!materials.is_empty() && regions.is_none()).then_some(());
|
||||||
let clip = material.as_ref().and_then(|_| {
|
let clip = material.as_ref().and_then(|_| {
|
||||||
@@ -181,7 +182,6 @@ pub(super) fn material_element(
|
|||||||
presentation_alpha,
|
presentation_alpha,
|
||||||
background_opacity,
|
background_opacity,
|
||||||
blur: (blur * scale) as f32,
|
blur: (blur * scale) as f32,
|
||||||
scene_generation: if blur > 0.0 { state.backdrop_generation } else { 0 },
|
|
||||||
sample_geometry,
|
sample_geometry,
|
||||||
sample_physical,
|
sample_physical,
|
||||||
sample_framebuffer: framebuffer_clip_rect(sample_physical, mode.size, transform),
|
sample_framebuffer: framebuffer_clip_rect(sample_physical, mode.size, transform),
|
||||||
@@ -202,11 +202,13 @@ pub(super) fn material_element(
|
|||||||
.flatten();
|
.flatten();
|
||||||
let capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
|
let capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
|
||||||
let capture_size = Size::from((capture_rect[2], capture_rect[3]));
|
let capture_size = Size::from((capture_rect[2], capture_rect[3]));
|
||||||
|
let output_id = state.output_id(output)?;
|
||||||
|
let capture_key = (context.clone(), output_id, index);
|
||||||
let buffers = state.render.surfaces.entry(surface.clone()).or_default();
|
let buffers = state.render.surfaces.entry(surface.clone()).or_default();
|
||||||
let capture = if let Some(blur_program) = blur_program {
|
let capture = if let Some(blur_program) = blur_program {
|
||||||
if buffers
|
if buffers
|
||||||
.captures
|
.captures
|
||||||
.get(&context)
|
.get(&capture_key)
|
||||||
.is_none_or(|c| c.geometry != sample_geometry || c.texture.size() != capture_size)
|
.is_none_or(|c| c.geometry != sample_geometry || c.texture.size() != capture_size)
|
||||||
{
|
{
|
||||||
let texture = Offscreen::<GlesTexture>::create_buffer(renderer, Fourcc::Abgr8888, capture_size)
|
let texture = Offscreen::<GlesTexture>::create_buffer(renderer, Fourcc::Abgr8888, capture_size)
|
||||||
@@ -217,7 +219,7 @@ pub(super) fn material_element(
|
|||||||
.ok();
|
.ok();
|
||||||
if let Some(texture) = texture {
|
if let Some(texture) = texture {
|
||||||
buffers.captures.insert(
|
buffers.captures.insert(
|
||||||
context.clone(),
|
capture_key.clone(),
|
||||||
BlurCapture {
|
BlurCapture {
|
||||||
texture,
|
texture,
|
||||||
dirty: Arc::new(AtomicBool::new(true)),
|
dirty: Arc::new(AtomicBool::new(true)),
|
||||||
@@ -225,16 +227,16 @@ pub(super) fn material_element(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
buffers.captures.remove(&context);
|
buffers.captures.remove(&capture_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buffers
|
buffers
|
||||||
.captures
|
.captures
|
||||||
.get(&context)
|
.get(&capture_key)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|capture| (capture, blur_program))
|
.map(|capture| (capture, blur_program))
|
||||||
} else {
|
} else {
|
||||||
buffers.captures.remove(&context);
|
buffers.captures.remove(&capture_key);
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
if capture.is_some() {
|
if capture.is_some() {
|
||||||
@@ -261,7 +263,7 @@ pub(super) fn material_element(
|
|||||||
};
|
};
|
||||||
let cached = buffers
|
let cached = buffers
|
||||||
.contexts
|
.contexts
|
||||||
.entry((context, index))
|
.entry((context, output_id, index))
|
||||||
.or_insert_with(|| CachedMaterial {
|
.or_insert_with(|| CachedMaterial {
|
||||||
element: make_element(),
|
element: make_element(),
|
||||||
parameters: parameters.clone(),
|
parameters: parameters.clone(),
|
||||||
@@ -284,8 +286,15 @@ pub(super) fn material_element(
|
|||||||
cached.element = make_element();
|
cached.element = make_element();
|
||||||
}
|
}
|
||||||
if cached.parameters != parameters {
|
if cached.parameters != parameters {
|
||||||
cached.shadow.resize(parameters.shadow_bounds, None);
|
if cached.parameters.shadow_rect != parameters.shadow_rect
|
||||||
cached.shadow.update_uniforms(decoration_uniforms(¶meters, 2.0));
|
|| cached.parameters.shadow_values != parameters.shadow_values
|
||||||
|
|| cached.parameters.shadow_bounds != parameters.shadow_bounds
|
||||||
|
|| cached.parameters.radius != parameters.radius
|
||||||
|
|| cached.parameters.visible_framebuffer != parameters.visible_framebuffer
|
||||||
|
{
|
||||||
|
cached.shadow.resize(parameters.shadow_bounds, None);
|
||||||
|
cached.shadow.update_uniforms(decoration_uniforms(¶meters, 2.0));
|
||||||
|
}
|
||||||
match &mut cached.element {
|
match &mut cached.element {
|
||||||
MaterialElement::Fill(element) => {
|
MaterialElement::Fill(element) => {
|
||||||
element.resize(
|
element.resize(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
mod backdrop;
|
||||||
mod capture;
|
mod capture;
|
||||||
mod decorations;
|
mod decorations;
|
||||||
mod materials;
|
mod materials;
|
||||||
@@ -130,7 +131,7 @@ struct BlurRenderElement {
|
|||||||
texture: GlesTexture,
|
texture: GlesTexture,
|
||||||
program: GlesTexProgram,
|
program: GlesTexProgram,
|
||||||
id: Id,
|
id: Id,
|
||||||
commit: CommitCounter,
|
backdrop: Arc<std::sync::Mutex<backdrop::Backdrop>>,
|
||||||
geometry: Rectangle<i32, Logical>,
|
geometry: Rectangle<i32, Logical>,
|
||||||
capture_rect: [i32; 4],
|
capture_rect: [i32; 4],
|
||||||
uniforms: Arc<[Uniform<'static>]>,
|
uniforms: Arc<[Uniform<'static>]>,
|
||||||
@@ -148,7 +149,7 @@ impl BlurRenderElement {
|
|||||||
texture,
|
texture,
|
||||||
program,
|
program,
|
||||||
id: Id::new(),
|
id: Id::new(),
|
||||||
commit: CommitCounter::default(),
|
backdrop: Arc::default(),
|
||||||
geometry: parameters.sample_geometry,
|
geometry: parameters.sample_geometry,
|
||||||
capture_rect: framebuffer_capture_rect(parameters.sample_framebuffer),
|
capture_rect: framebuffer_capture_rect(parameters.sample_framebuffer),
|
||||||
uniforms: blur_uniforms(parameters).into(),
|
uniforms: blur_uniforms(parameters).into(),
|
||||||
@@ -156,11 +157,13 @@ impl BlurRenderElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, parameters: &MaterialParameters) {
|
fn update(&mut self, parameters: &MaterialParameters) {
|
||||||
self.capture_dirty.store(true, Ordering::Relaxed);
|
if self.capture_rect != framebuffer_capture_rect(parameters.sample_framebuffer) {
|
||||||
|
self.capture_dirty.store(true, Ordering::Relaxed);
|
||||||
|
}
|
||||||
self.geometry = parameters.sample_geometry;
|
self.geometry = parameters.sample_geometry;
|
||||||
self.capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
|
self.capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
|
||||||
self.uniforms = blur_uniforms(parameters).into();
|
self.uniforms = blur_uniforms(parameters).into();
|
||||||
self.commit.increment();
|
self.backdrop.lock().unwrap().commit.increment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +173,7 @@ impl Element for BlurRenderElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn current_commit(&self) -> CommitCounter {
|
fn current_commit(&self) -> CommitCounter {
|
||||||
self.commit
|
self.backdrop.lock().unwrap().commit
|
||||||
}
|
}
|
||||||
|
|
||||||
fn src(&self) -> Rectangle<f64, Buffer> {
|
fn src(&self) -> Rectangle<f64, Buffer> {
|
||||||
@@ -182,7 +185,7 @@ impl Element for BlurRenderElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn damage_since(&self, scale: RenderScale<f64>, commit: Option<CommitCounter>) -> DamageSet<i32, Physical> {
|
fn damage_since(&self, scale: RenderScale<f64>, commit: Option<CommitCounter>) -> DamageSet<i32, Physical> {
|
||||||
blur_damage(self.geometry(scale).size, self.commit, commit)
|
blur_damage(self.geometry(scale).size, self.current_commit(), commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opaque_regions(&self, _scale: RenderScale<f64>) -> OpaqueRegions<i32, Physical> {
|
fn opaque_regions(&self, _scale: RenderScale<f64>) -> OpaqueRegions<i32, Physical> {
|
||||||
@@ -311,7 +314,6 @@ struct MaterialParameters {
|
|||||||
presentation_alpha: f32,
|
presentation_alpha: f32,
|
||||||
background_opacity: f32,
|
background_opacity: f32,
|
||||||
blur: f32,
|
blur: f32,
|
||||||
scene_generation: u64,
|
|
||||||
sample_geometry: Rectangle<i32, Logical>,
|
sample_geometry: Rectangle<i32, Logical>,
|
||||||
sample_physical: Rectangle<i32, Physical>,
|
sample_physical: Rectangle<i32, Physical>,
|
||||||
sample_framebuffer: [f32; 4],
|
sample_framebuffer: [f32; 4],
|
||||||
@@ -341,8 +343,8 @@ struct CachedMaterial {
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct MaterialBuffers {
|
pub(crate) struct MaterialBuffers {
|
||||||
contexts: HashMap<(ErasedContextId, usize), CachedMaterial>,
|
contexts: HashMap<(ErasedContextId, ferese_core::OutputId, usize), CachedMaterial>,
|
||||||
captures: HashMap<ErasedContextId, BlurCapture>,
|
captures: HashMap<(ErasedContextId, ferese_core::OutputId, usize), BlurCapture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ impl RenderResources {
|
|||||||
|
|
||||||
pub fn remove_output(&mut self, id: OutputId) {
|
pub fn remove_output(&mut self, id: OutputId) {
|
||||||
self.outputs.remove(&id);
|
self.outputs.remove(&id);
|
||||||
|
for surface in self.surfaces.values_mut() {
|
||||||
|
surface.contexts.retain(|(_, output, _), _| *output != id);
|
||||||
|
surface.captures.retain(|(_, output, _), _| *output != id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snapshot(&self, id: &WindowId) -> Option<&ResizeSnapshot> {
|
pub fn snapshot(&self, id: &WindowId) -> Option<&ResizeSnapshot> {
|
||||||
@@ -105,8 +109,8 @@ impl RenderResources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for surface in self.surfaces.values_mut() {
|
for surface in self.surfaces.values_mut() {
|
||||||
surface.contexts.retain(|(id, _), _| id != context);
|
surface.contexts.retain(|(id, _, _), _| id != context);
|
||||||
surface.captures.remove(context);
|
surface.captures.retain(|(id, _, _), _| id != context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -340,6 +340,7 @@ pub(crate) fn sampled_output_elements(
|
|||||||
}
|
}
|
||||||
elements.push(previous.into());
|
elements.push(previous.into());
|
||||||
}
|
}
|
||||||
|
backdrop::update(&elements, scale);
|
||||||
elements
|
elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -346,7 +346,6 @@ pub struct Ferese {
|
|||||||
pub(crate) pending_logout: Option<u32>,
|
pub(crate) pending_logout: Option<u32>,
|
||||||
pub(crate) logout_query: Option<u32>,
|
pub(crate) logout_query: Option<u32>,
|
||||||
pub(crate) logout_owner: Option<ObjectId>,
|
pub(crate) logout_owner: Option<ObjectId>,
|
||||||
pub(crate) backdrop_generation: u64,
|
|
||||||
viewport_animations: HashMap<WorkspaceId, AnimatedValue>,
|
viewport_animations: HashMap<WorkspaceId, AnimatedValue>,
|
||||||
paused_workspaces: HashSet<WorkspaceId>,
|
paused_workspaces: HashSet<WorkspaceId>,
|
||||||
#[cfg(feature = "resize-metrics")]
|
#[cfg(feature = "resize-metrics")]
|
||||||
@@ -576,7 +575,6 @@ impl Ferese {
|
|||||||
pending_logout: None,
|
pending_logout: None,
|
||||||
logout_query: None,
|
logout_query: None,
|
||||||
logout_owner: None,
|
logout_owner: None,
|
||||||
backdrop_generation: 0,
|
|
||||||
viewport_animations: HashMap::new(),
|
viewport_animations: HashMap::new(),
|
||||||
paused_workspaces: HashSet::new(),
|
paused_workspaces: HashSet::new(),
|
||||||
#[cfg(feature = "resize-metrics")]
|
#[cfg(feature = "resize-metrics")]
|
||||||
@@ -761,7 +759,7 @@ impl Ferese {
|
|||||||
|
|
||||||
self.overview.set_font_family(config.overview_font_family);
|
self.overview.set_font_family(config.overview_font_family);
|
||||||
self.wallpaper.reload(config.wallpaper);
|
self.wallpaper.reload(config.wallpaper);
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
self.relayout();
|
self.relayout();
|
||||||
crate::backends::direct::render_all(self);
|
crate::backends::direct::render_all(self);
|
||||||
|
|
||||||
|
|||||||
@@ -468,9 +468,7 @@ impl Ferese {
|
|||||||
self.refresh_workspace_slide_offsets();
|
self.refresh_workspace_slide_offsets();
|
||||||
self.sync_window_stacking();
|
self.sync_window_stacking();
|
||||||
|
|
||||||
if active_animation || dim_changed {
|
active_animation |= dim_changed;
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
}
|
|
||||||
active_animation
|
active_animation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ impl Ferese {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layout_changed = self.unmap_invisible_windows(&visible);
|
self.unmap_invisible_windows(&visible);
|
||||||
|
|
||||||
let now = self.start_time.elapsed();
|
let now = self.start_time.elapsed();
|
||||||
|
|
||||||
@@ -268,7 +268,6 @@ impl Ferese {
|
|||||||
} else {
|
} else {
|
||||||
PresentationMode::Normal
|
PresentationMode::Normal
|
||||||
};
|
};
|
||||||
layout_changed |= !had_geometry || geometry.logical != rect;
|
|
||||||
let mut requested_size = geometry.set_presentation_mode(rect, mode, now);
|
let mut requested_size = geometry.set_presentation_mode(rect, mode, now);
|
||||||
if !was_mapped && (had_geometry || is_fullscreen) {
|
if !was_mapped && (had_geometry || is_fullscreen) {
|
||||||
geometry.settle_presentation();
|
geometry.settle_presentation();
|
||||||
@@ -405,10 +404,6 @@ impl Ferese {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if layout_changed {
|
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.sync_window_stacking();
|
self.sync_window_stacking();
|
||||||
self.retarget_overview();
|
self.retarget_overview();
|
||||||
self.send_shell_snapshots();
|
self.send_shell_snapshots();
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ impl Ferese {
|
|||||||
if let Some(swipe) = &mut self.focus_swipe {
|
if let Some(swipe) = &mut self.focus_swipe {
|
||||||
swipe.progress = progress;
|
swipe.progress = progress;
|
||||||
}
|
}
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
if let Some(output) = self
|
if let Some(output) = self
|
||||||
.focus_swipe
|
.focus_swipe
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -440,7 +440,7 @@ impl Ferese {
|
|||||||
.expect("gesture output exists")
|
.expect("gesture output exists")
|
||||||
.held_progress = Some(progress);
|
.held_progress = Some(progress);
|
||||||
self.refresh_workspace_slide_offsets();
|
self.refresh_workspace_slide_offsets();
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
if let Some(output) = self.outputs_by_id.get(&output).cloned() {
|
if let Some(output) = self.outputs_by_id.get(&output).cloned() {
|
||||||
self.defer_output_redraw(output);
|
self.defer_output_redraw(output);
|
||||||
}
|
}
|
||||||
@@ -464,7 +464,7 @@ impl Ferese {
|
|||||||
slide.gesture = Some((from, to, direction));
|
slide.gesture = Some((from, to, direction));
|
||||||
self.workspace_slides.insert(output, slide);
|
self.workspace_slides.insert(output, slide);
|
||||||
self.swipe.mark_preview_started();
|
self.swipe.mark_preview_started();
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
self.relayout();
|
self.relayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ impl Ferese {
|
|||||||
self.theme_settings = Config::resolved_theme_settings(&presented).expect("validated resolved theme");
|
self.theme_settings = Config::resolved_theme_settings(&presented).expect("validated resolved theme");
|
||||||
self.theme_engine.snapshot.presented = presented;
|
self.theme_engine.snapshot.presented = presented;
|
||||||
self.theme_engine.publish();
|
self.theme_engine.publish();
|
||||||
self.backdrop_generation = self.backdrop_generation.wrapping_add(1);
|
|
||||||
if complete {
|
if complete {
|
||||||
self.theme_engine.transition = None;
|
self.theme_engine.transition = None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
let mut backend = backend.borrow_mut();
|
let mut backend = backend.borrow_mut();
|
||||||
match event {
|
match event {
|
||||||
WinitEvent::Resized { size, scale_factor } => {
|
WinitEvent::Resized { size, scale_factor } => {
|
||||||
state.backdrop_generation = state.backdrop_generation.wrapping_add(1);
|
|
||||||
let scale = normalized_scale(scale_factor);
|
let scale = normalized_scale(scale_factor);
|
||||||
let rate = backend
|
let rate = backend
|
||||||
.window()
|
.window()
|
||||||
|
|||||||
Reference in new issue
Block a user