Bug 1910133: The username and password labels should have the same color as the input...
[gecko.git] / gfx / wr / swgl / build.rs
blobd02797d43797f08744fbfdbe44ae49275a18da19
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 extern crate cc;
6 extern crate glsl_to_cxx;
7 extern crate webrender_build;
9 use std::collections::HashSet;
10 use std::fmt::Write;
11 use webrender_build::shader::{ShaderFeatureFlags, get_shader_features};
13 // Shader key is in "name feature,feature" format.
14 // File name needs to be formatted as "name_feature_feature".
15 fn shader_file(shader_key: &str) -> String {
16     shader_key.replace(' ', "_").replace(',', "_")
19 fn write_load_shader(shader_keys: &[String]) {
20     let mut load_shader = String::new();
21     for s in shader_keys {
22         let _ = write!(load_shader, "#include \"{}.h\"\n", shader_file(s));
23     }
24     load_shader.push_str("ProgramLoader load_shader(const char* name) {\n");
25     for s in shader_keys {
26         let _ = write!(load_shader, "  if (!strcmp(name, \"{}\")) {{ return {}_program::loader; }}\n",
27                        s, shader_file(s));
28     }
29     load_shader.push_str("  return nullptr;\n}\n");
30     std::fs::write(std::env::var("OUT_DIR").unwrap() + "/load_shader.h", load_shader).unwrap();
33 fn process_imports(shader_dir: &str, shader: &str, included: &mut HashSet<String>, output: &mut String) {
34     if !included.insert(shader.into()) {
35         return;
36     }
37     println!("cargo:rerun-if-changed={}/{}.glsl", shader_dir, shader);
38     let source = std::fs::read_to_string(format!("{}/{}.glsl", shader_dir, shader)).unwrap();
39     for line in source.lines() {
40         if line.starts_with("#include ") {
41             let imports = line["#include ".len() ..].split(',');
42             for import in imports {
43                 process_imports(shader_dir, import, included, output);
44             }
45         } else if line.starts_with("#version ") || line.starts_with("#extension ") {
46             // ignore
47         } else {
48             output.push_str(line);
49             output.push('\n');
50         }
51     }
54 fn translate_shader(shader_key: &str, shader_dir: &str) {
55     let mut imported = String::from("#define SWGL 1\n#define __VERSION__ 150\n");
56     let _ = write!(imported, "#define WR_MAX_VERTEX_TEXTURE_WIDTH {}U\n",
57                    webrender_build::MAX_VERTEX_TEXTURE_WIDTH);
59     let (basename, features) =
60         shader_key.split_at(shader_key.find(' ').unwrap_or(shader_key.len()));
61     if !features.is_empty() {
62         for feature in features.trim().split(',') {
63             let _ = write!(imported, "#define WR_FEATURE_{}\n", feature);
64         }
65     }
67     process_imports(shader_dir, basename, &mut HashSet::new(), &mut imported);
69     let shader = shader_file(shader_key);
71     let out_dir = std::env::var("OUT_DIR").unwrap();
72     let imp_name = format!("{}/{}.c", out_dir, shader);
73     std::fs::write(&imp_name, imported).unwrap();
75     let mut build = cc::Build::new();
76     build.no_default_flags(true);
77     if let Ok(tool) = build.try_get_compiler() {
78         if tool.is_like_msvc() {
79             build.flag("/EP");
80             if tool.path().to_str().map_or(false, |p| p.contains("clang")) {
81                 build.flag("/clang:-undef");
82             } else {
83                 build.flag("/u");
84             }
85         } else {
86             build.flag("-xc").flag("-P").flag("-undef");
87         }
88     }
89     // Use SWGLPP target to avoid pulling CFLAGS/CXXFLAGS.
90     build.target("SWGLPP");
91     build.file(&imp_name);
92     let vs = build.clone()
93         .define("WR_VERTEX_SHADER", Some("1"))
94         .expand();
95     let fs = build.clone()
96         .define("WR_FRAGMENT_SHADER", Some("1"))
97         .expand();
98     let vs_name = format!("{}/{}.vert", out_dir, shader);
99     let fs_name = format!("{}/{}.frag", out_dir, shader);
100     std::fs::write(&vs_name, vs).unwrap();
101     std::fs::write(&fs_name, fs).unwrap();
103     let args = vec![
104         "glsl_to_cxx".to_string(),
105         vs_name,
106         fs_name,
107     ];
108     let result = glsl_to_cxx::translate(&mut args.into_iter());
109     std::fs::write(format!("{}/{}.h", out_dir, shader), result).unwrap();
112 fn main() {
113     let shader_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap() + "/../webrender/res";
115     let shader_flags =
116         ShaderFeatureFlags::GL |
117         ShaderFeatureFlags::DUAL_SOURCE_BLENDING |
118         ShaderFeatureFlags::ADVANCED_BLEND_EQUATION |
119         ShaderFeatureFlags::DEBUG;
120     let mut shaders: Vec<String> = Vec::new();
121     for (name, features) in get_shader_features(shader_flags) {
122         shaders.extend(features.iter().map(|f| {
123             if f.is_empty() { name.to_owned() } else { format!("{} {}", name, f) }
124         }));
125     }
127     shaders.sort();
129     // We need to ensure that the C preprocessor does not pull compiler flags from
130     // the host or target environment. Set up a SWGLPP target with empty flags to
131     // work around this.
132     if let Ok(target) = std::env::var("TARGET") {
133         if let Ok(cc) = std::env::var(format!("CC_{}", target))
134                         .or(std::env::var(format!("CC_{}", target.replace("-", "_")))) {
135             std::env::set_var("CC_SWGLPP", cc);
136         }
137     }
138     std::env::set_var("CFLAGS_SWGLPP", "");
140     for shader in &shaders {
141         translate_shader(shader, &shader_dir);
142     }
144     write_load_shader(&shaders);
146     println!("cargo:rerun-if-changed=src/blend.h");
147     println!("cargo:rerun-if-changed=src/composite.h");
148     println!("cargo:rerun-if-changed=src/gl_defs.h");
149     println!("cargo:rerun-if-changed=src/glsl.h");
150     println!("cargo:rerun-if-changed=src/program.h");
151     println!("cargo:rerun-if-changed=src/rasterize.h");
152     println!("cargo:rerun-if-changed=src/swgl_ext.h");
153     println!("cargo:rerun-if-changed=src/texture.h");
154     println!("cargo:rerun-if-changed=src/vector_type.h");
155     println!("cargo:rerun-if-changed=src/gl.cc");
156     let mut build = cc::Build::new();
157     build.cpp(true);
159     if let Ok(tool) = build.try_get_compiler() {
160         if tool.is_like_msvc() {
161             build.flag("/std:c++17")
162                  .flag("/EHs-")
163                  .flag("/GR-")
164                  .flag("/UMOZILLA_CONFIG_H");
165         } else {
166             build.flag("-std=c++17")
167                  .flag("-fno-exceptions")
168                  .flag("-fno-rtti")
169                  .flag("-fno-math-errno")
170                  .flag("-UMOZILLA_CONFIG_H");
171         }
172         // SWGL relies heavily on inlining for performance so override -Oz with -O2
173         if tool.args().contains(&"-Oz".into()) {
174             build.flag("-O2");
175         }
177         // Most GLSL compilers assume something like fast-math so we turn it on.
178         // However, reciprocal division makes it so 1/1 = 0.999994 which can produce a lot of fuzz
179         // in reftests and the use of reciprocal instructions usually involves a refinement step
180         // which bloats our already bloated code. Further, our shader code is sufficiently parallel
181         // that we're more likely to be throughput bound vs latency bound. Having fewer
182         // instructions makes things easier on the processor and in places where it matters we can
183         // probably explicitly use reciprocal instructions and avoid the refinement step.
184         // Also, allow checks for non-finite values which fast-math may disable.
185         if tool.is_like_msvc() {
186             build.flag("/fp:fast")
187                  .flag("-Xclang")
188                  .flag("-mrecip=none")
189                  .flag("/clang:-fno-finite-math-only");
190         } else if tool.is_like_clang() {
191             // gcc only supports -mrecip=none on some targets so to keep
192             // things simple we don't use -ffast-math with gcc at all
193             build.flag("-ffast-math")
194                  .flag("-mrecip=none")
195                  .flag("-fno-finite-math-only");
196         }
197     }
199     build.file("src/gl.cc")
200         .define("_GLIBCXX_USE_CXX11_ABI", Some("0"))
201         .include(shader_dir)
202         .include("src")
203         .include(std::env::var("OUT_DIR").unwrap())
204         .compile("gl_cc");