fit layer buffers during output resize

This commit is contained in:
Samuel Onoja committed 2026-09-25 08:21:54 +01:00
1 parent 05fb4280f5
commit 0420242350
1 file changed
+54 -20
+54 -20
View File
@@ -1452,26 +1452,30 @@ fn layer_elements(
let mut elements = Vec::new(); let mut elements = Vec::new();
for (geometry, layer) in layers { for (geometry, layer) in layers {
elements.extend( let target = geometry.to_physical_precise_round(scale);
AsRenderElements::<GlesRenderer>::render_elements::< let surface_elements = AsRenderElements::<GlesRenderer>::render_elements::<
WaylandSurfaceRenderElement<GlesRenderer>, WaylandSurfaceRenderElement<GlesRenderer>,
>( >(&layer, renderer, target.loc, scale.into(), 1.0);
&layer, let source_bounds = surface_elements
renderer, .iter()
geometry.loc.to_physical_precise_round(scale), .map(|element| element.geometry(scale.into()))
scale.into(), .reduce(Rectangle::merge);
1.0, let content_scale = source_bounds
) .map(|source| layer_content_scale(source.size, target.size))
.into_iter() .unwrap_or_else(|| RenderScale::from(1.0));
.filter_map(|element| { let scale_origin = source_bounds.map_or(target.loc, |source| source.loc);
let origin = Point::<i32, Physical>::default(); let crop = target.intersection(output_crop).unwrap_or_default();
let element = RescaleRenderElement::from_element(element, origin, 1.0);
let element =
RelocateRenderElement::from_element(element, origin, Relocate::Relative);
CropRenderElement::from_element(element, scale, output_crop).map(Into::into) elements.extend(surface_elements.into_iter().filter_map(|element| {
}), let element = RescaleRenderElement::from_element(element, scale_origin, content_scale);
); let element = RelocateRenderElement::from_element(
element,
Point::<i32, Physical>::default(),
Relocate::Relative,
);
CropRenderElement::from_element(element, scale, crop).map(Into::into)
}));
if let Some(material) = material_element(state, renderer, output, &layer, geometry) { if let Some(material) = material_element(state, renderer, output, &layer, geometry) {
elements.push(material); elements.push(material);
@@ -1481,6 +1485,20 @@ fn layer_elements(
elements elements
} }
fn layer_content_scale(
source: Size<i32, Physical>,
target: Size<i32, Physical>,
) -> RenderScale<f64> {
if source.w <= 0 || source.h <= 0 || target.w <= 0 || target.h <= 0 {
return RenderScale::from(1.0);
}
RenderScale::from((
f64::from(target.w) / f64::from(source.w),
f64::from(target.h) / f64::from(source.h),
))
}
fn material_element( fn material_element(
state: &mut Ferese, state: &mut Ferese,
renderer: &mut GlesRenderer, renderer: &mut GlesRenderer,
@@ -1813,7 +1831,8 @@ mod tests {
use super::{ use super::{
color_with_alpha, expanded_blur_region, framebuffer_capture_rect, framebuffer_clip_rect, color_with_alpha, expanded_blur_region, framebuffer_capture_rect, framebuffer_clip_rect,
normalized_scale, rounded_visual_rect, scaled_visual_rect, shadow_bounds, layer_content_scale, normalized_scale, rounded_visual_rect, scaled_visual_rect,
shadow_bounds,
}; };
#[derive(Debug)] #[derive(Debug)]
@@ -1866,6 +1885,21 @@ mod tests {
assert_eq!(normalized_scale(f64::INFINITY), 1.0); assert_eq!(normalized_scale(f64::INFINITY), 1.0);
} }
#[test]
fn layer_content_tracks_new_allocation_before_the_client_repaints() {
let scale = layer_content_scale((1_000, 40).into(), (1_600, 40).into());
assert_eq!(scale, Scale::from((1.6, 1.0)));
}
#[test]
fn layer_content_scale_ignores_empty_allocations() {
assert_eq!(
layer_content_scale((0, 40).into(), (1_600, 40).into()),
Scale::from(1.0)
);
}
#[test] #[test]
fn clip_rect_matches_smithay_gles_projection() { fn clip_rect_matches_smithay_gles_projection() {
let geometry = Rectangle::<i32, Physical>::new((10, 5).into(), (30, 40).into()); let geometry = Rectangle::<i32, Physical>::new((10, 5).into(), (30, 40).into());