aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/tty.rs2
-rw-r--r--src/backend/winit.rs2
-rw-r--r--src/layout/focus_ring.rs19
-rw-r--r--src/layout/mod.rs17
-rw-r--r--src/layout/tile.rs39
-rw-r--r--src/layout/workspace.rs8
-rw-r--r--src/niri.rs6
-rw-r--r--src/render_helpers/border.rs24
-rw-r--r--src/render_helpers/resize.rs13
-rw-r--r--src/render_helpers/shader_element.rs36
-rw-r--r--src/render_helpers/shaders/mod.rs29
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()),
+ }
}
}