shader_element: Make shader optional

The element is long-lived, but the shader itself isn't.
This commit is contained in:
Ivan Molodetskikh
2024-05-03 20:20:36 +04:00
parent 85680a57da
commit 5c32031111
7 changed files with 78 additions and 89 deletions
@@ -64,7 +64,7 @@ impl TestCase for GradientAngle {
BorderRenderElement::shader(renderer)
.map(|shader| {
BorderRenderElement::new(
shader.clone(),
shader,
Scale::from(1.),
area,
area,
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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),
+17 -42
View File
@@ -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()
+1 -1
View File
@@ -92,7 +92,7 @@ impl ResizeRenderElement {
// Create the shader.
Self(ShaderRenderElement::new(
shader,
Some(shader),
area,
size,
None,
+39 -7
View File
@@ -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 {