diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/tty.rs | 2 | ||||
| -rw-r--r-- | src/backend/winit.rs | 2 | ||||
| -rw-r--r-- | src/layout/focus_ring.rs | 19 | ||||
| -rw-r--r-- | src/layout/mod.rs | 17 | ||||
| -rw-r--r-- | src/layout/tile.rs | 39 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 8 | ||||
| -rw-r--r-- | src/niri.rs | 6 | ||||
| -rw-r--r-- | src/render_helpers/border.rs | 24 | ||||
| -rw-r--r-- | src/render_helpers/resize.rs | 13 | ||||
| -rw-r--r-- | src/render_helpers/shader_element.rs | 36 | ||||
| -rw-r--r-- | src/render_helpers/shaders/mod.rs | 29 |
11 files changed, 120 insertions, 75 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs index abcc93d3..327a5c97 100644 --- a/src/backend/tty.rs +++ b/src/backend/tty.rs @@ -502,6 +502,8 @@ impl Tty { } drop(config); + niri.layout.update_shaders(); + // Create the dmabuf global. let primary_formats = renderer.dmabuf_formats().collect::<HashSet<_>>(); let default_feedback = diff --git a/src/backend/winit.rs b/src/backend/winit.rs index f61c1c9f..ab71ea2e 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -142,6 +142,8 @@ impl Winit { } drop(config); + niri.layout.update_shaders(); + niri.add_output(self.output.clone(), None, false); } diff --git a/src/layout/focus_ring.rs b/src/layout/focus_ring.rs index 155d3254..18b5d5ca 100644 --- a/src/layout/focus_ring.rs +++ b/src/layout/focus_ring.rs @@ -51,6 +51,13 @@ impl FocusRing { self.config = config; } + pub fn update_shaders(&mut self) { + let mut borders = self.borders.borrow_mut(); + for elem in &mut *borders { + elem.damage_all(); + } + } + pub fn update(&mut self, win_size: Size<i32, Logical>, is_border: bool, radius: CornerRadius) { let width = i32::from(self.config.width); self.full_size = win_size + Size::from((width * 2, width * 2)); @@ -138,9 +145,9 @@ impl FocusRing { self.is_active = is_active; } - pub fn render<R: NiriRenderer>( + pub fn render( &self, - renderer: &mut R, + renderer: &mut impl NiriRenderer, location: Point<i32, Logical>, scale: Scale<f64>, view_size: Size<i32, Logical>, @@ -180,18 +187,14 @@ impl FocusRing { } else { 0. }; - let shader = BorderRenderElement::shader(renderer); - + let has_border_shader = BorderRenderElement::has_shader(renderer); let mut borders = self.borders.borrow_mut(); - for elem in &mut *borders { - elem.update_shader(shader); - } let mut push = |buffer, border: &mut BorderRenderElement, location: Point<i32, Logical>, size: Size<i32, Logical>| { - let elem = if border.has_shader() { + let elem = if has_border_shader { if let Some(gradient) = gradient { let gradient_area = match gradient.relative_to { GradientRelativeTo::Window => full_rect, diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 83715364..b670b9f5 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1371,6 +1371,23 @@ impl<W: LayoutElement> Layout<W> { } } + pub fn update_shaders(&mut self) { + match &mut self.monitor_set { + MonitorSet::Normal { monitors, .. } => { + for mon in monitors { + for ws in &mut mon.workspaces { + ws.update_shaders(); + } + } + } + MonitorSet::NoOutputs { workspaces, .. } => { + for ws in workspaces { + ws.update_shaders(); + } + } + } + } + pub fn update_config(&mut self, config: &Config) { let options = Rc::new(Options::from_config(config)); diff --git a/src/layout/tile.rs b/src/layout/tile.rs index b47afc76..99b2bc57 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -142,6 +142,11 @@ impl<W: LayoutElement> Tile<W> { self.options = options; } + pub fn update_shaders(&mut self) { + self.border.update_shaders(); + self.focus_ring.update_shaders(); + } + pub fn update_window(&mut self) { // FIXME: remove when we can get a fullscreen size right away. if self.fullscreen_size != Size::from((0, 0)) { @@ -594,7 +599,7 @@ impl<W: LayoutElement> Tile<W> { .map(Into::into), ); - if let Some(shader) = ResizeRenderElement::shader(renderer) { + if ResizeRenderElement::has_shader(renderer) { let gles_renderer = renderer.as_gles_renderer(); if let Some(texture_from) = resize.snapshot.texture(gles_renderer, scale, target) { @@ -623,7 +628,6 @@ impl<W: LayoutElement> Tile<W> { if let Some((texture_current, _sync_point, texture_current_geo)) = current { let elem = ResizeRenderElement::new( - shader, area, scale, texture_from.clone(), @@ -680,7 +684,7 @@ impl<W: LayoutElement> Tile<W> { .fit_to(window_size.w as f32, window_size.h as f32); let clip_shader = ClippedSurfaceRenderElement::shader(renderer).cloned(); - let border_shader = BorderRenderElement::shader(renderer).cloned(); + let has_border_shader = BorderRenderElement::has_shader(renderer); if clip_to_geometry && clip_shader.is_some() { let damage = self.rounded_corner_damage.element(); @@ -715,22 +719,19 @@ impl<W: LayoutElement> Tile<W> { // the unclipped window CSD already has corners rounded to the // user-provided radius, so our blocked-out rendering should match that // radius. - if radius != CornerRadius::default() { - if let Some(shader) = border_shader.clone() { - return BorderRenderElement::new( - &shader, - scale, - elem.geometry(Scale::from(1.)).to_logical(1), - Rectangle::from_loc_and_size(Point::from((0, 0)), geo.size), - elem.color(), - elem.color(), - 0., - elem.geometry(Scale::from(1.)).to_logical(1), - 0., - radius, - ) - .into(); - } + if radius != CornerRadius::default() && has_border_shader { + return BorderRenderElement::new( + scale, + elem.geometry(Scale::from(1.)).to_logical(1), + Rectangle::from_loc_and_size(Point::from((0, 0)), geo.size), + elem.color(), + elem.color(), + 0., + elem.geometry(Scale::from(1.)).to_logical(1), + 0., + radius, + ) + .into(); } // Otherwise, render the solid color as is. diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 1aa1a02b..3205d82b 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -333,6 +333,14 @@ impl<W: LayoutElement> Workspace<W> { self.options = options; } + pub fn update_shaders(&mut self) { + for col in &mut self.columns { + for tile in &mut col.tiles { + tile.update_shaders(); + } + } + } + pub fn windows(&self) -> impl Iterator<Item = &W> + '_ { self.columns .iter() diff --git a/src/niri.rs b/src/niri.rs index f3f5396a..0510d919 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -860,6 +860,7 @@ impl State { let mut output_config_changed = false; let mut window_rules_changed = false; let mut debug_config_changed = false; + let mut shaders_changed = false; let mut old_config = self.niri.config.borrow_mut(); // Reload the cursor. @@ -916,6 +917,7 @@ impl State { self.backend.with_primary_renderer(|renderer| { shaders::set_custom_resize_program(renderer, src); }); + shaders_changed = true; } if config.debug != old_config.debug { @@ -1018,6 +1020,10 @@ impl State { } } + if shaders_changed { + self.niri.layout.update_shaders(); + } + // Can't really update xdg-decoration settings since we have to hide the globals for CSD // due to the SDL2 bug... I don't imagine clients are prepared for the xdg-decoration // global suddenly appearing? Either way, right now it's live-reloaded in a sense that new diff --git a/src/render_helpers/border.rs b/src/render_helpers/border.rs index 6f2b7795..b0b373e2 100644 --- a/src/render_helpers/border.rs +++ b/src/render_helpers/border.rs @@ -8,8 +8,8 @@ use smithay::backend::renderer::utils::{CommitCounter, DamageSet}; use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform}; use super::renderer::NiriRenderer; -use super::shader_element::{ShaderProgram, ShaderRenderElement}; -use super::shaders::{mat3_uniform, Shaders}; +use super::shader_element::ShaderRenderElement; +use super::shaders::{mat3_uniform, ProgramType, Shaders}; use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; /// Renders a wide variety of borders and border parts. @@ -40,7 +40,6 @@ struct Parameters { impl BorderRenderElement { #[allow(clippy::too_many_arguments)] pub fn new( - shader: &ShaderProgram, scale: Scale<f64>, area: Rectangle<i32, Logical>, gradient_area: Rectangle<i32, Logical>, @@ -51,8 +50,7 @@ impl BorderRenderElement { border_width: f32, corner_radius: CornerRadius, ) -> Self { - let mut inner = ShaderRenderElement::empty(Kind::Unspecified); - inner.update_shader(Some(shader)); + let inner = ShaderRenderElement::empty(ProgramType::Border, Kind::Unspecified); let mut rv = Self { inner, params: Parameters { @@ -72,7 +70,7 @@ impl BorderRenderElement { } pub fn empty() -> Self { - let inner = ShaderRenderElement::empty(Kind::Unspecified); + let inner = ShaderRenderElement::empty(ProgramType::Border, Kind::Unspecified); Self { inner, params: Parameters { @@ -89,8 +87,8 @@ impl BorderRenderElement { } } - pub fn update_shader(&mut self, shader: Option<&ShaderProgram>) { - self.inner.update_shader(shader); + pub fn damage_all(&mut self) { + self.inner.damage_all(); } #[allow(clippy::too_many_arguments)] @@ -187,12 +185,10 @@ impl BorderRenderElement { ); } - pub fn has_shader(&self) -> bool { - self.inner.has_shader() - } - - pub fn shader(renderer: &mut impl NiriRenderer) -> Option<&ShaderProgram> { - Shaders::get(renderer).border.as_ref() + pub fn has_shader(renderer: &mut impl NiriRenderer) -> bool { + Shaders::get(renderer) + .program(ProgramType::Border) + .is_some() } } diff --git a/src/render_helpers/resize.rs b/src/render_helpers/resize.rs index c728689a..021c59bc 100644 --- a/src/render_helpers/resize.rs +++ b/src/render_helpers/resize.rs @@ -8,8 +8,8 @@ use smithay::backend::renderer::utils::{CommitCounter, DamageSet}; use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Size, Transform}; use super::renderer::{AsGlesFrame, NiriRenderer}; -use super::shader_element::{ShaderProgram, ShaderRenderElement}; -use super::shaders::{mat3_uniform, Shaders}; +use super::shader_element::ShaderRenderElement; +use super::shaders::{mat3_uniform, ProgramType, Shaders}; use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; #[derive(Debug)] @@ -18,7 +18,6 @@ pub struct ResizeRenderElement(ShaderRenderElement); impl ResizeRenderElement { #[allow(clippy::too_many_arguments)] pub fn new( - shader: ShaderProgram, area: Rectangle<i32, Logical>, scale: Scale<f64>, texture_prev: (GlesTexture, Rectangle<i32, Physical>), @@ -92,7 +91,7 @@ impl ResizeRenderElement { // Create the shader. Self(ShaderRenderElement::new( - Some(shader), + ProgramType::Resize, area, size, None, @@ -117,8 +116,10 @@ impl ResizeRenderElement { )) } - pub fn shader(renderer: &mut impl NiriRenderer) -> Option<ShaderProgram> { - Shaders::get(renderer).resize() + pub fn has_shader(renderer: &mut impl NiriRenderer) -> bool { + Shaders::get(renderer) + .program(ProgramType::Resize) + .is_some() } } diff --git a/src/render_helpers/shader_element.rs b/src/render_helpers/shader_element.rs index 75ed2780..4b4af625 100644 --- a/src/render_helpers/shader_element.rs +++ b/src/render_helpers/shader_element.rs @@ -14,12 +14,13 @@ use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Size}; use super::renderer::AsGlesFrame; use super::resources::Resources; +use super::shaders::{ProgramType, Shaders}; use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError}; /// Renders a shader with optional texture input, on the primary GPU. #[derive(Debug, Clone)] pub struct ShaderRenderElement { - shader: Option<ShaderProgram>, + program: ProgramType, id: Id, commit_counter: CommitCounter, area: Rectangle<i32, Logical>, @@ -197,7 +198,7 @@ impl ShaderProgram { impl ShaderRenderElement { #[allow(clippy::too_many_arguments)] pub fn new( - shader: Option<ShaderProgram>, + program: ProgramType, area: Rectangle<i32, Logical>, size: Size<f64, Buffer>, opaque_regions: Option<Vec<Rectangle<i32, Logical>>>, @@ -207,7 +208,7 @@ impl ShaderRenderElement { kind: Kind, ) -> Self { Self { - shader, + program, id: Id::new(), commit_counter: CommitCounter::default(), area, @@ -220,9 +221,9 @@ impl ShaderRenderElement { } } - pub fn empty(kind: Kind) -> Self { + pub fn empty(program: ProgramType, kind: Kind) -> Self { Self { - shader: None, + program, id: Id::new(), commit_counter: CommitCounter::default(), area: Rectangle::default(), @@ -235,12 +236,7 @@ impl ShaderRenderElement { } } - pub fn update_shader(&mut self, shader: Option<&ShaderProgram>) { - if self.shader.as_ref() == shader { - return; - } - - self.shader = shader.cloned(); + pub fn damage_all(&mut self) { self.commit_counter.increment(); } @@ -260,10 +256,6 @@ impl ShaderRenderElement { self.commit_counter.increment(); } - - pub fn has_shader(&self) -> bool { - self.shader.is_some() - } } impl Element for ShaderRenderElement { @@ -309,7 +301,7 @@ impl RenderElement<GlesRenderer> for ShaderRenderElement { ) -> Result<(), GlesError> { let frame = frame.as_gles_frame(); - let Some(shader) = &self.shader else { + let Some(shader) = Shaders::get_from_frame(frame).program(self.program) else { return Ok(()); }; @@ -389,14 +381,14 @@ impl RenderElement<GlesRenderer> for ShaderRenderElement { let has_debug = !frame.debug_flags().is_empty(); let has_tint = frame.debug_flags().contains(DebugFlags::TINT); - let program = if has_debug { - &shader.0.debug - } else { - &shader.0.normal - }; - // render frame.with_context(move |gl| -> Result<(), GlesError> { + let program = if has_debug { + &shader.0.debug + } else { + &shader.0.normal + }; + unsafe { for (i, texture) in self.textures.values().enumerate() { gl.ActiveTexture(ffi::TEXTURE0 + i as u32); diff --git a/src/render_helpers/shaders/mod.rs b/src/render_helpers/shaders/mod.rs index 5937fcc1..034d8db1 100644 --- a/src/render_helpers/shaders/mod.rs +++ b/src/render_helpers/shaders/mod.rs @@ -2,7 +2,8 @@ use std::cell::RefCell; use glam::Mat3; use smithay::backend::renderer::gles::{ - GlesError, GlesRenderer, GlesTexProgram, Uniform, UniformName, UniformType, UniformValue, + GlesError, GlesFrame, GlesRenderer, GlesTexProgram, Uniform, UniformName, UniformType, + UniformValue, }; use super::renderer::NiriRenderer; @@ -15,6 +16,12 @@ pub struct Shaders { pub custom_resize: RefCell<Option<ShaderProgram>>, } +#[derive(Debug, Clone, Copy)] +pub enum ProgramType { + Border, + Resize, +} + impl Shaders { fn compile(renderer: &mut GlesRenderer) -> Self { let _span = tracy_client::span!("Shaders::compile"); @@ -68,6 +75,12 @@ impl Shaders { } } + pub fn get_from_frame<'a>(frame: &'a mut GlesFrame<'_>) -> &'a Self { + let data = frame.egl_context().user_data(); + data.get() + .expect("shaders::init() must be called when creating the renderer") + } + pub fn get(renderer: &mut impl NiriRenderer) -> &Self { let renderer = renderer.as_gles_renderer(); let data = renderer.egl_context().user_data(); @@ -82,11 +95,15 @@ impl Shaders { self.custom_resize.replace(program) } - pub fn resize(&self) -> Option<ShaderProgram> { - self.custom_resize - .borrow() - .clone() - .or_else(|| self.resize.clone()) + pub fn program(&self, program: ProgramType) -> Option<ShaderProgram> { + match program { + ProgramType::Border => self.border.clone(), + ProgramType::Resize => self + .custom_resize + .borrow() + .clone() + .or_else(|| self.resize.clone()), + } } } |
