webrender_build/
shader_features.rs1use std::collections::HashMap;
6
7bitflags! {
8 #[derive(Default, Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
9 pub struct ShaderFeatureFlags: u32 {
10 const GL = 1 << 0;
11 const GLES = 1 << 1;
12
13 const ADVANCED_BLEND_EQUATION = 1 << 8;
14 const DUAL_SOURCE_BLENDING = 1 << 9;
15 const DITHERING = 1 << 10;
16 const TEXTURE_EXTERNAL = 1 << 11;
17 const TEXTURE_EXTERNAL_ESSL1 = 1 << 12;
18 const TEXTURE_EXTERNAL_BT709 = 1 << 13;
19 const DEBUG = 1 << 14;
20 }
21}
22
23pub type ShaderFeatures = HashMap<&'static str, Vec<String>>;
24
25#[derive(Clone)]
27struct FeatureList<'a> {
28 list: Vec<&'a str>,
29}
30
31impl<'a> FeatureList<'a> {
32 fn new() -> Self {
33 FeatureList {
34 list: Vec::new(),
35 }
36 }
37
38 fn add(&mut self, feature: &'a str) {
39 assert!(!feature.contains(','));
40 self.list.push(feature);
41 }
42
43 fn with(&self, feature: &'a str) -> Self {
44 let mut other = self.clone();
45 other.add(feature);
46 other
47 }
48
49 fn concat(&self, other: &Self) -> Self {
50 let mut list = self.list.clone();
51 list.extend_from_slice(&other.list);
52 FeatureList {
53 list
54 }
55 }
56
57 fn finish(&mut self) -> String {
58 self.list.sort_unstable();
59 self.list.join(",")
60 }
61}
62
63pub fn get_shader_features(flags: ShaderFeatureFlags) -> ShaderFeatures {
65 let mut shaders = ShaderFeatures::new();
66
67 shaders.insert("cs_clip_rectangle", vec![String::new(), "FAST_PATH".to_string()]);
69
70 shaders.insert("cs_blur", vec!["ALPHA_TARGET".to_string(), "COLOR_TARGET".to_string()]);
72
73 shaders.insert("ps_quad_mask", vec![String::new(), "FAST_PATH".to_string()]);
74
75 for name in &[
76 "cs_line_decoration",
77 "cs_border_segment",
78 "cs_border_solid",
79 "cs_svg_filter_node",
80 ] {
81 shaders.insert(name, vec![String::new()]);
82 }
83
84 let mut base_prim_features = FeatureList::new();
85
86 let mut brush_alpha_features = base_prim_features.with("ALPHA_PASS");
88 for name in &["brush_solid", "brush_blend", "brush_mix_blend"] {
89 let features: Vec<String> = vec![
90 base_prim_features.finish(),
91 brush_alpha_features.finish(),
92 "DEBUG_OVERDRAW".to_string(),
93 ];
94 shaders.insert(name, features);
95 }
96
97
98 {
99 let features: Vec<String> = vec![
100 base_prim_features.finish(),
101 brush_alpha_features.finish(),
102 base_prim_features.with("ANTIALIASING").finish(),
103 brush_alpha_features.with("ANTIALIASING").finish(),
104 "ANTIALIASING,DEBUG_OVERDRAW".to_string(),
105 "DEBUG_OVERDRAW".to_string(),
106 ];
107 shaders.insert("brush_opacity", features);
108 }
109
110 let mut texture_types = vec!["TEXTURE_2D"];
112 if flags.contains(ShaderFeatureFlags::GL) {
113 texture_types.push("TEXTURE_RECT");
114 }
115 if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL) {
116 texture_types.push("TEXTURE_EXTERNAL");
117 }
118 if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709) {
119 texture_types.push("TEXTURE_EXTERNAL_BT709");
120 }
121 let mut image_features: Vec<String> = Vec::new();
122 for texture_type in &texture_types {
123 let mut fast = FeatureList::new();
124 if !texture_type.is_empty() {
125 fast.add(texture_type);
126 }
127 image_features.push(fast.concat(&base_prim_features).finish());
128 image_features.push(fast.concat(&brush_alpha_features).finish());
129 image_features.push(fast.with("DEBUG_OVERDRAW").finish());
130 let mut slow = fast.clone();
131 slow.add("REPETITION");
132 slow.add("ANTIALIASING");
133 image_features.push(slow.concat(&base_prim_features).finish());
134 image_features.push(slow.concat(&brush_alpha_features).finish());
135 image_features.push(slow.with("DEBUG_OVERDRAW").finish());
136 if flags.contains(ShaderFeatureFlags::ADVANCED_BLEND_EQUATION) {
137 let advanced_blend_features = brush_alpha_features.with("ADVANCED_BLEND");
138 image_features.push(fast.concat(&advanced_blend_features).finish());
139 image_features.push(slow.concat(&advanced_blend_features).finish());
140 }
141 if flags.contains(ShaderFeatureFlags::DUAL_SOURCE_BLENDING) {
142 let dual_source_features = brush_alpha_features.with("DUAL_SOURCE_BLENDING");
143 image_features.push(fast.concat(&dual_source_features).finish());
144 image_features.push(slow.concat(&dual_source_features).finish());
145 }
146 }
147 shaders.insert("brush_image", image_features);
148
149 let mut composite_texture_types = texture_types.clone();
150 if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1) {
151 composite_texture_types.push("TEXTURE_EXTERNAL_ESSL1");
152 }
153 let mut composite_features: Vec<String> = Vec::new();
154 for texture_type in &composite_texture_types {
155 let base = texture_type.to_string();
156 composite_features.push(base);
157 }
158 shaders.insert("cs_scale", composite_features.clone());
159
160 let mut yuv_features: Vec<String> = Vec::new();
162 for texture_type in &texture_types {
163 let mut list = FeatureList::new();
164 if !texture_type.is_empty() {
165 list.add(texture_type);
166 }
167 list.add("YUV");
168 composite_features.push(list.finish());
169 yuv_features.push(list.concat(&base_prim_features).finish());
170 yuv_features.push(list.concat(&brush_alpha_features).finish());
171 yuv_features.push(list.with("DEBUG_OVERDRAW").finish());
172 }
173 shaders.insert("brush_yuv_image", yuv_features);
174
175 for texture_type in &composite_texture_types {
177 let mut list = FeatureList::new();
178 if !texture_type.is_empty() {
179 list.add(texture_type);
180 }
181 list.add("FAST_PATH");
182 composite_features.push(list.finish());
183
184 if *texture_type == "TEXTURE_EXTERNAL_ESSL1" {
186 continue;
187 }
188
189 list.add("YUV");
190 composite_features.push(list.finish());
191 }
192 shaders.insert("composite", composite_features);
193
194 let mut text_types = vec![""];
196 if flags.contains(ShaderFeatureFlags::DUAL_SOURCE_BLENDING) {
197 text_types.push("DUAL_SOURCE_BLENDING");
198 }
199 let mut text_features: Vec<String> = Vec::new();
200 for text_type in &text_types {
201 let mut list = base_prim_features.with("TEXTURE_2D");
202 if !text_type.is_empty() {
203 list.add(text_type);
204 }
205 let mut alpha_list = list.with("ALPHA_PASS");
206 text_features.push(alpha_list.finish());
207 text_features.push(alpha_list.with("GLYPH_TRANSFORM").finish());
208 text_features.push(list.with("DEBUG_OVERDRAW").finish());
209 }
210 shaders.insert("ps_text_run", text_features);
211
212 shaders.insert("ps_split_composite", vec![base_prim_features.finish()]);
213
214 let mut ps_quad_textured_features: Vec<String> = vec!["TEXTURE_2D".to_string()];
218 if flags.contains(ShaderFeatureFlags::GL) {
219 ps_quad_textured_features.push("TEXTURE_RECT".to_string());
220 }
221 if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL) {
222 ps_quad_textured_features.push("TEXTURE_EXTERNAL".to_string());
223 }
224 if flags.contains(ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709) {
225 ps_quad_textured_features.push("TEXTURE_EXTERNAL_BT709".to_string());
226 }
227 shaders.insert("ps_quad_textured", ps_quad_textured_features);
228
229 shaders.insert("ps_quad_repeat", vec![base_prim_features.finish()]);
230
231 shaders.insert("ps_quad_box_shadow", vec![base_prim_features.finish()]);
232
233 let mut maybe_dithering = FeatureList::new();
234 if flags.contains(ShaderFeatureFlags::DITHERING) {
235 maybe_dithering.add("DITHERING");
236 }
237
238 shaders.insert("ps_quad_gradient", vec![base_prim_features.concat(&maybe_dithering).finish()]);
239
240 shaders.insert("ps_clear", vec![base_prim_features.finish()]);
241
242 shaders.insert("ps_copy", vec![base_prim_features.finish()]);
243
244 if flags.contains(ShaderFeatureFlags::DEBUG) {
245 for name in &["debug_color", "debug_font"] {
246 shaders.insert(name, vec![String::new()]);
247 }
248 }
249
250 shaders
251}