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/. */
4 
5 extern crate mozangle;
6 extern crate webrender;
7 
8 use mozangle::shaders::{BuiltInResources, Output, ShaderSpec, ShaderValidator};
9 
10 // from glslang
11 const FRAGMENT_SHADER: u32 = 0x8B30;
12 const VERTEX_SHADER: u32 = 0x8B31;
13 
14 struct Shader {
15     name: &'static str,
16     features: &'static [&'static str],
17 }
18 
19 const SHADER_PREFIX: &str = "#define WR_MAX_VERTEX_TEXTURE_WIDTH 1024\n";
20 
21 const CLIP_FEATURES: &[&str] = &["TRANSFORM"];
22 const CACHE_FEATURES: &[&str] = &[""];
23 const PRIM_FEATURES: &[&str] = &["", "TRANSFORM"];
24 
25 const SHADERS: &[Shader] = &[
26     // Clip mask shaders
27     Shader {
28         name: "cs_clip_rectangle",
29         features: CLIP_FEATURES,
30     },
31     Shader {
32         name: "cs_clip_image",
33         features: CLIP_FEATURES,
34     },
35     Shader {
36         name: "cs_clip_box_shadow",
37         features: CLIP_FEATURES,
38     },
39     Shader {
40         name: "cs_clip_border",
41         features: CLIP_FEATURES,
42     },
43     // Cache shaders
44     Shader {
45         name: "cs_blur",
46         features: CACHE_FEATURES,
47     },
48     Shader {
49         name: "cs_text_run",
50         features: CACHE_FEATURES,
51     },
52     // Prim shaders
53     Shader {
54         name: "ps_border_corner",
55         features: PRIM_FEATURES,
56     },
57     Shader {
58         name: "ps_border_edge",
59         features: PRIM_FEATURES,
60     },
61     Shader {
62         name: "ps_hardware_composite",
63         features: PRIM_FEATURES,
64     },
65     Shader {
66         name: "ps_split_composite",
67         features: PRIM_FEATURES,
68     },
69     Shader {
70         name: "ps_image",
71         features: PRIM_FEATURES,
72     },
73     Shader {
74         name: "ps_text_run",
75         features: PRIM_FEATURES,
76     },
77     // Brush shaders
78     Shader {
79         name: "brush_yuv_image",
80         features: &["", "YUV_NV12", "YUV_PLANAR", "YUV_INTERLEAVED", "YUV_NV12,TEXTURE_RECT"],
81     },
82     Shader {
83         name: "brush_mask",
84         features: &[],
85     },
86     Shader {
87         name: "brush_solid",
88         features: &[],
89     },
90     Shader {
91         name: "brush_blend",
92         features: &[],
93     },
94     Shader {
95         name: "brush_composite",
96         features: &[],
97     },
98     Shader {
99         name: "brush_line",
100         features: &[],
101     },
102     Shader {
103         name: "brush_radial_gradient",
104         features: &[ "DITHERING" ],
105     },
106     Shader {
107         name: "brush_linear_gradient",
108         features: &[],
109     },
110 ];
111 
112 const VERSION_STRING: &str = "#version 300 es\n";
113 
114 #[test]
validate_shaders()115 fn validate_shaders() {
116     mozangle::shaders::initialize().unwrap();
117 
118     let resources = BuiltInResources::default();
119     let vs_validator =
120         ShaderValidator::new(VERTEX_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();
121 
122     let fs_validator =
123         ShaderValidator::new(FRAGMENT_SHADER, ShaderSpec::Gles3, Output::Essl, &resources).unwrap();
124 
125     for shader in SHADERS {
126         for config in shader.features {
127             let mut features = String::new();
128             features.push_str(SHADER_PREFIX);
129 
130             for feature in config.split(",") {
131                 features.push_str(&format!("#define WR_FEATURE_{}", feature));
132             }
133 
134             let (vs, fs) =
135                 webrender::build_shader_strings(VERSION_STRING, &features, shader.name, &None);
136 
137             validate(&vs_validator, shader.name, vs);
138             validate(&fs_validator, shader.name, fs);
139         }
140     }
141 }
142 
validate(validator: &ShaderValidator, name: &str, source: String)143 fn validate(validator: &ShaderValidator, name: &str, source: String) {
144     // Check for each `switch` to have a `default`, see
145     // https://github.com/servo/webrender/wiki/Driver-issues#lack-of-default-case-in-a-switch
146     assert_eq!(source.matches("switch").count(), source.matches("default:").count(),
147         "Shader '{}' doesn't have all `switch` covered with `default` cases", name);
148     // Run Angle validator
149     match validator.compile_and_translate(&[&source]) {
150         Ok(_) => {
151             println!("Shader translated succesfully: {}", name);
152         }
153         Err(_) => {
154             panic!(
155                 "Shader compilation failed: {}\n{}",
156                 name,
157                 validator.info_log()
158             );
159         }
160     }
161 }
162