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
15extern crate khronos_api;
16
17use std::borrow::Cow;
18use std::collections::{BTreeMap, BTreeSet};
19use std::fmt;
20use std::hash::{Hash, Hasher};
21use std::io;
22use std::ops::{Add, AddAssign};
23
24use Generator;
25
26mod parse;
27
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29pub enum Api {
30 Gl,
31 Glx,
32 Wgl,
33 Egl,
34 GlCore,
35 Gles1,
36 Gles2,
37 Glsc2,
38}
39
40impl 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)]
56pub enum Fallbacks {
57 All,
58 None,
59}
60
61#[derive(Copy, Clone, Debug, PartialEq, Eq)]
62pub enum Profile {
63 Core,
64 Compatibility,
65}
66
67#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
68pub 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
76impl 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)]
83pub 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)]
90pub 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)]
97pub 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
105impl 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)]
112pub struct GlxOpcode {
113 pub opcode: String,
114 pub name: Option<String>,
115}
116
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub 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
126impl 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
187impl Add for Registry {
188 type Output = Registry;
189
190 fn add(mut self, other: Registry) -> Registry {
191 self += other;
192 self
193 }
194}
195
196impl 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