diff options
Diffstat (limited to 'gfx/wr/swgl/build.rs')
-rw-r--r-- | gfx/wr/swgl/build.rs | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/gfx/wr/swgl/build.rs b/gfx/wr/swgl/build.rs new file mode 100644 index 0000000000..b20dacd593 --- /dev/null +++ b/gfx/wr/swgl/build.rs @@ -0,0 +1,148 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +extern crate cc; +extern crate glsl_to_cxx; +extern crate webrender_build; + +use std::collections::HashSet; +use std::fmt::Write; +use webrender_build::shader::{ShaderFeatureFlags, get_shader_features}; + +// Shader key is in "name feature,feature" format. +// File name needs to be formatted as "name_feature_feature". +fn shader_file(shader_key: &str) -> String { + shader_key.replace(' ', "_").replace(',', "_") +} + +fn write_load_shader(shader_keys: &[String]) { + let mut load_shader = String::new(); + for s in shader_keys { + let _ = write!(load_shader, "#include \"{}.h\"\n", shader_file(s)); + } + load_shader.push_str("ProgramLoader load_shader(const char* name) {\n"); + for s in shader_keys { + let _ = write!(load_shader, " if (!strcmp(name, \"{}\")) {{ return {}_program::loader; }}\n", + s, shader_file(s)); + } + load_shader.push_str(" return nullptr;\n}\n"); + std::fs::write(std::env::var("OUT_DIR").unwrap() + "/load_shader.h", load_shader).unwrap(); +} + +fn process_imports(shader_dir: &str, shader: &str, included: &mut HashSet<String>, output: &mut String) { + if !included.insert(shader.into()) { + return; + } + println!("cargo:rerun-if-changed={}/{}.glsl", shader_dir, shader); + let source = std::fs::read_to_string(format!("{}/{}.glsl", shader_dir, shader)).unwrap(); + for line in source.lines() { + if line.starts_with("#include ") { + let imports = line["#include ".len() ..].split(','); + for import in imports { + process_imports(shader_dir, import, included, output); + } + } else if line.starts_with("#version ") || line.starts_with("#extension ") { + // ignore + } else { + output.push_str(line); + output.push('\n'); + } + } +} + +fn translate_shader(shader_key: &str, shader_dir: &str) { + let mut imported = String::from("#define SWGL 1\n"); + let _ = write!(imported, "#define WR_MAX_VERTEX_TEXTURE_WIDTH {}U\n", + webrender_build::MAX_VERTEX_TEXTURE_WIDTH); + + let (basename, features) = + shader_key.split_at(shader_key.find(' ').unwrap_or(shader_key.len())); + if !features.is_empty() { + for feature in features.trim().split(',') { + let _ = write!(imported, "#define WR_FEATURE_{}\n", feature); + } + } + + process_imports(shader_dir, basename, &mut HashSet::new(), &mut imported); + + let shader = shader_file(shader_key); + + let out_dir = std::env::var("OUT_DIR").unwrap(); + let imp_name = format!("{}/{}.c", out_dir, shader); + std::fs::write(&imp_name, imported).unwrap(); + + let mut build = cc::Build::new(); + if build.get_compiler().is_like_msvc() { + build.flag("/EP"); + } else { + build.flag("-xc").flag("-P"); + } + build.file(&imp_name); + let vs = build.clone() + .define("WR_VERTEX_SHADER", Some("1")) + .expand(); + let fs = build.clone() + .define("WR_FRAGMENT_SHADER", Some("1")) + .expand(); + let vs_name = format!("{}/{}.vert", out_dir, shader); + let fs_name = format!("{}/{}.frag", out_dir, shader); + std::fs::write(&vs_name, vs).unwrap(); + std::fs::write(&fs_name, fs).unwrap(); + + let args = vec![ + "glsl_to_cxx".to_string(), + vs_name, + fs_name, + ]; + let result = glsl_to_cxx::translate(&mut args.into_iter()); + std::fs::write(format!("{}/{}.h", out_dir, shader), result).unwrap(); +} + +fn main() { + let shader_dir = match std::env::var("MOZ_SRC") { + Ok(dir) => dir + "/gfx/wr/webrender/res", + Err(_) => std::env::var("CARGO_MANIFEST_DIR").unwrap() + "/../webrender/res", + }; + + let shader_flags = + ShaderFeatureFlags::GL | + ShaderFeatureFlags::DUAL_SOURCE_BLENDING | + ShaderFeatureFlags::DEBUG; + let mut shaders: Vec<String> = Vec::new(); + for (name, features) in get_shader_features(shader_flags) { + shaders.extend(features.iter().map(|f| { + if f.is_empty() { name.to_owned() } else { format!("{} {}", name, f) } + })); + } + + shaders.sort(); + + for shader in &shaders { + translate_shader(shader, &shader_dir); + } + + write_load_shader(&shaders); + + println!("cargo:rerun-if-changed=src/composite.h"); + println!("cargo:rerun-if-changed=src/gl_defs.h"); + println!("cargo:rerun-if-changed=src/glsl.h"); + println!("cargo:rerun-if-changed=src/program.h"); + println!("cargo:rerun-if-changed=src/swgl_ext.h"); + println!("cargo:rerun-if-changed=src/texture.h"); + println!("cargo:rerun-if-changed=src/vector_type.h"); + println!("cargo:rerun-if-changed=src/gl.cc"); + cc::Build::new() + .cpp(true) + .file("src/gl.cc") + .flag("-std=c++14") + .flag("-UMOZILLA_CONFIG_H") + .flag("-fno-exceptions") + .flag("-fno-rtti") + .flag("-fno-math-errno") + .define("_GLIBCXX_USE_CXX11_ABI", Some("0")) + .include(shader_dir) + .include("src") + .include(std::env::var("OUT_DIR").unwrap()) + .compile("gl_cc"); +} |