mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:00:18 +07:00
shader_element: Make shader optional
The element is long-lived, but the shader itself isn't.
This commit is contained in:
@@ -64,7 +64,7 @@ impl TestCase for GradientAngle {
|
||||
BorderRenderElement::shader(renderer)
|
||||
.map(|shader| {
|
||||
BorderRenderElement::new(
|
||||
shader.clone(),
|
||||
shader,
|
||||
Scale::from(1.),
|
||||
area,
|
||||
area,
|
||||
|
||||
@@ -101,7 +101,7 @@ impl TestCase for GradientArea {
|
||||
BorderRenderElement::shader(renderer)
|
||||
.map(|shader| {
|
||||
BorderRenderElement::new(
|
||||
shader.clone(),
|
||||
shader,
|
||||
Scale::from(1.),
|
||||
area,
|
||||
g_area,
|
||||
|
||||
+18
-36
@@ -17,7 +17,7 @@ pub struct FocusRing {
|
||||
buffers: [SolidColorBuffer; 8],
|
||||
locations: [Point<i32, Logical>; 8],
|
||||
sizes: [Size<i32, Logical>; 8],
|
||||
borders: RefCell<Option<[BorderRenderElement; 8]>>,
|
||||
borders: RefCell<[BorderRenderElement; 8]>,
|
||||
full_size: Size<i32, Logical>,
|
||||
is_active: bool,
|
||||
is_border: bool,
|
||||
@@ -183,38 +183,20 @@ impl FocusRing {
|
||||
let shader = BorderRenderElement::shader(renderer);
|
||||
|
||||
let mut borders = self.borders.borrow_mut();
|
||||
|
||||
// Initialize the border render elements.
|
||||
if let Some(shader) = shader {
|
||||
if let Some(borders) = &mut *borders {
|
||||
for elem in borders {
|
||||
elem.update_shader(shader);
|
||||
}
|
||||
} else {
|
||||
*borders = Some([(); 8].map(|()| BorderRenderElement::empty(shader.clone())));
|
||||
}
|
||||
for elem in &mut *borders {
|
||||
elem.update_shader(shader);
|
||||
}
|
||||
|
||||
let mut borders = if let Some(borders) = &mut *borders {
|
||||
let a = Some(borders.iter_mut().map(Some));
|
||||
let b = None;
|
||||
a.into_iter().flatten().chain(b.into_iter().flatten())
|
||||
} else {
|
||||
let a = None;
|
||||
let b = Some([None, None, None, None, None, None, None, None].into_iter());
|
||||
a.into_iter().flatten().chain(b.into_iter().flatten())
|
||||
};
|
||||
|
||||
let mut push = |buffer,
|
||||
border: Option<&mut BorderRenderElement>,
|
||||
border: &mut BorderRenderElement,
|
||||
location: Point<i32, Logical>,
|
||||
size: Size<i32, Logical>| {
|
||||
let elem = if let Some(gradient) = gradient {
|
||||
let gradient_area = match gradient.relative_to {
|
||||
GradientRelativeTo::Window => full_rect,
|
||||
GradientRelativeTo::WorkspaceView => view_rect,
|
||||
};
|
||||
border.map(|border| {
|
||||
let elem = if border.has_shader() {
|
||||
if let Some(gradient) = gradient {
|
||||
let gradient_area = match gradient.relative_to {
|
||||
GradientRelativeTo::Window => full_rect,
|
||||
GradientRelativeTo::WorkspaceView => view_rect,
|
||||
};
|
||||
border.update(
|
||||
scale,
|
||||
Rectangle::from_loc_and_size(location, size),
|
||||
@@ -226,10 +208,8 @@ impl FocusRing {
|
||||
border_width,
|
||||
self.radius,
|
||||
);
|
||||
border.clone().into()
|
||||
})
|
||||
} else if self.radius != CornerRadius::default() {
|
||||
border.map(|border| {
|
||||
Some(border.clone().into())
|
||||
} else if self.radius != CornerRadius::default() {
|
||||
border.update(
|
||||
scale,
|
||||
Rectangle::from_loc_and_size(location, size),
|
||||
@@ -241,8 +221,10 @@ impl FocusRing {
|
||||
border_width,
|
||||
self.radius,
|
||||
);
|
||||
border.clone().into()
|
||||
})
|
||||
Some(border.clone().into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -262,7 +244,7 @@ impl FocusRing {
|
||||
|
||||
if self.is_border {
|
||||
for ((buf, border), (loc, size)) in zip(
|
||||
zip(&self.buffers, &mut borders),
|
||||
zip(&self.buffers, &mut *borders),
|
||||
zip(self.locations, self.sizes),
|
||||
) {
|
||||
push(buf, border, location + loc, size);
|
||||
@@ -270,7 +252,7 @@ impl FocusRing {
|
||||
} else {
|
||||
push(
|
||||
&self.buffers[0],
|
||||
borders.next().unwrap(),
|
||||
&mut borders[0],
|
||||
location + self.locations[0],
|
||||
self.sizes[0],
|
||||
);
|
||||
|
||||
+1
-1
@@ -718,7 +718,7 @@ impl<W: LayoutElement> Tile<W> {
|
||||
if radius != CornerRadius::default() {
|
||||
if let Some(shader) = border_shader.clone() {
|
||||
return BorderRenderElement::new(
|
||||
shader,
|
||||
&shader,
|
||||
scale,
|
||||
elem.geometry(Scale::from(1.)).to_logical(1),
|
||||
Rectangle::from_loc_and_size(Point::from((0, 0)), geo.size),
|
||||
|
||||
@@ -21,7 +21,6 @@ use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BorderRenderElement {
|
||||
inner: ShaderRenderElement,
|
||||
shader: ShaderProgram,
|
||||
params: Parameters,
|
||||
}
|
||||
|
||||
@@ -41,7 +40,7 @@ struct Parameters {
|
||||
impl BorderRenderElement {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
shader: ShaderProgram,
|
||||
shader: &ShaderProgram,
|
||||
scale: Scale<f64>,
|
||||
area: Rectangle<i32, Logical>,
|
||||
gradient_area: Rectangle<i32, Logical>,
|
||||
@@ -52,19 +51,10 @@ impl BorderRenderElement {
|
||||
border_width: f32,
|
||||
corner_radius: CornerRadius,
|
||||
) -> Self {
|
||||
let inner = ShaderRenderElement::new(
|
||||
shader.clone(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
1.,
|
||||
vec![],
|
||||
HashMap::new(),
|
||||
Kind::Unspecified,
|
||||
);
|
||||
let mut inner = ShaderRenderElement::empty(Kind::Unspecified);
|
||||
inner.update_shader(Some(shader));
|
||||
let mut rv = Self {
|
||||
inner,
|
||||
shader,
|
||||
params: Parameters {
|
||||
scale,
|
||||
area,
|
||||
@@ -81,20 +71,10 @@ impl BorderRenderElement {
|
||||
rv
|
||||
}
|
||||
|
||||
pub fn empty(shader: ShaderProgram) -> Self {
|
||||
let inner = ShaderRenderElement::new(
|
||||
shader.clone(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
1.,
|
||||
vec![],
|
||||
HashMap::new(),
|
||||
Kind::Unspecified,
|
||||
);
|
||||
pub fn empty() -> Self {
|
||||
let inner = ShaderRenderElement::empty(Kind::Unspecified);
|
||||
Self {
|
||||
inner,
|
||||
shader,
|
||||
params: Parameters {
|
||||
scale: Scale::from(1.),
|
||||
area: Default::default(),
|
||||
@@ -109,23 +89,8 @@ impl BorderRenderElement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_shader(&mut self, shader: &ShaderProgram) {
|
||||
if &self.shader == shader {
|
||||
return;
|
||||
}
|
||||
|
||||
self.inner = ShaderRenderElement::new(
|
||||
shader.clone(),
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
None,
|
||||
1.,
|
||||
vec![],
|
||||
HashMap::new(),
|
||||
Kind::Unspecified,
|
||||
);
|
||||
self.update_inner();
|
||||
self.shader = shader.clone();
|
||||
pub fn update_shader(&mut self, shader: Option<&ShaderProgram>) {
|
||||
self.inner.update_shader(shader);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -222,11 +187,21 @@ 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()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BorderRenderElement {
|
||||
fn default() -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for BorderRenderElement {
|
||||
fn id(&self) -> &Id {
|
||||
self.inner.id()
|
||||
|
||||
@@ -92,7 +92,7 @@ impl ResizeRenderElement {
|
||||
|
||||
// Create the shader.
|
||||
Self(ShaderRenderElement::new(
|
||||
shader,
|
||||
Some(shader),
|
||||
area,
|
||||
size,
|
||||
None,
|
||||
|
||||
@@ -19,8 +19,7 @@ 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: ShaderProgram,
|
||||
textures: HashMap<String, GlesTexture>,
|
||||
shader: Option<ShaderProgram>,
|
||||
id: Id,
|
||||
commit_counter: CommitCounter,
|
||||
area: Rectangle<i32, Logical>,
|
||||
@@ -28,6 +27,7 @@ pub struct ShaderRenderElement {
|
||||
opaque_regions: Vec<Rectangle<i32, Logical>>,
|
||||
alpha: f32,
|
||||
additional_uniforms: Vec<Uniform<'static>>,
|
||||
textures: HashMap<String, GlesTexture>,
|
||||
kind: Kind,
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ impl ShaderProgram {
|
||||
impl ShaderRenderElement {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
shader: ShaderProgram,
|
||||
shader: Option<ShaderProgram>,
|
||||
area: Rectangle<i32, Logical>,
|
||||
size: Size<f64, Buffer>,
|
||||
opaque_regions: Option<Vec<Rectangle<i32, Logical>>>,
|
||||
@@ -208,7 +208,6 @@ impl ShaderRenderElement {
|
||||
) -> Self {
|
||||
Self {
|
||||
shader,
|
||||
textures,
|
||||
id: Id::new(),
|
||||
commit_counter: CommitCounter::default(),
|
||||
area,
|
||||
@@ -216,10 +215,35 @@ impl ShaderRenderElement {
|
||||
opaque_regions: opaque_regions.unwrap_or_default(),
|
||||
alpha,
|
||||
additional_uniforms: uniforms.into_iter().map(|u| u.into_owned()).collect(),
|
||||
textures,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn empty(kind: Kind) -> Self {
|
||||
Self {
|
||||
shader: None,
|
||||
id: Id::new(),
|
||||
commit_counter: CommitCounter::default(),
|
||||
area: Rectangle::default(),
|
||||
size: Size::default(),
|
||||
opaque_regions: vec![],
|
||||
alpha: 1.,
|
||||
additional_uniforms: vec![],
|
||||
textures: HashMap::new(),
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_shader(&mut self, shader: Option<&ShaderProgram>) {
|
||||
if self.shader.as_ref() == shader {
|
||||
return;
|
||||
}
|
||||
|
||||
self.shader = shader.cloned();
|
||||
self.commit_counter.increment();
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
area: Rectangle<i32, Logical>,
|
||||
@@ -236,6 +260,10 @@ impl ShaderRenderElement {
|
||||
|
||||
self.commit_counter.increment();
|
||||
}
|
||||
|
||||
pub fn has_shader(&self) -> bool {
|
||||
self.shader.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for ShaderRenderElement {
|
||||
@@ -281,6 +309,10 @@ impl RenderElement<GlesRenderer> for ShaderRenderElement {
|
||||
) -> Result<(), GlesError> {
|
||||
let frame = frame.as_gles_frame();
|
||||
|
||||
let Some(shader) = &self.shader else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(resources) = Resources::get(frame) else {
|
||||
return Ok(());
|
||||
};
|
||||
@@ -358,9 +390,9 @@ impl RenderElement<GlesRenderer> for ShaderRenderElement {
|
||||
let has_tint = frame.debug_flags().contains(DebugFlags::TINT);
|
||||
|
||||
let program = if has_debug {
|
||||
&self.shader.0.debug
|
||||
&shader.0.debug
|
||||
} else {
|
||||
&self.shader.0.normal
|
||||
&shader.0.normal
|
||||
};
|
||||
|
||||
// render
|
||||
@@ -406,7 +438,7 @@ impl RenderElement<GlesRenderer> for ShaderRenderElement {
|
||||
|
||||
let tint = if has_tint { 1.0f32 } else { 0.0f32 };
|
||||
if has_debug {
|
||||
gl.Uniform1f(self.shader.0.uniform_tint, tint);
|
||||
gl.Uniform1f(shader.0.uniform_tint, tint);
|
||||
}
|
||||
|
||||
for uniform in &self.additional_uniforms {
|
||||
|
||||
Reference in New Issue
Block a user