1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
use std::cell::RefCell;
use smithay::backend::renderer::gles::{
GlesError, GlesPixelProgram, GlesRenderer, UniformName, UniformType,
};
use super::primary_gpu_pixel_shader_with_textures::PixelWithTexturesProgram;
use super::renderer::NiriRenderer;
pub struct Shaders {
pub gradient_border: Option<GlesPixelProgram>,
pub resize: Option<PixelWithTexturesProgram>,
pub custom_resize: RefCell<Option<PixelWithTexturesProgram>>,
}
impl Shaders {
fn compile(renderer: &mut GlesRenderer) -> Self {
let _span = tracy_client::span!("Shaders::compile");
let gradient_border = renderer
.compile_custom_pixel_shader(
include_str!("gradient_border.frag"),
&[
UniformName::new("color_from", UniformType::_4f),
UniformName::new("color_to", UniformType::_4f),
UniformName::new("grad_offset", UniformType::_2f),
UniformName::new("grad_width", UniformType::_1f),
UniformName::new("grad_vec", UniformType::_2f),
],
)
.map_err(|err| {
warn!("error compiling gradient border shader: {err:?}");
})
.ok();
let resize = compile_resize_program(renderer, include_str!("resize.frag"))
.map_err(|err| {
warn!("error compiling resize shader: {err:?}");
})
.ok();
Self {
gradient_border,
resize,
custom_resize: RefCell::new(None),
}
}
pub fn get(renderer: &mut impl NiriRenderer) -> &Self {
let renderer = renderer.as_gles_renderer();
let data = renderer.egl_context().user_data();
data.get()
.expect("shaders::init() must be called when creating the renderer")
}
pub fn replace_custom_resize_program(
&self,
program: Option<PixelWithTexturesProgram>,
) -> Option<PixelWithTexturesProgram> {
self.custom_resize.replace(program)
}
pub fn resize(&self) -> Option<PixelWithTexturesProgram> {
self.custom_resize
.borrow()
.clone()
.or_else(|| self.resize.clone())
}
}
pub fn init(renderer: &mut GlesRenderer) {
let shaders = Shaders::compile(renderer);
let data = renderer.egl_context().user_data();
if !data.insert_if_missing(|| shaders) {
error!("shaders were already compiled");
}
}
fn compile_resize_program(
renderer: &mut GlesRenderer,
src: &str,
) -> Result<PixelWithTexturesProgram, GlesError> {
let mut program = include_str!("resize-prelude.frag").to_string();
program.push_str(src);
program.push_str(include_str!("resize-epilogue.frag"));
PixelWithTexturesProgram::compile(
renderer,
&program,
&[
UniformName::new("niri_input_to_curr_geo", UniformType::Matrix3x3),
UniformName::new("niri_curr_geo_to_prev_geo", UniformType::Matrix3x3),
UniformName::new("niri_curr_geo_to_next_geo", UniformType::Matrix3x3),
UniformName::new("niri_geo_to_tex_prev", UniformType::Matrix3x3),
UniformName::new("niri_geo_to_tex_next", UniformType::Matrix3x3),
UniformName::new("niri_progress", UniformType::_1f),
UniformName::new("niri_clamped_progress", UniformType::_1f),
],
&["niri_tex_prev", "niri_tex_next"],
)
}
pub fn set_custom_resize_program(renderer: &mut GlesRenderer, src: Option<&str>) {
let program = if let Some(src) = src {
match compile_resize_program(renderer, src) {
Ok(program) => Some(program),
Err(err) => {
warn!("error compiling custom resize shader: {err:?}");
return;
}
}
} else {
None
};
if let Some(prev) = Shaders::get(renderer).replace_custom_resize_program(program) {
if let Err(err) = prev.destroy(renderer) {
warn!("error destroying previous custom resize shader: {err:?}");
}
}
}
|