Damage window on corner radius changes

This commit is contained in:
Ivan Molodetskikh
2024-05-02 08:14:21 +04:00
parent 42cef79c69
commit 2f42f8ac75
4 changed files with 126 additions and 2 deletions
+22 -1
View File
@@ -19,7 +19,8 @@ use super::{
use crate::animation::Animation; use crate::animation::Animation;
use crate::niri_render_elements; use crate::niri_render_elements;
use crate::render_helpers::border::BorderRenderElement; use crate::render_helpers::border::BorderRenderElement;
use crate::render_helpers::clipped_surface::ClippedSurfaceRenderElement; use crate::render_helpers::clipped_surface::{ClippedSurfaceRenderElement, RoundedCornerDamage};
use crate::render_helpers::damage::ExtraDamage;
use crate::render_helpers::offscreen::OffscreenRenderElement; use crate::render_helpers::offscreen::OffscreenRenderElement;
use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::resize::ResizeRenderElement; use crate::render_helpers::resize::ResizeRenderElement;
@@ -68,6 +69,9 @@ pub struct Tile<W: LayoutElement> {
/// Snapshot of the last render for use in the close animation. /// Snapshot of the last render for use in the close animation.
unmap_snapshot: RefCell<Option<TileRenderSnapshot>>, unmap_snapshot: RefCell<Option<TileRenderSnapshot>>,
/// Extra damage for clipped surface corner radius changes.
rounded_corner_damage: RoundedCornerDamage,
/// Configurable properties of the layout. /// Configurable properties of the layout.
pub options: Rc<Options>, pub options: Rc<Options>,
} }
@@ -81,6 +85,7 @@ niri_render_elements! {
Resize = ResizeRenderElement, Resize = ResizeRenderElement,
Border = BorderRenderElement, Border = BorderRenderElement,
ClippedSurface = ClippedSurfaceRenderElement<R>, ClippedSurface = ClippedSurfaceRenderElement<R>,
ExtraDamage = ExtraDamage,
} }
} }
@@ -118,6 +123,7 @@ impl<W: LayoutElement> Tile<W> {
move_x_animation: None, move_x_animation: None,
move_y_animation: None, move_y_animation: None,
unmap_snapshot: RefCell::new(None), unmap_snapshot: RefCell::new(None),
rounded_corner_damage: Default::default(),
options, options,
} }
} }
@@ -180,6 +186,14 @@ impl<W: LayoutElement> Tile<W> {
.focus_ring .focus_ring
.resolve_against(self.options.focus_ring.into()); .resolve_against(self.options.focus_ring.into());
self.focus_ring.update_config(focus_ring_config.into()); self.focus_ring.update_config(focus_ring_config.into());
let window_size = self.window_size();
let radius = rules
.geometry_corner_radius
.unwrap_or_default()
.fit_to(window_size.w as f32, window_size.h as f32);
self.rounded_corner_damage.set_corner_radius(radius);
self.rounded_corner_damage.set_size(window_size);
} }
pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) { pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) {
@@ -650,6 +664,7 @@ impl<W: LayoutElement> Tile<W> {
// If we're not resizing, render the window itself. // If we're not resizing, render the window itself.
let mut window_surface = None; let mut window_surface = None;
let mut window_popups = None; let mut window_popups = None;
let mut rounded_corner_damage = None;
if resize_shader.is_none() && resize_fallback.is_none() { if resize_shader.is_none() && resize_fallback.is_none() {
let window = self let window = self
.window .window
@@ -667,6 +682,11 @@ impl<W: LayoutElement> Tile<W> {
let clip_shader = ClippedSurfaceRenderElement::shader(renderer).cloned(); let clip_shader = ClippedSurfaceRenderElement::shader(renderer).cloned();
let border_shader = BorderRenderElement::shader(renderer).cloned(); let border_shader = BorderRenderElement::shader(renderer).cloned();
if clip_to_geometry && clip_shader.is_some() {
let damage = self.rounded_corner_damage.element();
rounded_corner_damage = Some(damage.with_location(window_render_loc).into());
}
window_surface = Some(window.normal.into_iter().map(move |elem| match elem { window_surface = Some(window.normal.into_iter().map(move |elem| match elem {
LayoutElementRenderElement::Wayland(elem) => { LayoutElementRenderElement::Wayland(elem) => {
// If we should clip to geometry, render a clipped window. // If we should clip to geometry, render a clipped window.
@@ -727,6 +747,7 @@ impl<W: LayoutElement> Tile<W> {
.chain(resize_shader) .chain(resize_shader)
.chain(resize_fallback) .chain(resize_fallback)
.chain(window_popups.into_iter().flatten()) .chain(window_popups.into_iter().flatten())
.chain(rounded_corner_damage)
.chain(window_surface.into_iter().flatten()); .chain(window_surface.into_iter().flatten());
let elem = self.is_fullscreen.then(|| { let elem = self.is_fullscreen.then(|| {
+28 -1
View File
@@ -6,8 +6,9 @@ use smithay::backend::renderer::gles::{
GlesError, GlesFrame, GlesRenderer, GlesTexProgram, Uniform, GlesError, GlesFrame, GlesRenderer, GlesTexProgram, Uniform,
}; };
use smithay::backend::renderer::utils::{CommitCounter, DamageSet}; use smithay::backend::renderer::utils::{CommitCounter, DamageSet};
use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform}; use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Size, Transform};
use super::damage::ExtraDamage;
use super::renderer::{AsGlesFrame as _, NiriRenderer}; use super::renderer::{AsGlesFrame as _, NiriRenderer};
use super::shaders::{mat3_uniform, Shaders}; use super::shaders::{mat3_uniform, Shaders};
use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
@@ -21,6 +22,12 @@ pub struct ClippedSurfaceRenderElement<R: NiriRenderer> {
input_to_geo: Mat3, input_to_geo: Mat3,
} }
#[derive(Debug, Default, Clone)]
pub struct RoundedCornerDamage {
damage: ExtraDamage,
corner_radius: CornerRadius,
}
impl<R: NiriRenderer> ClippedSurfaceRenderElement<R> { impl<R: NiriRenderer> ClippedSurfaceRenderElement<R> {
pub fn new( pub fn new(
elem: WaylandSurfaceRenderElement<R>, elem: WaylandSurfaceRenderElement<R>,
@@ -267,3 +274,23 @@ impl<'render> RenderElement<TtyRenderer<'render>>
None None
} }
} }
impl RoundedCornerDamage {
pub fn set_size(&mut self, size: Size<i32, Logical>) {
self.damage.set_size(size);
}
pub fn set_corner_radius(&mut self, corner_radius: CornerRadius) {
if self.corner_radius == corner_radius {
return;
}
// FIXME: make the damage granular.
self.corner_radius = corner_radius;
self.damage.damage_all();
}
pub fn element(&self) -> ExtraDamage {
self.damage.clone()
}
}
+75
View File
@@ -0,0 +1,75 @@
use smithay::backend::renderer::element::{Element, Id, RenderElement};
use smithay::backend::renderer::utils::CommitCounter;
use smithay::backend::renderer::Renderer;
use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size};
#[derive(Debug, Clone)]
pub struct ExtraDamage {
id: Id,
commit: CommitCounter,
geometry: Rectangle<i32, Logical>,
}
impl ExtraDamage {
pub fn new() -> Self {
Self {
id: Id::new(),
commit: Default::default(),
geometry: Default::default(),
}
}
pub fn set_size(&mut self, size: Size<i32, Logical>) {
if self.geometry.size == size {
return;
}
self.geometry.size = size;
self.commit.increment();
}
pub fn damage_all(&mut self) {
self.commit.increment();
}
pub fn with_location(mut self, location: Point<i32, Logical>) -> Self {
self.geometry.loc = location;
self
}
}
impl Default for ExtraDamage {
fn default() -> Self {
Self::new()
}
}
impl Element for ExtraDamage {
fn id(&self) -> &Id {
&self.id
}
fn current_commit(&self) -> CommitCounter {
self.commit
}
fn src(&self) -> Rectangle<f64, Buffer> {
Rectangle::from_loc_and_size((0., 0.), (1., 1.))
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
self.geometry.to_physical_precise_round(scale)
}
}
impl<R: Renderer> RenderElement<R> for ExtraDamage {
fn draw(
&self,
_frame: &mut <R as Renderer>::Frame<'_>,
_src: Rectangle<f64, Buffer>,
_dst: Rectangle<i32, Physical>,
_damage: &[Rectangle<i32, Physical>],
) -> Result<(), R::Error> {
Ok(())
}
}
+1
View File
@@ -18,6 +18,7 @@ use self::primary_gpu_texture::PrimaryGpuTextureRenderElement;
pub mod border; pub mod border;
pub mod clipped_surface; pub mod clipped_surface;
pub mod damage;
pub mod offscreen; pub mod offscreen;
pub mod primary_gpu_texture; pub mod primary_gpu_texture;
pub mod render_elements; pub mod render_elements;