1 | // Copyright 2015-2016 Brendan Zabarauskas and the gl-rs developers |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | extern crate khronos_api; |
16 | |
17 | use std::borrow::Cow; |
18 | use std::collections::{BTreeMap, BTreeSet}; |
19 | use std::fmt; |
20 | use std::hash::{Hash, Hasher}; |
21 | use std::io; |
22 | use std::ops::{Add, AddAssign}; |
23 | |
24 | use Generator; |
25 | |
26 | mod parse; |
27 | |
28 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
29 | pub enum Api { |
30 | Gl, |
31 | Glx, |
32 | Wgl, |
33 | Egl, |
34 | GlCore, |
35 | Gles1, |
36 | Gles2, |
37 | Glsc2, |
38 | } |
39 | |
40 | impl fmt::Display for Api { |
41 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
42 | match *self { |
43 | Api::Gl => write!(fmt, "gl" ), |
44 | Api::Glx => write!(fmt, "glx" ), |
45 | Api::Wgl => write!(fmt, "wgl" ), |
46 | Api::Egl => write!(fmt, "egl" ), |
47 | Api::GlCore => write!(fmt, "glcore" ), |
48 | Api::Gles1 => write!(fmt, "gles1" ), |
49 | Api::Gles2 => write!(fmt, "gles2" ), |
50 | Api::Glsc2 => write!(fmt, "glsc2" ), |
51 | } |
52 | } |
53 | } |
54 | |
55 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
56 | pub enum Fallbacks { |
57 | All, |
58 | None, |
59 | } |
60 | |
61 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
62 | pub enum Profile { |
63 | Core, |
64 | Compatibility, |
65 | } |
66 | |
67 | #[derive (Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
68 | pub struct Enum { |
69 | pub ident: String, |
70 | pub value: String, |
71 | pub cast: bool, |
72 | pub alias: Option<String>, |
73 | pub ty: Cow<'static, str>, |
74 | } |
75 | |
76 | impl Hash for Enum { |
77 | fn hash<H: Hasher>(&self, state: &mut H) { |
78 | self.ident.hash(state); |
79 | } |
80 | } |
81 | |
82 | #[derive (Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
83 | pub struct Binding { |
84 | pub ident: String, |
85 | pub ty: Cow<'static, str>, |
86 | pub group: Option<String>, |
87 | } |
88 | |
89 | #[derive (Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
90 | pub struct Group { |
91 | pub ident: String, |
92 | pub enums_type: Option<String>, |
93 | pub enums: Vec<String>, |
94 | } |
95 | |
96 | #[derive (Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
97 | pub struct Cmd { |
98 | pub proto: Binding, |
99 | pub params: Vec<Binding>, |
100 | pub alias: Option<String>, |
101 | pub vecequiv: Option<String>, |
102 | pub glx: Option<GlxOpcode>, |
103 | } |
104 | |
105 | impl Hash for Cmd { |
106 | fn hash<H: Hasher>(&self, state: &mut H) { |
107 | self.proto.ident.hash(state); |
108 | } |
109 | } |
110 | |
111 | #[derive (Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] |
112 | pub struct GlxOpcode { |
113 | pub opcode: String, |
114 | pub name: Option<String>, |
115 | } |
116 | |
117 | #[derive (Clone, Debug, PartialEq, Eq)] |
118 | pub struct Registry { |
119 | pub api: Api, |
120 | pub enums: BTreeSet<Enum>, |
121 | pub cmds: BTreeSet<Cmd>, |
122 | pub aliases: BTreeMap<String, Vec<String>>, |
123 | pub groups: BTreeMap<String, Group>, |
124 | } |
125 | |
126 | impl Registry { |
127 | pub fn new<'a, Exts>( |
128 | api: Api, |
129 | version: (u8, u8), |
130 | profile: Profile, |
131 | fallbacks: Fallbacks, |
132 | extensions: Exts, |
133 | ) -> Registry |
134 | where |
135 | Exts: AsRef<[&'a str]>, |
136 | { |
137 | let (major, minor) = version; |
138 | let extensions = extensions.as_ref().iter().map(<&str>::to_string).collect(); |
139 | |
140 | let filter = parse::Filter { |
141 | api, |
142 | fallbacks, |
143 | extensions, |
144 | version: format!(" {}. {}" , major, minor), |
145 | profile, |
146 | }; |
147 | |
148 | let src = match api { |
149 | Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => khronos_api::GL_XML, |
150 | Api::Glx => khronos_api::GLX_XML, |
151 | Api::Wgl => khronos_api::WGL_XML, |
152 | Api::Egl => khronos_api::EGL_XML, |
153 | }; |
154 | |
155 | let mut registry = parse::from_xml(src, &filter, true); |
156 | if filter.extensions.iter().any(|e| e.starts_with("GL_ANGLE_" )) { |
157 | registry += parse::from_xml(khronos_api::GL_ANGLE_EXT_XML, &filter, false); |
158 | } |
159 | if filter.extensions.iter().any(|e| e.starts_with("EGL_ANGLE_" )) { |
160 | registry += parse::from_xml(khronos_api::EGL_ANGLE_EXT_XML, &filter, false); |
161 | } |
162 | registry |
163 | } |
164 | |
165 | pub fn write_bindings<W, G>(&self, generator: G, output: &mut W) -> io::Result<()> |
166 | where |
167 | G: Generator, |
168 | W: io::Write, |
169 | { |
170 | generator.write(&self, output) |
171 | } |
172 | |
173 | /// Returns a set of all the types used in the supplied registry. This is useful |
174 | /// for working out what conversions are needed for the specific registry. |
175 | pub fn get_tys(&self) -> BTreeSet<&str> { |
176 | let mut tys = BTreeSet::new(); |
177 | for def in &self.cmds { |
178 | tys.insert(def.proto.ty.as_ref()); |
179 | for param in &def.params { |
180 | tys.insert(param.ty.as_ref()); |
181 | } |
182 | } |
183 | tys |
184 | } |
185 | } |
186 | |
187 | impl Add for Registry { |
188 | type Output = Registry; |
189 | |
190 | fn add(mut self, other: Registry) -> Registry { |
191 | self += other; |
192 | self |
193 | } |
194 | } |
195 | |
196 | impl AddAssign for Registry { |
197 | fn add_assign(&mut self, other: Self) { |
198 | self.enums.extend(iter:other.enums); |
199 | self.cmds.extend(iter:other.cmds); |
200 | self.aliases.extend(iter:other.aliases); |
201 | } |
202 | } |
203 | |