mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
shader_element: Store program type instead of shader
This commit is contained in:
@@ -54,30 +54,26 @@ impl TestCase for GradientAngle {
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
renderer: &mut GlesRenderer,
|
||||
_renderer: &mut GlesRenderer,
|
||||
size: Size<i32, Physical>,
|
||||
) -> Vec<Box<dyn RenderElement<GlesRenderer>>> {
|
||||
let (a, b) = (size.w / 4, size.h / 4);
|
||||
let size = (size.w - a * 2, size.h - b * 2);
|
||||
let area = Rectangle::from_loc_and_size((a, b), size);
|
||||
|
||||
BorderRenderElement::shader(renderer)
|
||||
.map(|shader| {
|
||||
BorderRenderElement::new(
|
||||
shader,
|
||||
Scale::from(1.),
|
||||
area,
|
||||
area,
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
self.angle - FRAC_PI_2,
|
||||
area,
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
)
|
||||
})
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
[BorderRenderElement::new(
|
||||
Scale::from(1.),
|
||||
area,
|
||||
area,
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
self.angle - FRAC_PI_2,
|
||||
area,
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,23 +98,19 @@ impl TestCase for GradientArea {
|
||||
);
|
||||
|
||||
rv.extend(
|
||||
BorderRenderElement::shader(renderer)
|
||||
.map(|shader| {
|
||||
BorderRenderElement::new(
|
||||
shader,
|
||||
Scale::from(1.),
|
||||
area,
|
||||
g_area,
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
FRAC_PI_4,
|
||||
area,
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
)
|
||||
})
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _),
|
||||
[BorderRenderElement::new(
|
||||
Scale::from(1.),
|
||||
area,
|
||||
g_area,
|
||||
[1., 0., 0., 1.],
|
||||
[0., 1., 0., 1.],
|
||||
FRAC_PI_4,
|
||||
area,
|
||||
0.,
|
||||
CornerRadius::default(),
|
||||
)]
|
||||
.into_iter()
|
||||
.map(|elem| Box::new(elem) as _),
|
||||
);
|
||||
|
||||
rv
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -142,6 +142,8 @@ impl Winit {
|
||||
}
|
||||
drop(config);
|
||||
|
||||
niri.layout.update_shaders();
|
||||
|
||||
niri.add_output(self.output.clone(), None, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
+20
-19
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user