summaryrefslogtreecommitdiffstats
path: root/third_party/rust/gl_generator
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/gl_generator')
-rw-r--r--third_party/rust/gl_generator/.cargo-checksum.json1
-rw-r--r--third_party/rust/gl_generator/Cargo.toml39
-rw-r--r--third_party/rust/gl_generator/README.md165
-rw-r--r--third_party/rust/gl_generator/generators/debug_struct_gen.rs289
-rw-r--r--third_party/rust/gl_generator/generators/global_gen.rs309
-rw-r--r--third_party/rust/gl_generator/generators/mod.rs119
-rw-r--r--third_party/rust/gl_generator/generators/static_gen.rs115
-rw-r--r--third_party/rust/gl_generator/generators/static_struct_gen.rs165
-rw-r--r--third_party/rust/gl_generator/generators/struct_gen.rs256
-rw-r--r--third_party/rust/gl_generator/generators/templates/types/egl.rs70
-rw-r--r--third_party/rust/gl_generator/generators/templates/types/gl.rs108
-rw-r--r--third_party/rust/gl_generator/generators/templates/types/glx.rs128
-rw-r--r--third_party/rust/gl_generator/generators/templates/types/wgl.rs139
-rw-r--r--third_party/rust/gl_generator/lib.rs81
-rw-r--r--third_party/rust/gl_generator/registry/mod.rs202
-rw-r--r--third_party/rust/gl_generator/registry/parse.rs1393
16 files changed, 3579 insertions, 0 deletions
diff --git a/third_party/rust/gl_generator/.cargo-checksum.json b/third_party/rust/gl_generator/.cargo-checksum.json
new file mode 100644
index 0000000000..863d2f5ad9
--- /dev/null
+++ b/third_party/rust/gl_generator/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"f586015aa2816b3c34d89f5e6a6539172efcd7f3ed055a0fab433ea83e2a0f0f","README.md":"52d8fee4681c879f2c964fd30e3faf0c907e8bf676eab7b44beab5c5bbd5c284","generators/debug_struct_gen.rs":"6fecccf8e57d4be93ea2657328d6e111ca44bc69542a5522cd7360d80ca64630","generators/global_gen.rs":"1696013af16bb92a3fa7cf3802a57ec6f7ba460322ede33aa2af30fc9911bd98","generators/mod.rs":"100a1da965bf11eaa9fad48a06c7856b60f48363a4a707e34ba97938bedae0b8","generators/static_gen.rs":"925a9401e27358a466baadfb660056a24394cf2fa21f5613e2d7f50ab8935e71","generators/static_struct_gen.rs":"eb08e6e59b0e0947c4ab263a0749efbb28430c5741634c413a2be011fcdad88f","generators/struct_gen.rs":"fa1bcda4501a597922be7c7ef4ad13738536a9c97529996671e264acd709c680","generators/templates/types/egl.rs":"d1785a30f1098e101302ba74ba4c22cf95ac44b17edf221dbb9d890f4bd635a2","generators/templates/types/gl.rs":"d72f91355febec875c40899a44c5575bd04993f7cf5c6e289eec872a2a161b20","generators/templates/types/glx.rs":"f444166d117b96afed2d8d13db6cd3369d6c59704f296e76202269f411bbd4a8","generators/templates/types/wgl.rs":"9d626e0959374c694c19a36d4dd34dae2f37acf3cb94e9bd4d242a16b41a970d","lib.rs":"6f47da878479b503b5202bda84ad8935607264ac03c0b68203109fad9cd479db","registry/mod.rs":"84eed5c113b322e5267b2b130987e6bb726b4e7c38ce50292cd6cc57b8e06994","registry/parse.rs":"5cb781082014f143b06ef7d3678f3c4ca59133a5732d4e136fd750b78fb9453f"},"package":"1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d"} \ No newline at end of file
diff --git a/third_party/rust/gl_generator/Cargo.toml b/third_party/rust/gl_generator/Cargo.toml
new file mode 100644
index 0000000000..88c6a85a9b
--- /dev/null
+++ b/third_party/rust/gl_generator/Cargo.toml
@@ -0,0 +1,39 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "gl_generator"
+version = "0.14.0"
+authors = ["Brendan Zabarauskas <bjzaba@yahoo.com.au>", "Corey Richardson", "Arseny Kapoulkine"]
+description = "Code generators for creating bindings to the Khronos OpenGL APIs."
+homepage = "https://github.com/brendanzab/gl-rs/"
+documentation = "https://docs.rs/gl_generator"
+readme = "README.md"
+keywords = ["gl", "egl", "opengl", "khronos"]
+categories = ["api-bindings", "rendering::graphics-api"]
+license = "Apache-2.0"
+repository = "https://github.com/brendanzab/gl-rs/"
+
+[lib]
+name = "gl_generator"
+path = "lib.rs"
+[dependencies.khronos_api]
+version = "3.1.0"
+
+[dependencies.log]
+version = "0.4"
+
+[dependencies.xml-rs]
+version = "0.8"
+
+[features]
+unstable_generator_utils = []
diff --git a/third_party/rust/gl_generator/README.md b/third_party/rust/gl_generator/README.md
new file mode 100644
index 0000000000..36d3e707b6
--- /dev/null
+++ b/third_party/rust/gl_generator/README.md
@@ -0,0 +1,165 @@
+# gl_generator
+
+[![Version](https://img.shields.io/crates/v/gl_generator.svg)](https://crates.io/crates/gl_generator)
+[![License](https://img.shields.io/crates/l/gl_generator.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE)
+[![Downloads](https://img.shields.io/crates/d/gl_generator.svg)](https://crates.io/crates/gl_generator)
+
+Code generators for creating bindings to the Khronos OpenGL APIs.
+
+## Usage
+
+If you need a specific version of OpenGL, or you need a different API
+(OpenGL ES, EGL, WGL, GLX), or if you need certain extensions, you should use
+the `gl_generator` plugin instead.
+
+See [gfx_gl](https://github.com/gfx-rs/gfx_gl) for an example of using a
+custom gfx-rs loader for a project.
+
+Add this to your `Cargo.toml`:
+
+```toml
+[build-dependencies]
+gl_generator = "0.5.0"
+```
+
+Under the `[package]` section, add:
+
+```toml
+build = "build.rs"
+```
+
+Create a `build.rs` to pull your specific version/API:
+
+```rust
+extern crate gl_generator;
+
+use gl_generator::{Registry, Api, Profile, Fallbacks, GlobalGenerator};
+use std::env;
+use std::fs::File;
+use std::path::Path;
+
+fn main() {
+ let dest = env::var("OUT_DIR").unwrap();
+ let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap();
+
+ Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [])
+ .write_bindings(GlobalGenerator, &mut file)
+ .unwrap();
+}
+```
+
+Then use it like this:
+
+```rust
+mod gl {
+ include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
+}
+
+/// Simple loading example
+fn main() {
+ let window = ...;
+
+ // Assuming `window` is GLFW: initialize, and make current
+ gl::load_with(|s| window.get_proc_address(s) as *const _);
+}
+```
+
+The `build.rs` file will generate all the OpenGL functions in a file named,
+`bindings.rs` plus all enumerations, and all types in the `types` submodule.
+
+## Generator types
+
+### Global generator
+
+The global generator is the one used by default by the `gl` crate. See above
+for more details.
+
+### Struct generator
+
+The struct generator is a cleaner alternative to the global generator.
+
+The main difference is that you must call `gl::Gl::load_with` instead of
+`gl::load_with`, and this functions returns a struct of type `Gl`. The OpenGL
+functions are not static functions but member functions in this `Gl` struct.
+This is important when the GL functions are associated with the current
+context, as is true on Windows.
+
+The enumerations and types are still static and available in a similar way as
+in the global generator.
+
+### Static generator
+
+The static generator generates plain old bindings. You don't need to load the
+functions.
+
+This generator should only be used only if the platform you are compiling for
+is guaranteed to support the requested API. Otherwise you will get a
+compilation error.
+For example, you can use it for WGL and OpenGL 1.1 on Windows or GLX and
+OpenGL 1.3 on Linux, because Windows and Linux are guaranteed to provide
+implementations for these APIs.
+
+You will need to manually provide the linkage. For example to use WGL or
+OpenGL 1.1 on Windows, you will need to add
+`#[link="OpenGL32.lib"] extern {}` somewhere in your code.
+
+### Custom Generators
+
+The `gl_generator` can be extended with custom generators. This is a niche
+feature useful only in very rare cases. To create a custom generator, implement
+the `gl_generator::Generator` trait. See the source of the
+`gl_generator::generators` module for examples.
+
+Various utility functions are provided in the `generators` module, but the api
+is unstable, so it has been placed behind a feature flag. In access these
+functions, you will need to add the `"unstable_generator_utils"` feature to
+your `Cargo.toml`:
+
+```toml
+[build-dependencies.gl_generator]
+version = "0.4.2"
+features = ["unstable_generator_utils"]
+```
+
+## Extra features
+
+The global and struct generators will attempt to use fallbacks functions when
+they are available. For example, if `glGenFramebuffers` cannot be loaded it will
+also attempt to load `glGenFramebuffersEXT` as a fallback.
+
+## Changelog
+
+### v0.5.0
+
+- Rename `Ns` to `API`, and expose at the top level
+- Remove the need for clients to depend on the `khronos_api` crate by
+ determining the XML source based on the requested `API`
+- Use a `(u8, u8)` instead of a string for the target version number
+- Use a `Profile` enum instead of a string for the profile
+- Remove unused fields from `Registry`
+- Accept types satisfying `AsRef<[&str]>` for extension lists
+- Separate parsing and generation stages in API
+- Hide `registry::{Feature, Filter, Require, Remove, Extension}` types from the
+ public API
+- Move `registry::{Fallbacks, Api, Profile}` types to top level module
+- Remove `GlxOpcode::type` field
+- Make `ty` fields on `Enum` and `Binding` take `Cow<'static, str>`s to reduce
+ allocations
+
+### v0.4.2
+
+- Update crate metadata
+
+### v0.4.1
+
+- Upgrade `khronos_api` to v1.0.0
+
+### v0.4.0
+
+- Upgrade `xml-rs` to v0.2.2
+- Use `raw::c_void` for `GLvoid`
+- Remove `registry::{Group, EnumNs, CmdNs}`
+- Remove `groups` field from `registry::Registry`
+- Remove `is_safe` field from `registry::Cmd`
+- Remove `comment` field from `registry::{Require, Remove, GlxOpcode}`
+- Downgrade `khronos_api` to be a dev-dependency
diff --git a/third_party/rust/gl_generator/generators/debug_struct_gen.rs b/third_party/rust/gl_generator/generators/debug_struct_gen.rs
new file mode 100644
index 0000000000..98fbcef158
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/debug_struct_gen.rs
@@ -0,0 +1,289 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::Registry;
+use std::io;
+
+#[allow(missing_copy_implementations)]
+pub struct DebugStructGenerator;
+
+impl super::Generator for DebugStructGenerator {
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write,
+ {
+ try!(write_header(dest));
+ try!(write_type_aliases(registry, dest));
+ try!(write_enums(registry, dest));
+ try!(write_fnptr_struct_def(dest));
+ try!(write_panicking_fns(registry, dest));
+ try!(write_struct(registry, dest));
+ try!(write_impl(registry, dest));
+ Ok(())
+ }
+}
+
+/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
+/// bindings.
+fn write_header<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ mod __gl_imports {{
+ pub use std::mem;
+ pub use std::marker::Send;
+ pub use std::os::raw;
+ }}
+ "#
+ )
+}
+
+/// Creates a `types` module which contains all the type aliases.
+///
+/// See also `generators::gen_types`.
+fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ r#"
+ pub mod types {{
+ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
+ "#
+ ));
+
+ try!(super::gen_types(registry.api, dest));
+
+ writeln!(dest, "}}")
+}
+
+/// Creates all the `<enum>` elements at the root of the bindings.
+fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for enm in &registry.enums {
+ try!(super::gen_enum_item(enm, "types::", dest));
+ }
+
+ Ok(())
+}
+
+/// Creates a `FnPtr` structure which contains the store for a single binding.
+fn write_fnptr_struct_def<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "
+ #[allow(dead_code, missing_copy_implementations)]
+ #[derive(Clone)]
+ pub struct FnPtr {{
+ /// The function pointer that will be used when calling the function.
+ f: *const __gl_imports::raw::c_void,
+ /// True if the pointer points to a real function, false if points to a `panic!` fn.
+ is_loaded: bool,
+ }}
+
+ impl FnPtr {{
+ /// Creates a `FnPtr` from a load attempt.
+ fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{
+ if ptr.is_null() {{
+ FnPtr {{
+ f: missing_fn_panic as *const __gl_imports::raw::c_void,
+ is_loaded: false
+ }}
+ }} else {{
+ FnPtr {{ f: ptr, is_loaded: true }}
+ }}
+ }}
+
+ /// Returns `true` if the function has been successfully loaded.
+ ///
+ /// If it returns `false`, calling the corresponding function will fail.
+ #[inline]
+ #[allow(dead_code)]
+ pub fn is_loaded(&self) -> bool {{
+ self.is_loaded
+ }}
+ }}
+ "
+ )
+}
+
+/// Creates a `panicking` module which contains one function per GL command.
+///
+/// These functions are the mocks that are called if the real function could not be loaded.
+fn write_panicking_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "#[inline(never)]
+ fn missing_fn_panic() -> ! {{
+ panic!(\"{api} function was not loaded\")
+ }}",
+ api = registry.api
+ )
+}
+
+/// Creates a structure which stores all the `FnPtr` of the bindings.
+///
+/// The name of the struct corresponds to the namespace.
+fn write_struct<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ "
+ #[allow(non_camel_case_types, non_snake_case, dead_code)]
+ #[derive(Clone)]
+ pub struct {api} {{",
+ api = super::gen_struct_name(registry.api)
+ ));
+
+ for cmd in &registry.cmds {
+ if let Some(v) = registry.aliases.get(&cmd.proto.ident) {
+ try!(writeln!(dest, "/// Fallbacks: {}", v.join(", ")));
+ }
+ try!(writeln!(dest, "pub {name}: FnPtr,", name = cmd.proto.ident));
+ }
+ try!(writeln!(dest, "_priv: ()"));
+
+ writeln!(dest, "}}")
+}
+
+/// Creates the `impl` of the structure created by `write_struct`.
+fn write_impl<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(dest,
+ "impl {api} {{
+ /// Load each OpenGL symbol using a custom load function. This allows for the
+ /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
+ ///
+ /// ~~~ignore
+ /// let gl = Gl::load_with(|s| glfw.get_proc_address(s));
+ /// ~~~
+ #[allow(dead_code, unused_variables)]
+ pub fn load_with<F>(mut loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{
+ #[inline(never)]
+ fn do_metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void,
+ symbol: &'static str,
+ symbols: &[&'static str])
+ -> *const __gl_imports::raw::c_void {{
+ let mut ptr = loadfn(symbol);
+ if ptr.is_null() {{
+ for &sym in symbols {{
+ ptr = loadfn(sym);
+ if !ptr.is_null() {{ break; }}
+ }}
+ }}
+ ptr
+ }}
+ let mut metaloadfn = |symbol: &'static str, symbols: &[&'static str]| {{
+ do_metaloadfn(&mut loadfn, symbol, symbols)
+ }};
+ {api} {{",
+ api = super::gen_struct_name(registry.api)));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "{name}: FnPtr::new(metaloadfn(\"{symbol}\", &[{fallbacks}])),",
+ name = cmd.proto.ident,
+ symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident),
+ fallbacks = match registry.aliases.get(&cmd.proto.ident) {
+ Some(fbs) => fbs
+ .iter()
+ .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name)))
+ .collect::<Vec<_>>()
+ .join(", "),
+ None => format!(""),
+ },
+ ))
+ }
+ try!(writeln!(dest, "_priv: ()"));
+
+ try!(writeln!(
+ dest,
+ "}}
+ }}"
+ ));
+
+ for cmd in &registry.cmds {
+ let idents = super::gen_parameters(cmd, true, false);
+ let typed_params = super::gen_parameters(cmd, false, true);
+ let println = format!(
+ "println!(\"[OpenGL] {}({})\" {});",
+ cmd.proto.ident,
+ (0..idents.len())
+ .map(|_| "{:?}".to_string())
+ .collect::<Vec<_>>()
+ .join(", "),
+ idents
+ .iter()
+ .zip(typed_params.iter())
+ .map(|(name, ty)| if ty.contains("GLDEBUGPROC") {
+ format!(", \"<callback>\"")
+ } else {
+ format!(", {}", name)
+ }).collect::<Vec<_>>()
+ .concat()
+ );
+
+ try!(writeln!(dest,
+ "#[allow(non_snake_case, unused_variables, dead_code)]
+ #[inline] pub unsafe fn {name}(&self, {params}) -> {return_suffix} {{ \
+ {println}
+ let r = __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
+ (self.{name}.f)({idents});
+ {print_err}
+ r
+ }}",
+ name = cmd.proto.ident,
+ params = super::gen_parameters(cmd, true, true).join(", "),
+ typed_params = typed_params.join(", "),
+ return_suffix = cmd.proto.ty,
+ idents = idents.join(", "),
+ println = println,
+ print_err = if cmd.proto.ident != "GetError" &&
+ registry
+ .cmds
+ .iter()
+ .find(|cmd| cmd.proto.ident == "GetError")
+ .is_some() {
+ format!(r#"match __gl_imports::mem::transmute::<_, extern "system" fn() -> u32>
+ (self.GetError.f)() {{ 0 => (), r => println!("[OpenGL] ^ GL error triggered: {{}}", r) }}"#)
+ } else {
+ format!("")
+ }))
+ }
+
+ writeln!(
+ dest,
+ "}}
+
+ unsafe impl __gl_imports::Send for {api} {{}}",
+ api = super::gen_struct_name(registry.api)
+ )
+}
diff --git a/third_party/rust/gl_generator/generators/global_gen.rs b/third_party/rust/gl_generator/generators/global_gen.rs
new file mode 100644
index 0000000000..82c4710979
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/global_gen.rs
@@ -0,0 +1,309 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::Registry;
+use std::io;
+
+#[allow(missing_copy_implementations)]
+pub struct GlobalGenerator;
+
+impl super::Generator for GlobalGenerator {
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write,
+ {
+ try!(write_header(dest));
+ try!(write_metaloadfn(dest));
+ try!(write_type_aliases(registry, dest));
+ try!(write_enums(registry, dest));
+ try!(write_fns(registry, dest));
+ try!(write_fnptr_struct_def(dest));
+ try!(write_ptrs(registry, dest));
+ try!(write_fn_mods(registry, dest));
+ try!(write_panicking_fns(registry, dest));
+ try!(write_load_fn(registry, dest));
+ Ok(())
+ }
+}
+
+/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
+/// bindings.
+fn write_header<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ mod __gl_imports {{
+ pub use std::mem;
+ pub use std::os::raw;
+ }}
+ "#
+ )
+}
+
+/// Creates the metaloadfn function for fallbacks
+fn write_metaloadfn<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ #[inline(never)]
+ fn metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void,
+ symbol: &'static str,
+ fallbacks: &[&'static str]) -> *const __gl_imports::raw::c_void {{
+ let mut ptr = loadfn(symbol);
+ if ptr.is_null() {{
+ for &sym in fallbacks {{
+ ptr = loadfn(sym);
+ if !ptr.is_null() {{ break; }}
+ }}
+ }}
+ ptr
+ }}
+ "#
+ )
+}
+
+/// Creates a `types` module which contains all the type aliases.
+///
+/// See also `generators::gen_types`.
+fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ r#"
+ pub mod types {{
+ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
+ "#
+ ));
+
+ try!(super::gen_types(registry.api, dest));
+
+ writeln!(
+ dest,
+ "
+ }}
+ "
+ )
+}
+
+/// Creates all the `<enum>` elements at the root of the bindings.
+fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for enm in &registry.enums {
+ try!(super::gen_enum_item(enm, "types::", dest));
+ }
+
+ Ok(())
+}
+
+/// Creates the functions corresponding to the GL commands.
+///
+/// The function calls the corresponding function pointer stored in the `storage` module created
+/// by `write_ptrs`.
+fn write_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for cmd in &registry.cmds {
+ if let Some(v) = registry.aliases.get(&cmd.proto.ident) {
+ try!(writeln!(dest, "/// Fallbacks: {}", v.join(", ")));
+ }
+
+ try!(writeln!(dest,
+ "#[allow(non_snake_case, unused_variables, dead_code)] #[inline]
+ pub unsafe fn {name}({params}) -> {return_suffix} {{ \
+ __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
+ (storage::{name}.f)({idents}) \
+ }}",
+ name = cmd.proto.ident,
+ params = super::gen_parameters(cmd, true, true).join(", "),
+ typed_params = super::gen_parameters(cmd, false, true).join(", "),
+ return_suffix = cmd.proto.ty,
+ idents = super::gen_parameters(cmd, true, false).join(", "),
+ ));
+ }
+
+ Ok(())
+}
+
+/// Creates a `FnPtr` structure which contains the store for a single binding.
+fn write_fnptr_struct_def<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(dest,
+ "
+ #[allow(missing_copy_implementations)]
+ pub struct FnPtr {{
+ /// The function pointer that will be used when calling the function.
+ f: *const __gl_imports::raw::c_void,
+ /// True if the pointer points to a real function, false if points to a `panic!` fn.
+ is_loaded: bool,
+ }}
+
+ impl FnPtr {{
+ /// Creates a `FnPtr` from a load attempt.
+ pub fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{
+ if ptr.is_null() {{
+ FnPtr {{ f: missing_fn_panic as *const __gl_imports::raw::c_void, is_loaded: false }}
+ }} else {{
+ FnPtr {{ f: ptr, is_loaded: true }}
+ }}
+ }}
+ }}
+ ")
+}
+
+/// Creates a `storage` module which contains a static `FnPtr` per GL command in the registry.
+fn write_ptrs<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ "mod storage {{
+ #![allow(non_snake_case)]
+ #![allow(non_upper_case_globals)]
+ use super::__gl_imports::raw;
+ use super::FnPtr;"
+ ));
+
+ for c in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "pub static mut {name}: FnPtr = FnPtr {{
+ f: super::missing_fn_panic as *const raw::c_void,
+ is_loaded: false
+ }};",
+ name = c.proto.ident
+ ));
+ }
+
+ writeln!(dest, "}}")
+}
+
+/// Creates one module for each GL command.
+///
+/// Each module contains `is_loaded` and `load_with` which interact with the `storage` module
+/// created by `write_ptrs`.
+fn write_fn_mods<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for c in &registry.cmds {
+ let fallbacks = match registry.aliases.get(&c.proto.ident) {
+ Some(v) => {
+ let names = v
+ .iter()
+ .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name[..])))
+ .collect::<Vec<_>>();
+ format!("&[{}]", names.join(", "))
+ },
+ None => "&[]".to_string(),
+ };
+ let fnname = &c.proto.ident[..];
+ let symbol = super::gen_symbol_name(registry.api, &c.proto.ident[..]);
+ let symbol = &symbol[..];
+
+ try!(writeln!(dest, r##"
+ #[allow(non_snake_case)]
+ pub mod {fnname} {{
+ use super::{{storage, metaloadfn}};
+ use super::__gl_imports::raw;
+ use super::FnPtr;
+
+ #[inline]
+ #[allow(dead_code)]
+ pub fn is_loaded() -> bool {{
+ unsafe {{ storage::{fnname}.is_loaded }}
+ }}
+
+ #[allow(dead_code)]
+ pub fn load_with<F>(mut loadfn: F) where F: FnMut(&'static str) -> *const raw::c_void {{
+ unsafe {{
+ storage::{fnname} = FnPtr::new(metaloadfn(&mut loadfn, "{symbol}", {fallbacks}))
+ }}
+ }}
+ }}
+ "##, fnname = fnname, fallbacks = fallbacks, symbol = symbol));
+ }
+
+ Ok(())
+}
+
+/// Creates a `missing_fn_panic` function.
+///
+/// This function is the mock that is called if the real function could not be called.
+fn write_panicking_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "#[inline(never)]
+ fn missing_fn_panic() -> ! {{
+ panic!(\"{api} function was not loaded\")
+ }}
+ ",
+ api = registry.api
+ )
+}
+
+/// Creates the `load_with` function.
+///
+/// The function calls `load_with` in each module created by `write_fn_mods`.
+fn write_load_fn<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(dest,
+ "
+ /// Load each OpenGL symbol using a custom load function. This allows for the
+ /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
+ /// ~~~ignore
+ /// gl::load_with(|s| glfw.get_proc_address(s));
+ /// ~~~
+ #[allow(dead_code)]
+ pub fn load_with<F>(mut loadfn: F) where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{
+ #[inline(never)]
+ fn inner(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void) {{
+ "));
+
+ for c in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "{cmd_name}::load_with(&mut *loadfn);",
+ cmd_name = &c.proto.ident[..]
+ ));
+ }
+
+ writeln!(
+ dest,
+ "
+ }}
+
+ inner(&mut loadfn)
+ }}
+ "
+ )
+}
diff --git a/third_party/rust/gl_generator/generators/mod.rs b/third_party/rust/gl_generator/generators/mod.rs
new file mode 100644
index 0000000000..659d2ecaf4
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/mod.rs
@@ -0,0 +1,119 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::{Cmd, Enum, Registry};
+use std::io;
+use Api;
+
+pub mod debug_struct_gen;
+pub mod global_gen;
+pub mod static_gen;
+pub mod static_struct_gen;
+pub mod struct_gen;
+
+/// Trait for a bindings generator.
+///
+/// See https://github.com/brendanzab/gl-rs/tree/master/gl_generator#generator-types
+pub trait Generator {
+ /// Builds the GL bindings.
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write;
+}
+
+pub fn gen_struct_name(api: Api) -> &'static str {
+ match api {
+ Api::Gl => "Gl",
+ Api::Glx => "Glx",
+ Api::Wgl => "Wgl",
+ Api::Egl => "Egl",
+ Api::GlCore => "GlCore",
+ Api::Gles1 => "Gles1",
+ Api::Gles2 => "Gles2",
+ Api::Glsc2 => "Glsc2",
+ }
+}
+
+/// This function generates a `const name: type = value;` item.
+pub fn gen_enum_item<W>(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(dest,
+ "#[allow(dead_code, non_upper_case_globals)] pub const {ident}: {types_prefix}{ty} = {value}{cast_suffix};",
+ ident = enm.ident,
+ types_prefix = if enm.ty == "&'static str" { "" } else { types_prefix },
+ ty = enm.ty,
+ value = enm.value,
+ cast_suffix = match enm.cast {
+ true => format!(" as {}{}", types_prefix, enm.ty),
+ false => String::new(),
+ },
+ )
+}
+
+/// Generates all the type aliases for a namespace.
+///
+/// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the
+/// things that we can't obtain from the XML files.
+pub fn gen_types<W>(api: Api, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ if let Api::Egl = api {
+ try!(writeln!(dest, "{}", include_str!("templates/types/egl.rs")));
+ return Ok(());
+ }
+
+ try!(writeln!(dest, "{}", include_str!("templates/types/gl.rs")));
+
+ match api {
+ Api::Glx => try!(writeln!(dest, "{}", include_str!("templates/types/glx.rs"))),
+ Api::Wgl => try!(writeln!(dest, "{}", include_str!("templates/types/wgl.rs"))),
+ _ => {},
+ }
+
+ Ok(())
+}
+
+/// Generates the list of Rust `Arg`s that a `Cmd` requires.
+pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec<String> {
+ cmd.params
+ .iter()
+ .map(|binding| {
+ // returning
+ if with_idents && with_types {
+ format!("{}: {}", binding.ident, binding.ty)
+ } else if with_types {
+ format!("{}", binding.ty)
+ } else if with_idents {
+ format!("{}", binding.ident)
+ } else {
+ panic!()
+ }
+ })
+ .collect()
+}
+
+/// Generates the native symbol name of a `Cmd`.
+///
+/// Example results: `"glClear"`, `"wglCreateContext"`, etc.
+pub fn gen_symbol_name(api: Api, cmd: &str) -> String {
+ match api {
+ Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => format!("gl{}", cmd),
+ Api::Glx => format!("glX{}", cmd),
+ Api::Wgl => format!("wgl{}", cmd),
+ Api::Egl => format!("egl{}", cmd),
+ }
+}
diff --git a/third_party/rust/gl_generator/generators/static_gen.rs b/third_party/rust/gl_generator/generators/static_gen.rs
new file mode 100644
index 0000000000..8d15de0103
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/static_gen.rs
@@ -0,0 +1,115 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::Registry;
+use std::io;
+
+#[allow(missing_copy_implementations)]
+pub struct StaticGenerator;
+
+impl super::Generator for StaticGenerator {
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write,
+ {
+ try!(write_header(dest));
+ try!(write_type_aliases(registry, dest));
+ try!(write_enums(registry, dest));
+ try!(write_fns(registry, dest));
+ Ok(())
+ }
+}
+
+/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
+/// bindings.
+fn write_header<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ mod __gl_imports {{
+ pub use std::mem;
+ pub use std::os::raw;
+ }}
+ "#
+ )
+}
+
+/// Creates a `types` module which contains all the type aliases.
+///
+/// See also `generators::gen_types`.
+fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ r#"
+ pub mod types {{
+ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
+ "#
+ ));
+
+ try!(super::gen_types(registry.api, dest));
+
+ writeln!(
+ dest,
+ "
+ }}
+ "
+ )
+}
+
+/// Creates all the `<enum>` elements at the root of the bindings.
+fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for enm in &registry.enums {
+ try!(super::gen_enum_item(enm, "types::", dest));
+ }
+
+ Ok(())
+}
+
+/// io::Writes all functions corresponding to the GL bindings.
+///
+/// These are foreign functions, they don't have any content.
+fn write_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ "
+ #[allow(non_snake_case, unused_variables, dead_code)]
+ extern \"system\" {{"
+ ));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "#[link_name=\"{symbol}\"]
+ pub fn {name}({params}) -> {return_suffix};",
+ symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident),
+ name = cmd.proto.ident,
+ params = super::gen_parameters(cmd, true, true).join(", "),
+ return_suffix = cmd.proto.ty,
+ ));
+ }
+
+ writeln!(dest, "}}")
+}
diff --git a/third_party/rust/gl_generator/generators/static_struct_gen.rs b/third_party/rust/gl_generator/generators/static_struct_gen.rs
new file mode 100644
index 0000000000..c03a3e09dd
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/static_struct_gen.rs
@@ -0,0 +1,165 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::Registry;
+use std::io;
+
+#[allow(missing_copy_implementations)]
+pub struct StaticStructGenerator;
+
+impl super::Generator for StaticStructGenerator {
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write,
+ {
+ try!(write_header(dest));
+ try!(write_type_aliases(registry, dest));
+ try!(write_enums(registry, dest));
+ try!(write_struct(registry, dest));
+ try!(write_impl(registry, dest));
+ try!(write_fns(registry, dest));
+ Ok(())
+ }
+}
+
+/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
+/// bindings.
+fn write_header<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ mod __gl_imports {{
+ pub use std::mem;
+ pub use std::os::raw;
+ }}
+ "#
+ )
+}
+
+/// Creates a `types` module which contains all the type aliases.
+///
+/// See also `generators::gen_types`.
+fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ r#"
+ pub mod types {{
+ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
+ "#
+ ));
+
+ try!(super::gen_types(registry.api, dest));
+
+ writeln!(dest, "}}")
+}
+
+/// Creates all the `<enum>` elements at the root of the bindings.
+fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for enm in &registry.enums {
+ try!(super::gen_enum_item(enm, "types::", dest));
+ }
+
+ Ok(())
+}
+
+/// Creates a stub structure.
+///
+/// The name of the struct corresponds to the namespace.
+fn write_struct<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "
+ #[allow(non_camel_case_types, non_snake_case, dead_code)]
+ #[derive(Copy, Clone)]
+ pub struct {api};",
+ api = super::gen_struct_name(registry.api),
+ )
+}
+
+/// Creates the `impl` of the structure created by `write_struct`.
+fn write_impl<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(dest,
+ "impl {api} {{
+ /// Stub function.
+ #[allow(dead_code)]
+ pub fn load_with<F>(mut _loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{
+ {api}
+ }}",
+ api = super::gen_struct_name(registry.api),
+ ));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "#[allow(non_snake_case)]
+ // #[allow(unused_variables)]
+ #[allow(dead_code)]
+ #[inline]
+ pub unsafe fn {name}(&self, {typed_params}) -> {return_suffix} {{
+ {name}({idents})
+ }}",
+ name = cmd.proto.ident,
+ typed_params = super::gen_parameters(cmd, true, true).join(", "),
+ return_suffix = cmd.proto.ty,
+ idents = super::gen_parameters(cmd, true, false).join(", "),
+ ));
+ }
+
+ writeln!(dest, "}}")
+}
+
+/// io::Writes all functions corresponding to the GL bindings.
+///
+/// These are foreign functions, they don't have any content.
+fn write_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ "
+ #[allow(non_snake_case)]
+ #[allow(unused_variables)]
+ #[allow(dead_code)]
+ extern \"system\" {{"
+ ));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "#[link_name=\"{symbol}\"] fn {name}({params}) -> {return_suffix};",
+ symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident),
+ name = cmd.proto.ident,
+ params = super::gen_parameters(cmd, true, true).join(", "),
+ return_suffix = cmd.proto.ty,
+ ));
+ }
+
+ writeln!(dest, "}}")
+}
diff --git a/third_party/rust/gl_generator/generators/struct_gen.rs b/third_party/rust/gl_generator/generators/struct_gen.rs
new file mode 100644
index 0000000000..6fcc3af00e
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/struct_gen.rs
@@ -0,0 +1,256 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use registry::Registry;
+use std::io;
+
+#[allow(missing_copy_implementations)]
+pub struct StructGenerator;
+
+impl super::Generator for StructGenerator {
+ fn write<W>(&self, registry: &Registry, dest: &mut W) -> io::Result<()>
+ where
+ W: io::Write,
+ {
+ try!(write_header(dest));
+ try!(write_type_aliases(registry, dest));
+ try!(write_enums(registry, dest));
+ try!(write_fnptr_struct_def(dest));
+ try!(write_panicking_fns(registry, dest));
+ try!(write_struct(registry, dest));
+ try!(write_impl(registry, dest));
+ Ok(())
+ }
+}
+
+/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
+/// bindings.
+fn write_header<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ r#"
+ mod __gl_imports {{
+ pub use std::mem;
+ pub use std::marker::Send;
+ pub use std::os::raw;
+ }}
+ "#
+ )
+}
+
+/// Creates a `types` module which contains all the type aliases.
+///
+/// See also `generators::gen_types`.
+fn write_type_aliases<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ r#"
+ pub mod types {{
+ #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)]
+ "#
+ ));
+
+ try!(super::gen_types(registry.api, dest));
+
+ writeln!(dest, "}}")
+}
+
+/// Creates all the `<enum>` elements at the root of the bindings.
+fn write_enums<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ for enm in &registry.enums {
+ try!(super::gen_enum_item(enm, "types::", dest));
+ }
+
+ Ok(())
+}
+
+/// Creates a `FnPtr` structure which contains the store for a single binding.
+fn write_fnptr_struct_def<W>(dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "
+ #[allow(dead_code, missing_copy_implementations)]
+ #[derive(Clone)]
+ pub struct FnPtr {{
+ /// The function pointer that will be used when calling the function.
+ f: *const __gl_imports::raw::c_void,
+ /// True if the pointer points to a real function, false if points to a `panic!` fn.
+ is_loaded: bool,
+ }}
+
+ impl FnPtr {{
+ /// Creates a `FnPtr` from a load attempt.
+ fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{
+ if ptr.is_null() {{
+ FnPtr {{
+ f: missing_fn_panic as *const __gl_imports::raw::c_void,
+ is_loaded: false
+ }}
+ }} else {{
+ FnPtr {{ f: ptr, is_loaded: true }}
+ }}
+ }}
+
+ /// Returns `true` if the function has been successfully loaded.
+ ///
+ /// If it returns `false`, calling the corresponding function will fail.
+ #[inline]
+ #[allow(dead_code)]
+ pub fn is_loaded(&self) -> bool {{
+ self.is_loaded
+ }}
+ }}
+ "
+ )
+}
+
+/// Creates a `panicking` module which contains one function per GL command.
+///
+/// These functions are the mocks that are called if the real function could not be loaded.
+fn write_panicking_fns<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ writeln!(
+ dest,
+ "#[inline(never)]
+ fn missing_fn_panic() -> ! {{
+ panic!(\"{api} function was not loaded\")
+ }}",
+ api = registry.api
+ )
+}
+
+/// Creates a structure which stores all the `FnPtr` of the bindings.
+///
+/// The name of the struct corresponds to the namespace.
+fn write_struct<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(
+ dest,
+ "
+ #[allow(non_camel_case_types, non_snake_case, dead_code)]
+ #[derive(Clone)]
+ pub struct {api} {{",
+ api = super::gen_struct_name(registry.api)
+ ));
+
+ for cmd in &registry.cmds {
+ if let Some(v) = registry.aliases.get(&cmd.proto.ident) {
+ try!(writeln!(dest, "/// Fallbacks: {}", v.join(", ")));
+ }
+ try!(writeln!(dest, "pub {name}: FnPtr,", name = cmd.proto.ident));
+ }
+ try!(writeln!(dest, "_priv: ()"));
+
+ writeln!(dest, "}}")
+}
+
+/// Creates the `impl` of the structure created by `write_struct`.
+fn write_impl<W>(registry: &Registry, dest: &mut W) -> io::Result<()>
+where
+ W: io::Write,
+{
+ try!(writeln!(dest,
+ "impl {api} {{
+ /// Load each OpenGL symbol using a custom load function. This allows for the
+ /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`.
+ ///
+ /// ~~~ignore
+ /// let gl = Gl::load_with(|s| glfw.get_proc_address(s));
+ /// ~~~
+ #[allow(dead_code, unused_variables)]
+ pub fn load_with<F>(mut loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{
+ #[inline(never)]
+ fn do_metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void,
+ symbol: &'static str,
+ symbols: &[&'static str])
+ -> *const __gl_imports::raw::c_void {{
+ let mut ptr = loadfn(symbol);
+ if ptr.is_null() {{
+ for &sym in symbols {{
+ ptr = loadfn(sym);
+ if !ptr.is_null() {{ break; }}
+ }}
+ }}
+ ptr
+ }}
+ let mut metaloadfn = |symbol: &'static str, symbols: &[&'static str]| {{
+ do_metaloadfn(&mut loadfn, symbol, symbols)
+ }};
+ {api} {{",
+ api = super::gen_struct_name(registry.api)));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(
+ dest,
+ "{name}: FnPtr::new(metaloadfn(\"{symbol}\", &[{fallbacks}])),",
+ name = cmd.proto.ident,
+ symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident),
+ fallbacks = match registry.aliases.get(&cmd.proto.ident) {
+ Some(fbs) => fbs
+ .iter()
+ .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name)))
+ .collect::<Vec<_>>()
+ .join(", "),
+ None => format!(""),
+ },
+ ))
+ }
+
+ try!(writeln!(dest, "_priv: ()"));
+
+ try!(writeln!(
+ dest,
+ "}}
+ }}"
+ ));
+
+ for cmd in &registry.cmds {
+ try!(writeln!(dest,
+ "#[allow(non_snake_case, unused_variables, dead_code)]
+ #[inline] pub unsafe fn {name}(&self, {params}) -> {return_suffix} {{ \
+ __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\
+ (self.{name}.f)({idents}) \
+ }}",
+ name = cmd.proto.ident,
+ params = super::gen_parameters(cmd, true, true).join(", "),
+ typed_params = super::gen_parameters(cmd, false, true).join(", "),
+ return_suffix = cmd.proto.ty,
+ idents = super::gen_parameters(cmd, true, false).join(", "),
+ ))
+ }
+
+ writeln!(
+ dest,
+ "}}
+
+ unsafe impl __gl_imports::Send for {api} {{}}",
+ api = super::gen_struct_name(registry.api)
+ )
+}
diff --git a/third_party/rust/gl_generator/generators/templates/types/egl.rs b/third_party/rust/gl_generator/generators/templates/types/egl.rs
new file mode 100644
index 0000000000..877638ab98
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/templates/types/egl.rs
@@ -0,0 +1,70 @@
+// platform-specific aliases are unknown
+// IMPORTANT: these are alises to the same level of the bindings
+// the values must be defined by the user
+#[allow(dead_code)]
+pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;
+#[allow(dead_code)]
+pub type khronos_uint64_t = super::khronos_uint64_t;
+#[allow(dead_code)]
+pub type khronos_ssize_t = super::khronos_ssize_t;
+pub type EGLNativeDisplayType = super::EGLNativeDisplayType;
+#[allow(dead_code)]
+pub type EGLNativePixmapType = super::EGLNativePixmapType;
+#[allow(dead_code)]
+pub type EGLNativeWindowType = super::EGLNativeWindowType;
+pub type EGLint = super::EGLint;
+#[allow(dead_code)]
+pub type NativeDisplayType = super::NativeDisplayType;
+#[allow(dead_code)]
+pub type NativePixmapType = super::NativePixmapType;
+#[allow(dead_code)]
+pub type NativeWindowType = super::NativeWindowType;
+
+// EGL alises
+pub type Bool = EGLBoolean; // TODO: not sure
+pub type EGLBoolean = super::__gl_imports::raw::c_uint;
+pub type EGLenum = super::__gl_imports::raw::c_uint;
+pub type EGLAttribKHR = isize;
+pub type EGLAttrib = isize;
+pub type EGLConfig = *const super::__gl_imports::raw::c_void;
+pub type EGLContext = *const super::__gl_imports::raw::c_void;
+pub type EGLDeviceEXT = *const super::__gl_imports::raw::c_void;
+pub type EGLDisplay = *const super::__gl_imports::raw::c_void;
+pub type EGLSurface = *const super::__gl_imports::raw::c_void;
+pub type EGLClientBuffer = *const super::__gl_imports::raw::c_void;
+pub enum __eglMustCastToProperFunctionPointerType_fn {}
+pub type __eglMustCastToProperFunctionPointerType =
+ *mut __eglMustCastToProperFunctionPointerType_fn;
+pub type EGLImageKHR = *const super::__gl_imports::raw::c_void;
+pub type EGLImage = *const super::__gl_imports::raw::c_void;
+pub type EGLOutputLayerEXT = *const super::__gl_imports::raw::c_void;
+pub type EGLOutputPortEXT = *const super::__gl_imports::raw::c_void;
+pub type EGLSyncKHR = *const super::__gl_imports::raw::c_void;
+pub type EGLSync = *const super::__gl_imports::raw::c_void;
+pub type EGLTimeKHR = khronos_utime_nanoseconds_t;
+pub type EGLTime = khronos_utime_nanoseconds_t;
+pub type EGLSyncNV = *const super::__gl_imports::raw::c_void;
+pub type EGLTimeNV = khronos_utime_nanoseconds_t;
+pub type EGLuint64NV = khronos_utime_nanoseconds_t;
+pub type EGLStreamKHR = *const super::__gl_imports::raw::c_void;
+pub type EGLuint64KHR = khronos_uint64_t;
+pub type EGLNativeFileDescriptorKHR = super::__gl_imports::raw::c_int;
+pub type EGLsizeiANDROID = khronos_ssize_t;
+pub type EGLSetBlobFuncANDROID = extern "system" fn(*const super::__gl_imports::raw::c_void,
+ EGLsizeiANDROID,
+ *const super::__gl_imports::raw::c_void,
+ EGLsizeiANDROID)
+ -> ();
+pub type EGLGetBlobFuncANDROID = extern "system" fn(*const super::__gl_imports::raw::c_void,
+ EGLsizeiANDROID,
+ *mut super::__gl_imports::raw::c_void,
+ EGLsizeiANDROID)
+ -> EGLsizeiANDROID;
+
+#[repr(C)]
+pub struct EGLClientPixmapHI {
+ pData: *const super::__gl_imports::raw::c_void,
+ iWidth: EGLint,
+ iHeight: EGLint,
+ iStride: EGLint,
+}
diff --git a/third_party/rust/gl_generator/generators/templates/types/gl.rs b/third_party/rust/gl_generator/generators/templates/types/gl.rs
new file mode 100644
index 0000000000..90e4620104
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/templates/types/gl.rs
@@ -0,0 +1,108 @@
+// Common types from OpenGL 1.1
+pub type GLenum = super::__gl_imports::raw::c_uint;
+pub type GLboolean = super::__gl_imports::raw::c_uchar;
+pub type GLbitfield = super::__gl_imports::raw::c_uint;
+pub type GLvoid = super::__gl_imports::raw::c_void;
+pub type GLbyte = super::__gl_imports::raw::c_char;
+pub type GLshort = super::__gl_imports::raw::c_short;
+pub type GLint = super::__gl_imports::raw::c_int;
+pub type GLclampx = super::__gl_imports::raw::c_int;
+pub type GLubyte = super::__gl_imports::raw::c_uchar;
+pub type GLushort = super::__gl_imports::raw::c_ushort;
+pub type GLuint = super::__gl_imports::raw::c_uint;
+pub type GLsizei = super::__gl_imports::raw::c_int;
+pub type GLfloat = super::__gl_imports::raw::c_float;
+pub type GLclampf = super::__gl_imports::raw::c_float;
+pub type GLdouble = super::__gl_imports::raw::c_double;
+pub type GLclampd = super::__gl_imports::raw::c_double;
+pub type GLeglImageOES = *const super::__gl_imports::raw::c_void;
+pub type GLchar = super::__gl_imports::raw::c_char;
+pub type GLcharARB = super::__gl_imports::raw::c_char;
+
+#[cfg(target_os = "macos")]
+pub type GLhandleARB = *const super::__gl_imports::raw::c_void;
+#[cfg(not(target_os = "macos"))]
+pub type GLhandleARB = super::__gl_imports::raw::c_uint;
+
+pub type GLhalfARB = super::__gl_imports::raw::c_ushort;
+pub type GLhalf = super::__gl_imports::raw::c_ushort;
+
+// Must be 32 bits
+pub type GLfixed = GLint;
+
+pub type GLintptr = isize;
+pub type GLsizeiptr = isize;
+pub type GLint64 = i64;
+pub type GLuint64 = u64;
+pub type GLintptrARB = isize;
+pub type GLsizeiptrARB = isize;
+pub type GLint64EXT = i64;
+pub type GLuint64EXT = u64;
+
+pub enum __GLsync {}
+pub type GLsync = *const __GLsync;
+
+// compatible with OpenCL cl_context
+pub enum _cl_context {}
+pub enum _cl_event {}
+
+pub type GLDEBUGPROC = Option<extern "system" fn(source: GLenum,
+ gltype: GLenum,
+ id: GLuint,
+ severity: GLenum,
+ length: GLsizei,
+ message: *const GLchar,
+ userParam: *mut super::__gl_imports::raw::c_void)>;
+pub type GLDEBUGPROCARB = Option<extern "system" fn(source: GLenum,
+ gltype: GLenum,
+ id: GLuint,
+ severity: GLenum,
+ length: GLsizei,
+ message: *const GLchar,
+ userParam: *mut super::__gl_imports::raw::c_void)>;
+pub type GLDEBUGPROCKHR = Option<extern "system" fn(source: GLenum,
+ gltype: GLenum,
+ id: GLuint,
+ severity: GLenum,
+ length: GLsizei,
+ message: *const GLchar,
+ userParam: *mut super::__gl_imports::raw::c_void)>;
+
+// GLES 1 types
+// "pub type GLclampx = i32;",
+
+// GLES 1/2 types (tagged for GLES 1)
+// "pub type GLbyte = i8;",
+// "pub type GLubyte = u8;",
+// "pub type GLfloat = GLfloat;",
+// "pub type GLclampf = GLfloat;",
+// "pub type GLfixed = i32;",
+// "pub type GLint64 = i64;",
+// "pub type GLuint64 = u64;",
+// "pub type GLintptr = intptr_t;",
+// "pub type GLsizeiptr = ssize_t;",
+
+// GLES 1/2 types (tagged for GLES 2 - attribute syntax is limited)
+// "pub type GLbyte = i8;",
+// "pub type GLubyte = u8;",
+// "pub type GLfloat = GLfloat;",
+// "pub type GLclampf = GLfloat;",
+// "pub type GLfixed = i32;",
+// "pub type GLint64 = i64;",
+// "pub type GLuint64 = u64;",
+// "pub type GLint64EXT = i64;",
+// "pub type GLuint64EXT = u64;",
+// "pub type GLintptr = intptr_t;",
+// "pub type GLsizeiptr = ssize_t;",
+
+// GLES 2 types (none currently)
+
+// Vendor extension types
+pub type GLDEBUGPROCAMD = Option<extern "system" fn(id: GLuint,
+ category: GLenum,
+ severity: GLenum,
+ length: GLsizei,
+ message: *const GLchar,
+ userParam: *mut super::__gl_imports::raw::c_void)>;
+pub type GLhalfNV = super::__gl_imports::raw::c_ushort;
+pub type GLvdpauSurfaceNV = GLintptr;
diff --git a/third_party/rust/gl_generator/generators/templates/types/glx.rs b/third_party/rust/gl_generator/generators/templates/types/glx.rs
new file mode 100644
index 0000000000..b0078da0a1
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/templates/types/glx.rs
@@ -0,0 +1,128 @@
+pub type XID = super::__gl_imports::raw::c_ulong;
+pub type Bool = super::__gl_imports::raw::c_int; // Not sure if this is correct...
+pub enum Display {}
+
+pub type Font = XID;
+pub type Pixmap = XID;
+pub enum Visual {} // TODO: not sure
+pub type VisualID = super::__gl_imports::raw::c_ulong; // TODO: not sure
+pub type Window = XID;
+pub type GLXFBConfigID = XID;
+pub type GLXFBConfig = *const super::__gl_imports::raw::c_void;
+pub type GLXContextID = XID;
+pub type GLXContext = *const super::__gl_imports::raw::c_void;
+pub type GLXPixmap = XID;
+pub type GLXDrawable = XID;
+pub type GLXWindow = XID;
+pub type GLXPbuffer = XID;
+pub enum __GLXextFuncPtr_fn {}
+pub type __GLXextFuncPtr = *mut __GLXextFuncPtr_fn;
+pub type GLXVideoCaptureDeviceNV = XID;
+pub type GLXVideoDeviceNV = super::__gl_imports::raw::c_int;
+pub type GLXVideoSourceSGIX = XID;
+pub type GLXFBConfigIDSGIX = XID;
+pub type GLXFBConfigSGIX = *const super::__gl_imports::raw::c_void;
+pub type GLXPbufferSGIX = XID;
+
+#[repr(C)]
+pub struct XVisualInfo {
+ pub visual: *mut Visual,
+ pub visualid: VisualID,
+ pub screen: super::__gl_imports::raw::c_int,
+ pub depth: super::__gl_imports::raw::c_int,
+ pub class: super::__gl_imports::raw::c_int,
+ pub red_mask: super::__gl_imports::raw::c_ulong,
+ pub green_mask: super::__gl_imports::raw::c_ulong,
+ pub blue_mask: super::__gl_imports::raw::c_ulong,
+ pub colormap_size: super::__gl_imports::raw::c_int,
+ pub bits_per_rgb: super::__gl_imports::raw::c_int,
+}
+
+#[repr(C)]
+pub struct GLXPbufferClobberEvent {
+ pub event_type: super::__gl_imports::raw::c_int, // GLX_DAMAGED or GLX_SAVED
+ pub draw_type: super::__gl_imports::raw::c_int, // GLX_WINDOW or GLX_PBUFFER
+ pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server
+ pub send_event: Bool, // true if this came for SendEvent request
+ pub display: *const Display, // display the event was read from
+ pub drawable: GLXDrawable, // XID of Drawable
+ pub buffer_mask: super::__gl_imports::raw::c_uint, // mask indicating which buffers are affected
+ pub aux_buffer: super::__gl_imports::raw::c_uint, // which aux buffer was affected
+ pub x: super::__gl_imports::raw::c_int,
+ pub y: super::__gl_imports::raw::c_int,
+ pub width: super::__gl_imports::raw::c_int,
+ pub height: super::__gl_imports::raw::c_int,
+ pub count: super::__gl_imports::raw::c_int, // if nonzero, at least this many more
+}
+
+#[repr(C)]
+pub struct GLXBufferSwapComplete {
+ pub type_: super::__gl_imports::raw::c_int,
+ pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server
+ pub send_event: Bool, // true if this came from a SendEvent request
+ pub display: *const Display, // Display the event was read from
+ pub drawable: GLXDrawable, // drawable on which event was requested in event mask
+ pub event_type: super::__gl_imports::raw::c_int,
+ pub ust: i64,
+ pub msc: i64,
+ pub sbc: i64,
+}
+
+// typedef union __GLXEvent {
+// GLXPbufferClobberEvent glxpbufferclobber;
+// GLXBufferSwapComplete glxbufferswapcomplete;
+// long pad[24];
+// }
+
+#[repr(C)]
+pub struct GLXBufferClobberEventSGIX {
+ pub type_: super::__gl_imports::raw::c_int,
+ pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server
+ pub send_event: Bool, // true if this came for SendEvent request
+ pub display: *const Display, // display the event was read from
+ pub drawable: GLXDrawable, // i.d. of Drawable
+ pub event_type: super::__gl_imports::raw::c_int, // GLX_DAMAGED_SGIX or GLX_SAVED_SGIX
+ pub draw_type: super::__gl_imports::raw::c_int, // GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX
+ pub mask: super::__gl_imports::raw::c_uint, // mask indicating which buffers are affected
+ pub x: super::__gl_imports::raw::c_int,
+ pub y: super::__gl_imports::raw::c_int,
+ pub width: super::__gl_imports::raw::c_int,
+ pub height: super::__gl_imports::raw::c_int,
+ pub count: super::__gl_imports::raw::c_int, // if nonzero, at least this many more
+}
+
+#[repr(C)]
+pub struct GLXHyperpipeNetworkSGIX {
+ pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
+ pub networkId: super::__gl_imports::raw::c_int,
+}
+
+#[repr(C)]
+pub struct GLXHyperpipeConfigSGIX {
+ pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
+ pub channel: super::__gl_imports::raw::c_int,
+ pub participationType: super::__gl_imports::raw::c_uint,
+ pub timeSlice: super::__gl_imports::raw::c_int,
+}
+
+#[repr(C)]
+pub struct GLXPipeRect {
+ pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
+ pub srcXOrigin: super::__gl_imports::raw::c_int,
+ pub srcYOrigin: super::__gl_imports::raw::c_int,
+ pub srcWidth: super::__gl_imports::raw::c_int,
+ pub srcHeight: super::__gl_imports::raw::c_int,
+ pub destXOrigin: super::__gl_imports::raw::c_int,
+ pub destYOrigin: super::__gl_imports::raw::c_int,
+ pub destWidth: super::__gl_imports::raw::c_int,
+ pub destHeight: super::__gl_imports::raw::c_int,
+}
+
+#[repr(C)]
+pub struct GLXPipeRectLimits {
+ pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX]
+ pub XOrigin: super::__gl_imports::raw::c_int,
+ pub YOrigin: super::__gl_imports::raw::c_int,
+ pub maxHeight: super::__gl_imports::raw::c_int,
+ pub maxWidth: super::__gl_imports::raw::c_int,
+}
diff --git a/third_party/rust/gl_generator/generators/templates/types/wgl.rs b/third_party/rust/gl_generator/generators/templates/types/wgl.rs
new file mode 100644
index 0000000000..a376d4fa05
--- /dev/null
+++ b/third_party/rust/gl_generator/generators/templates/types/wgl.rs
@@ -0,0 +1,139 @@
+// From WinNT.h
+
+pub type CHAR = super::__gl_imports::raw::c_char;
+pub type HANDLE = PVOID;
+pub type LONG = super::__gl_imports::raw::c_long;
+pub type LPCSTR = *const super::__gl_imports::raw::c_char;
+pub type VOID = ();
+// #define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
+pub type HPBUFFERARB = *const super::__gl_imports::raw::c_void;
+pub type HPBUFFEREXT = *const super::__gl_imports::raw::c_void;
+pub type HVIDEOOUTPUTDEVICENV = *const super::__gl_imports::raw::c_void;
+pub type HPVIDEODEV = *const super::__gl_imports::raw::c_void;
+pub type HPGPUNV = *const super::__gl_imports::raw::c_void;
+pub type HGPUNV = *const super::__gl_imports::raw::c_void;
+pub type HVIDEOINPUTDEVICENV = *const super::__gl_imports::raw::c_void;
+
+// From Windef.h
+
+pub type BOOL = super::__gl_imports::raw::c_int;
+pub type BYTE = super::__gl_imports::raw::c_uchar;
+pub type COLORREF = DWORD;
+pub type FLOAT = super::__gl_imports::raw::c_float;
+pub type HDC = HANDLE;
+pub type HENHMETAFILE = HANDLE;
+pub type HGLRC = *const super::__gl_imports::raw::c_void;
+pub type INT = super::__gl_imports::raw::c_int;
+pub type PVOID = *const super::__gl_imports::raw::c_void;
+pub type LPVOID = *const super::__gl_imports::raw::c_void;
+pub enum __PROC_fn {}
+pub type PROC = *mut __PROC_fn;
+
+#[repr(C)]
+pub struct RECT {
+ left: LONG,
+ top: LONG,
+ right: LONG,
+ bottom: LONG,
+}
+
+pub type UINT = super::__gl_imports::raw::c_uint;
+pub type USHORT = super::__gl_imports::raw::c_ushort;
+pub type WORD = super::__gl_imports::raw::c_ushort;
+
+// From BaseTsd.h
+
+pub type INT32 = i32;
+pub type INT64 = i64;
+
+// From IntSafe.h
+
+pub type DWORD = super::__gl_imports::raw::c_ulong;
+
+// From Wingdi.h
+
+#[repr(C)]
+pub struct POINTFLOAT {
+ pub x: FLOAT,
+ pub y: FLOAT,
+}
+
+#[repr(C)]
+pub struct GLYPHMETRICSFLOAT {
+ pub gmfBlackBoxX: FLOAT,
+ pub gmfBlackBoxY: FLOAT,
+ pub gmfptGlyphOrigin: POINTFLOAT,
+ pub gmfCellIncX: FLOAT,
+ pub gmfCellIncY: FLOAT,
+}
+pub type LPGLYPHMETRICSFLOAT = *const GLYPHMETRICSFLOAT;
+
+#[repr(C)]
+pub struct LAYERPLANEDESCRIPTOR {
+ pub nSize: WORD,
+ pub nVersion: WORD,
+ pub dwFlags: DWORD,
+ pub iPixelType: BYTE,
+ pub cColorBits: BYTE,
+ pub cRedBits: BYTE,
+ pub cRedShift: BYTE,
+ pub cGreenBits: BYTE,
+ pub cGreenShift: BYTE,
+ pub cBlueBits: BYTE,
+ pub cBlueShift: BYTE,
+ pub cAlphaBits: BYTE,
+ pub cAlphaShift: BYTE,
+ pub cAccumBits: BYTE,
+ pub cAccumRedBits: BYTE,
+ pub cAccumGreenBits: BYTE,
+ pub cAccumBlueBits: BYTE,
+ pub cAccumAlphaBits: BYTE,
+ pub cDepthBits: BYTE,
+ pub cStencilBits: BYTE,
+ pub cAuxBuffers: BYTE,
+ pub iLayerType: BYTE,
+ pub bReserved: BYTE,
+ pub crTransparent: COLORREF,
+}
+
+#[repr(C)]
+pub struct PIXELFORMATDESCRIPTOR {
+ pub nSize: WORD,
+ pub nVersion: WORD,
+ pub dwFlags: DWORD,
+ pub iPixelType: BYTE,
+ pub cColorBits: BYTE,
+ pub cRedBits: BYTE,
+ pub cRedShift: BYTE,
+ pub cGreenBits: BYTE,
+ pub cGreenShift: BYTE,
+ pub cBlueBits: BYTE,
+ pub cBlueShift: BYTE,
+ pub cAlphaBits: BYTE,
+ pub cAlphaShift: BYTE,
+ pub cAccumBits: BYTE,
+ pub cAccumRedBits: BYTE,
+ pub cAccumGreenBits: BYTE,
+ pub cAccumBlueBits: BYTE,
+ pub cAccumAlphaBits: BYTE,
+ pub cDepthBits: BYTE,
+ pub cStencilBits: BYTE,
+ pub cAuxBuffers: BYTE,
+ pub iLayerType: BYTE,
+ pub bReserved: BYTE,
+ pub dwLayerMask: DWORD,
+ pub dwVisibleMask: DWORD,
+ pub dwDamageMask: DWORD,
+}
+
+#[repr(C)]
+pub struct _GPU_DEVICE {
+ cb: DWORD,
+ DeviceName: [CHAR; 32],
+ DeviceString: [CHAR; 128],
+ Flags: DWORD,
+ rcVirtualScreen: RECT,
+}
+
+pub struct GPU_DEVICE(_GPU_DEVICE);
+pub struct PGPU_DEVICE(*const _GPU_DEVICE);
diff --git a/third_party/rust/gl_generator/lib.rs b/third_party/rust/gl_generator/lib.rs
new file mode 100644
index 0000000000..ebeb07be25
--- /dev/null
+++ b/third_party/rust/gl_generator/lib.rs
@@ -0,0 +1,81 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! An OpenGL bindings generator. It defines a function named `generate_bindings` which can be
+//! used to generate all constants and functions of a given OpenGL version.
+//!
+//! # Example
+//!
+//! In `build.rs`:
+//!
+//! ```no_run
+//! extern crate gl_generator;
+//!
+//! use gl_generator::{Registry, Api, Profile, Fallbacks, GlobalGenerator};
+//! use std::env;
+//! use std::fs::File;
+//! use std::path::Path;
+//!
+//! fn main() {
+//! let dest = env::var("OUT_DIR").unwrap();
+//! let mut file = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap();
+//!
+//! Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [])
+//! .write_bindings(GlobalGenerator, &mut file)
+//! .unwrap();
+//! }
+//! ```
+//!
+//! In your project:
+//!
+//! ```ignore
+//! include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
+//! ```
+//!
+//! # About EGL
+//!
+//! When you generate bindings for EGL, the following platform-specific types must be declared
+//! *at the same level where you include the bindings*:
+//!
+//! - `khronos_utime_nanoseconds_t`
+//! - `khronos_uint64_t`
+//! - `khronos_ssize_t`
+//! - `EGLNativeDisplayType`
+//! - `EGLNativePixmapType`
+//! - `EGLNativeWindowType`
+//! - `EGLint`
+//! - `NativeDisplayType`
+//! - `NativePixmapType`
+//! - `NativeWindowType`
+//!
+
+#[macro_use]
+extern crate log;
+extern crate xml;
+
+#[cfg(feature = "unstable_generator_utils")]
+pub mod generators;
+#[cfg(not(feature = "unstable_generator_utils"))]
+mod generators;
+
+mod registry;
+
+pub use generators::debug_struct_gen::DebugStructGenerator;
+pub use generators::global_gen::GlobalGenerator;
+pub use generators::static_gen::StaticGenerator;
+pub use generators::static_struct_gen::StaticStructGenerator;
+pub use generators::struct_gen::StructGenerator;
+pub use generators::Generator;
+
+pub use registry::*;
diff --git a/third_party/rust/gl_generator/registry/mod.rs b/third_party/rust/gl_generator/registry/mod.rs
new file mode 100644
index 0000000000..385b2dfea1
--- /dev/null
+++ b/third_party/rust/gl_generator/registry/mod.rs
@@ -0,0 +1,202 @@
+// Copyright 2015-2016 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate khronos_api;
+
+use std::borrow::Cow;
+use std::collections::{BTreeMap, BTreeSet};
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::io;
+use std::ops::{Add, AddAssign};
+
+use Generator;
+
+mod parse;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Api {
+ Gl,
+ Glx,
+ Wgl,
+ Egl,
+ GlCore,
+ Gles1,
+ Gles2,
+ Glsc2,
+}
+
+impl fmt::Display for Api {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Api::Gl => write!(fmt, "gl"),
+ Api::Glx => write!(fmt, "glx"),
+ Api::Wgl => write!(fmt, "wgl"),
+ Api::Egl => write!(fmt, "egl"),
+ Api::GlCore => write!(fmt, "glcore"),
+ Api::Gles1 => write!(fmt, "gles1"),
+ Api::Gles2 => write!(fmt, "gles2"),
+ Api::Glsc2 => write!(fmt, "glsc2"),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Fallbacks {
+ All,
+ None,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Profile {
+ Core,
+ Compatibility,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Enum {
+ pub ident: String,
+ pub value: String,
+ pub cast: bool,
+ pub alias: Option<String>,
+ pub ty: Cow<'static, str>,
+}
+
+impl Hash for Enum {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.ident.hash(state);
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Binding {
+ pub ident: String,
+ pub ty: Cow<'static, str>,
+ pub group: Option<String>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Group {
+ pub ident: String,
+ pub enums_type: Option<String>,
+ pub enums: Vec<String>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Cmd {
+ pub proto: Binding,
+ pub params: Vec<Binding>,
+ pub alias: Option<String>,
+ pub vecequiv: Option<String>,
+ pub glx: Option<GlxOpcode>,
+}
+
+impl Hash for Cmd {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.proto.ident.hash(state);
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct GlxOpcode {
+ pub opcode: String,
+ pub name: Option<String>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Registry {
+ pub api: Api,
+ pub enums: BTreeSet<Enum>,
+ pub cmds: BTreeSet<Cmd>,
+ pub aliases: BTreeMap<String, Vec<String>>,
+ pub groups: BTreeMap<String, Group>,
+}
+
+impl Registry {
+ pub fn new<'a, Exts>(
+ api: Api,
+ version: (u8, u8),
+ profile: Profile,
+ fallbacks: Fallbacks,
+ extensions: Exts,
+ ) -> Registry
+ where
+ Exts: AsRef<[&'a str]>,
+ {
+ let (major, minor) = version;
+ let extensions = extensions.as_ref().iter().map(<&str>::to_string).collect();
+
+ let filter = parse::Filter {
+ api,
+ fallbacks,
+ extensions,
+ version: format!("{}.{}", major, minor),
+ profile,
+ };
+
+ let src = match api {
+ Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => khronos_api::GL_XML,
+ Api::Glx => khronos_api::GLX_XML,
+ Api::Wgl => khronos_api::WGL_XML,
+ Api::Egl => khronos_api::EGL_XML,
+ };
+
+ let mut registry = parse::from_xml(src, &filter, true);
+ if filter.extensions.iter().any(|e| e.starts_with("GL_ANGLE_")) {
+ registry += parse::from_xml(khronos_api::GL_ANGLE_EXT_XML, &filter, false);
+ }
+ if filter.extensions.iter().any(|e| e.starts_with("EGL_ANGLE_")) {
+ registry += parse::from_xml(khronos_api::EGL_ANGLE_EXT_XML, &filter, false);
+ }
+ registry
+ }
+
+ pub fn write_bindings<W, G>(&self, generator: G, output: &mut W) -> io::Result<()>
+ where
+ G: Generator,
+ W: io::Write,
+ {
+ generator.write(&self, output)
+ }
+
+ /// Returns a set of all the types used in the supplied registry. This is useful
+ /// for working out what conversions are needed for the specific registry.
+ pub fn get_tys(&self) -> BTreeSet<&str> {
+ let mut tys = BTreeSet::new();
+ for def in &self.cmds {
+ tys.insert(def.proto.ty.as_ref());
+ for param in &def.params {
+ tys.insert(param.ty.as_ref());
+ }
+ }
+ tys
+ }
+}
+
+impl Add for Registry {
+ type Output = Registry;
+
+ fn add(mut self, other: Registry) -> Registry {
+ self += other;
+ self
+ }
+}
+
+impl AddAssign for Registry {
+ fn add_assign(&mut self, other: Self) {
+ self.enums.extend(other.enums);
+ self.cmds.extend(other.cmds);
+ self.aliases.extend(other.aliases);
+ }
+}
diff --git a/third_party/rust/gl_generator/registry/parse.rs b/third_party/rust/gl_generator/registry/parse.rs
new file mode 100644
index 0000000000..c1a11a6c5f
--- /dev/null
+++ b/third_party/rust/gl_generator/registry/parse.rs
@@ -0,0 +1,1393 @@
+// Copyright 2015 Brendan Zabarauskas and the gl-rs developers
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate khronos_api;
+
+use std::borrow::Cow;
+use std::collections::btree_map::Entry;
+use std::collections::{BTreeMap, BTreeSet};
+use std::io;
+use xml::attribute::OwnedAttribute;
+use xml::reader::XmlEvent;
+use xml::EventReader as XmlEventReader;
+
+use registry::{Binding, Cmd, Enum, GlxOpcode, Group, Registry};
+use {Api, Fallbacks, Profile};
+
+pub fn from_xml<R: io::Read>(
+ src: R,
+ filter: &Filter,
+ require_feature: bool,
+) -> Registry {
+ XmlEventReader::new(src)
+ .into_iter()
+ .map(Result::unwrap)
+ .filter_map(ParseEvent::from_xml)
+ .parse(filter, require_feature)
+}
+
+#[derive(Debug, PartialEq, Eq)]
+struct Attribute {
+ key: String,
+ value: String,
+}
+
+impl Attribute {
+ fn new<Key, Value>(key: Key, value: Value) -> Attribute
+ where
+ Key: ToString,
+ Value: ToString,
+ {
+ Attribute {
+ key: key.to_string(),
+ value: value.to_string(),
+ }
+ }
+}
+
+impl From<OwnedAttribute> for Attribute {
+ fn from(attribute: OwnedAttribute) -> Attribute {
+ Attribute::new(attribute.name.local_name, attribute.value)
+ }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum ParseEvent {
+ Start(String, Vec<Attribute>),
+ End(String),
+ Text(String),
+}
+
+impl ParseEvent {
+ fn from_xml(event: XmlEvent) -> Option<ParseEvent> {
+ match event {
+ XmlEvent::StartDocument { .. } => None,
+ XmlEvent::EndDocument => None,
+ XmlEvent::StartElement {
+ name, attributes, ..
+ } => {
+ let attributes = attributes.into_iter().map(Attribute::from).collect();
+ Some(ParseEvent::Start(name.local_name, attributes))
+ },
+ XmlEvent::EndElement { name } => Some(ParseEvent::End(name.local_name)),
+ XmlEvent::Characters(chars) => Some(ParseEvent::Text(chars)),
+ XmlEvent::ProcessingInstruction { .. } => None,
+ XmlEvent::CData(_) => None,
+ XmlEvent::Comment(_) => None,
+ XmlEvent::Whitespace(_) => None,
+ }
+ }
+}
+
+fn api_from_str(src: &str) -> Result<Option<Api>, ()> {
+ match src {
+ "gl" => Ok(Some(Api::Gl)),
+ "glx" => Ok(Some(Api::Glx)),
+ "wgl" => Ok(Some(Api::Wgl)),
+ "egl" => Ok(Some(Api::Egl)),
+ "glcore" => Ok(Some(Api::GlCore)),
+ "gles1" => Ok(Some(Api::Gles1)),
+ "gles2" => Ok(Some(Api::Gles2)),
+ "glsc2" => Ok(Some(Api::Glsc2)),
+ "disabled" => Ok(None),
+ _ => Err(()),
+ }
+}
+
+fn profile_from_str(src: &str) -> Result<Profile, ()> {
+ match src {
+ "core" => Ok(Profile::Core),
+ "compatibility" => Ok(Profile::Compatibility),
+ _ => Err(()),
+ }
+}
+
+fn underscore_numeric_prefix(src: &str) -> String {
+ match src.chars().next() {
+ Some(c) if c.is_numeric() => format!("_{}", src),
+ Some(_) | None => src.to_string(),
+ }
+}
+
+fn underscore_keyword(ident: String) -> String {
+ match ident.as_ref() {
+ "in" => "in_".to_string(),
+ "ref" => "ref_".to_string(),
+ "type" => "type_".to_string(),
+ _ => ident,
+ }
+}
+
+fn trim_str<'a>(s: &'a str, trim: &str) -> &'a str {
+ if s.starts_with(trim) {
+ &s[trim.len()..]
+ } else {
+ s
+ }
+}
+
+fn trim_enum_prefix(ident: &str, api: Api) -> String {
+ let ident = match api {
+ Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => trim_str(ident, "GL_"),
+ Api::Glx => trim_str(ident, "GLX_"),
+ Api::Wgl => trim_str(ident, "WGL_"),
+ Api::Egl => trim_str(ident, "EGL_"),
+ };
+ underscore_numeric_prefix(ident)
+}
+
+fn make_enum(ident: String, ty: Option<String>, value: String, alias: Option<String>) -> Enum {
+ let (ty, value, cast) = {
+ if value.starts_with("((") && value.ends_with(")") {
+ // Some enums have a value of the form `'((' type ')' expr ')'`.
+
+ // nothing to see here....
+ // just brute forcing some paren matching... (ノ ◕ ◡ ◕)ノ *:・゚✧
+ let working = &value[2..value.len() - 1];
+ if let Some((i, _)) = working.match_indices(")").next() {
+ let ty = working[..i].to_string();
+ let value = working[i + 1..].to_string();
+
+ (Cow::Owned(ty), value, true)
+ } else {
+ panic!("Unexpected value format: {}", value)
+ }
+ } else {
+ let ty = match ty {
+ Some(ref ty) if ty == "u" => "GLuint",
+ Some(ref ty) if ty == "ull" => "GLuint64",
+ Some(ty) => panic!("Unhandled enum type: {}", ty),
+ None if value.starts_with("\"") => "&'static str",
+ None if ident == "TRUE" || ident == "FALSE" => "GLboolean",
+ None => "GLenum",
+ };
+ (Cow::Borrowed(ty), value, false)
+ }
+ };
+
+ Enum {
+ ident: ident,
+ value: value,
+ cast: cast,
+ alias: alias,
+ ty: ty,
+ }
+}
+
+fn make_egl_enum(ident: String, ty: Option<String>, value: String, alias: Option<String>) -> Enum {
+ let (ty, value, cast) = {
+ if value.starts_with("EGL_CAST(") && value.ends_with(")") {
+ // Handling "SpecialNumbers" in the egl.xml file
+ // The values for these enums has the form `'EGL_CAST(' type ',' expr ')'`.
+ let working = &value[9..value.len() - 1];
+ if let Some((i, _)) = working.match_indices(",").next() {
+ let ty = working[..i].to_string();
+ let value = working[i + 1..].to_string();
+
+ (Cow::Owned(ty), value, true)
+ } else {
+ panic!("Unexpected value format: {}", value)
+ }
+ } else {
+ match value.chars().next() {
+ Some('-') | Some('0'..='9') => (),
+ _ => panic!("Unexpected value format: {}", value),
+ }
+
+ let ty = match ty {
+ Some(ref ty) if ty == "ull" => "EGLuint64KHR",
+ Some(ty) => panic!("Unhandled enum type: {}", ty),
+ None if value.starts_with('-') => "EGLint",
+ None if ident == "TRUE" || ident == "FALSE" => "EGLBoolean",
+ None => "EGLenum",
+ };
+ (Cow::Borrowed(ty), value, false)
+ }
+ };
+
+ Enum {
+ ident: ident,
+ value: value,
+ cast: cast,
+ alias: alias,
+ ty: ty,
+ }
+}
+
+fn trim_cmd_prefix(ident: &str, api: Api) -> &str {
+ match api {
+ Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => trim_str(ident, "gl"),
+ Api::Glx => trim_str(ident, "glX"),
+ Api::Wgl => trim_str(ident, "wgl"),
+ Api::Egl => trim_str(ident, "egl"),
+ }
+}
+
+fn merge_map(a: &mut BTreeMap<String, Vec<String>>, b: BTreeMap<String, Vec<String>>) {
+ for (k, v) in b {
+ match a.entry(k) {
+ Entry::Occupied(mut ent) => {
+ ent.get_mut().extend(v);
+ },
+ Entry::Vacant(ent) => {
+ ent.insert(v);
+ },
+ }
+ }
+}
+
+#[derive(Clone)]
+struct Feature {
+ pub api: Api,
+ pub name: String,
+ pub number: String,
+ pub requires: Vec<Require>,
+ pub removes: Vec<Remove>,
+}
+
+#[derive(Clone)]
+struct Require {
+ /// A reference to the earlier types, by name
+ pub enums: Vec<String>,
+ /// A reference to the earlier types, by name
+ pub commands: Vec<String>,
+}
+
+#[derive(Clone)]
+struct Remove {
+ // always Core, for now
+ pub profile: Profile,
+ /// A reference to the earlier types, by name
+ pub enums: Vec<String>,
+ /// A reference to the earlier types, by name
+ pub commands: Vec<String>,
+}
+
+#[derive(Clone)]
+struct Extension {
+ pub name: String,
+ /// which apis this extension is defined for (see Feature.api)
+ pub supported: Vec<Api>,
+ pub requires: Vec<Require>,
+}
+
+pub struct Filter {
+ pub api: Api,
+ pub fallbacks: Fallbacks,
+ pub extensions: BTreeSet<String>,
+ pub profile: Profile,
+ pub version: String,
+}
+
+trait Parse: Sized + Iterator<Item = ParseEvent> {
+ fn parse(mut self, filter: &Filter, require_feature: bool) -> Registry {
+ self.consume_start_element("registry");
+
+ let mut enums = Vec::new();
+ let mut cmds = Vec::new();
+ let mut features = Vec::new();
+ let mut extensions = Vec::new();
+ let mut aliases = BTreeMap::new();
+ let mut groups: BTreeMap<String, Group> = BTreeMap::new();
+
+ while let Some(event) = self.next() {
+ match event {
+ // ignores
+ ParseEvent::Text(_) => (),
+ ParseEvent::Start(ref name, _) if name == "comment" => self.skip_to_end("comment"),
+ ParseEvent::Start(ref name, _) if name == "types" => self.skip_to_end("types"),
+
+ // add group namespace
+ ParseEvent::Start(ref name, _) if name == "groups" => {
+ groups.extend(self.consume_groups(filter.api));
+ },
+
+ // add enum namespace
+ ParseEvent::Start(ref name, ref attributes) if name == "enums" => {
+ enums.extend(self.consume_enums(filter.api));
+ let enums_group = get_attribute(&attributes, "group");
+ let enums_type = get_attribute(&attributes, "type");
+ if let Some(group) = enums_group.and_then(|name| groups.get_mut(&name)) {
+ group.enums_type = enums_type;
+ }
+ },
+
+ // add command namespace
+ ParseEvent::Start(ref name, _) if name == "commands" => {
+ let (new_cmds, new_aliases) = self.consume_cmds(filter.api);
+ cmds.extend(new_cmds);
+ merge_map(&mut aliases, new_aliases);
+ },
+
+ ParseEvent::Start(ref name, ref attributes) if name == "feature" => {
+ debug!("Parsing feature: {:?}", attributes);
+ features.push(Feature::convert(&mut self, &attributes));
+ },
+
+ ParseEvent::Start(ref name, _) if name == "extensions" => loop {
+ match self.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) if name == "extension" => {
+ extensions.push(Extension::convert(&mut self, &attributes));
+ },
+ ParseEvent::End(ref name) if name == "extensions" => break,
+ event => panic!("Unexpected message {:?}", event),
+ }
+ },
+
+ // finished building the registry
+ ParseEvent::End(ref name) if name == "registry" => break,
+
+ // error handling
+ event => panic!("Expected </registry>, found: {:?}", event),
+ }
+ }
+
+ let mut desired_enums = BTreeSet::new();
+ let mut desired_cmds = BTreeSet::new();
+
+ // find the features we want
+ let mut found_feature = false;
+ for feature in &features {
+ // XXX: verify that the string comparison with <= actually works as desired
+ if feature.api == filter.api && feature.number <= filter.version {
+ for require in &feature.requires {
+ desired_enums.extend(require.enums.iter().map(|x| x.clone()));
+ desired_cmds.extend(require.commands.iter().map(|x| x.clone()));
+ }
+
+ for remove in &feature.removes {
+ if remove.profile == filter.profile {
+ for enm in &remove.enums {
+ debug!("Removing {}", enm);
+ desired_enums.remove(enm);
+ }
+ for cmd in &remove.commands {
+ debug!("Removing {}", cmd);
+ desired_cmds.remove(cmd);
+ }
+ }
+ }
+ }
+ if feature.number == filter.version {
+ found_feature = true;
+ }
+ }
+
+ if !found_feature && require_feature {
+ panic!("Did not find version {} in the registry", filter.version);
+ }
+
+ for extension in &extensions {
+ if filter.extensions.contains(&extension.name) {
+ if !extension.supported.contains(&filter.api) {
+ panic!(
+ "Requested {}, which doesn't support the {} API",
+ extension.name, filter.api
+ );
+ }
+ for require in &extension.requires {
+ desired_enums.extend(require.enums.iter().map(|x| x.clone()));
+ desired_cmds.extend(require.commands.iter().map(|x| x.clone()));
+ }
+ }
+ }
+
+ let is_desired_enum = |e: &Enum| {
+ desired_enums.contains(&("GL_".to_string() + &e.ident))
+ || desired_enums.contains(&("WGL_".to_string() + &e.ident))
+ || desired_enums.contains(&("GLX_".to_string() + &e.ident))
+ || desired_enums.contains(&("EGL_".to_string() + &e.ident))
+ };
+
+ let is_desired_cmd = |c: &Cmd| {
+ desired_cmds.contains(&("gl".to_string() + &c.proto.ident))
+ || desired_cmds.contains(&("wgl".to_string() + &c.proto.ident))
+ || desired_cmds.contains(&("glX".to_string() + &c.proto.ident))
+ || desired_cmds.contains(&("egl".to_string() + &c.proto.ident))
+ };
+
+ Registry {
+ api: filter.api,
+ enums: enums.into_iter().filter(is_desired_enum).collect(),
+ cmds: cmds.into_iter().filter(is_desired_cmd).collect(),
+ aliases: if filter.fallbacks == Fallbacks::None {
+ BTreeMap::new()
+ } else {
+ aliases
+ },
+ groups,
+ }
+ }
+
+ fn consume_characters(&mut self) -> String {
+ match self.next().unwrap() {
+ ParseEvent::Text(ch) => ch,
+ event => panic!("Expected characters, found: {:?}", event),
+ }
+ }
+
+ fn consume_start_element(&mut self, expected_name: &str) -> Vec<Attribute> {
+ match self.next().unwrap() {
+ ParseEvent::Start(name, attributes) => {
+ if expected_name == name {
+ attributes
+ } else {
+ panic!("Expected <{}>, found: <{}>", expected_name, name)
+ }
+ },
+ event => panic!("Expected <{}>, found: {:?}", expected_name, event),
+ }
+ }
+
+ fn consume_end_element(&mut self, expected_name: &str) {
+ match self.next().unwrap() {
+ ParseEvent::End(ref name) if expected_name == name => (),
+ event => panic!("Expected </{}>, found: {:?}", expected_name, event),
+ }
+ }
+
+ fn skip_to_end(&mut self, expected_name: &str) {
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::End(ref name) if expected_name == name => break,
+ _ => {},
+ }
+ }
+ }
+
+ fn consume_two<'a, T: FromXml, U: FromXml>(
+ &mut self,
+ one: &'a str,
+ two: &'a str,
+ end: &'a str,
+ ) -> (Vec<T>, Vec<U>) {
+ debug!("consume_two: looking for {} and {} until {}", one, two, end);
+
+ let mut ones = Vec::new();
+ let mut twos = Vec::new();
+
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) => {
+ debug!("Found start element <{:?} {:?}>", name, attributes);
+ debug!("one and two are {} and {}", one, two);
+
+ let n = name.clone();
+
+ if one == n {
+ ones.push(FromXml::convert(self, &attributes));
+ } else if "type" == n {
+ // XXX: GL1.1 contains types, which we never care about anyway.
+ // Make sure consume_two doesn't get used for things which *do*
+ // care about type.
+ warn!("Ignoring type!");
+ continue;
+ } else if two == n {
+ twos.push(FromXml::convert(self, &attributes));
+ } else {
+ panic!("Unexpected element: <{:?} {:?}>", n, &attributes);
+ }
+ },
+ ParseEvent::End(ref name) => {
+ debug!("Found end element </{:?}>", name);
+
+ if one == name || two == name {
+ continue;
+ } else if "type" == name {
+ // XXX: GL1.1 contains types, which we never care about anyway.
+ // Make sure consume_two doesn't get used for things which *do*
+ // care about type.
+ warn!("Ignoring type!");
+ continue;
+ } else if end == name {
+ return (ones, twos);
+ } else {
+ panic!("Unexpected end element {:?}", name);
+ }
+ },
+ event => panic!("Unexpected message {:?}", event),
+ }
+ }
+ }
+
+ fn consume_enums(&mut self, api: Api) -> Vec<Enum> {
+ let mut enums = Vec::new();
+ loop {
+ match self.next().unwrap() {
+ // ignores
+ ParseEvent::Text(_) => {},
+ ParseEvent::Start(ref name, _) if name == "unused" => self.skip_to_end("unused"),
+
+ // add enum definition
+ ParseEvent::Start(ref name, ref attributes) if name == "enum" => {
+ enums.push(self.consume_enum(api, attributes));
+ },
+
+ // finished building the namespace
+ ParseEvent::End(ref name) if name == "enums" => break,
+ // error handling
+ event => panic!("Expected </enums>, found: {:?}", event),
+ }
+ }
+ enums
+ }
+
+ fn consume_enum(&mut self, api: Api, attributes: &[Attribute]) -> Enum {
+ let ident = trim_enum_prefix(&get_attribute(&attributes, "name").unwrap(), api).to_string();
+ let value = get_attribute(&attributes, "value").unwrap();
+ let alias = get_attribute(&attributes, "alias");
+ let ty = get_attribute(&attributes, "type");
+ self.consume_end_element("enum");
+
+ match api {
+ Api::Egl => make_egl_enum(ident, ty, value, alias),
+ _ => make_enum(ident, ty, value, alias),
+ }
+ }
+
+ fn consume_groups(&mut self, api: Api) -> BTreeMap<String, Group> {
+ let mut groups = BTreeMap::new();
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) if name == "group" => {
+ let ident = get_attribute(&attributes, "name").unwrap();
+ let group = Group {
+ ident: ident.clone(),
+ enums_type: None,
+ enums: self.consume_group_enums(api)
+ };
+ groups.insert(ident, group);
+ },
+ ParseEvent::End(ref name) if name == "groups" => break,
+ event => panic!("Expected </groups>, found: {:?}", event),
+ }
+ }
+ groups
+ }
+
+ fn consume_group_enums(&mut self, api: Api) -> Vec<String> {
+ let mut enums = Vec::new();
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) if name == "enum" => {
+ let enum_name = get_attribute(&attributes, "name");
+ enums.push(trim_enum_prefix(&enum_name.unwrap(), api));
+ self.consume_end_element("enum");
+ },
+ ParseEvent::End(ref name) if name == "group" => break,
+ event => panic!("Expected </group>, found: {:?}", event),
+ }
+ }
+ enums
+ }
+
+ fn consume_cmds(&mut self, api: Api) -> (Vec<Cmd>, BTreeMap<String, Vec<String>>) {
+ let mut cmds = Vec::new();
+ let mut aliases: BTreeMap<String, Vec<String>> = BTreeMap::new();
+ loop {
+ match self.next().unwrap() {
+ // add command definition
+ ParseEvent::Start(ref name, _) if name == "command" => {
+ let new = self.consume_cmd(api);
+ if let Some(ref v) = new.alias {
+ match aliases.entry(v.clone()) {
+ Entry::Occupied(mut ent) => {
+ ent.get_mut().push(new.proto.ident.clone());
+ },
+ Entry::Vacant(ent) => {
+ ent.insert(vec![new.proto.ident.clone()]);
+ },
+ }
+ }
+ cmds.push(new);
+ },
+ // finished building the namespace
+ ParseEvent::End(ref name) if name == "commands" => break,
+ // error handling
+ event => panic!("Expected </commands>, found: {:?}", event),
+ }
+ }
+ (cmds, aliases)
+ }
+
+ fn consume_cmd(&mut self, api: Api) -> Cmd {
+ // consume command prototype
+ self.consume_start_element("proto");
+ let mut proto = self.consume_binding("proto", &[]);
+ proto.ident = trim_cmd_prefix(&proto.ident, api).to_string();
+
+ let mut params = Vec::new();
+ let mut alias = None;
+ let mut vecequiv = None;
+ let mut glx = None;
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) if name == "param" => {
+ params.push(self.consume_binding("param", attributes));
+ },
+ ParseEvent::Start(ref name, ref attributes) if name == "alias" => {
+ alias = get_attribute(&attributes, "name");
+ alias = alias.map(|t| trim_cmd_prefix(&t, api).to_string());
+ self.consume_end_element("alias");
+ },
+ ParseEvent::Start(ref name, ref attributes) if name == "vecequiv" => {
+ vecequiv = get_attribute(&attributes, "vecequiv");
+ self.consume_end_element("vecequiv");
+ },
+ ParseEvent::Start(ref name, ref attributes) if name == "glx" => {
+ glx = Some(GlxOpcode {
+ opcode: get_attribute(&attributes, "opcode").unwrap(),
+ name: get_attribute(&attributes, "name"),
+ });
+ self.consume_end_element("glx");
+ },
+ ParseEvent::End(ref name) if name == "command" => break,
+ event => panic!("Expected </command>, found: {:?}", event),
+ }
+ }
+
+ Cmd {
+ proto: proto,
+ params: params,
+ alias: alias,
+ vecequiv: vecequiv,
+ glx: glx,
+ }
+ }
+
+ fn consume_binding(&mut self, outside_tag: &str, attributes: &[Attribute]) -> Binding {
+ // consume type
+ let mut ty = String::new();
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Text(text) => ty.push_str(&text),
+ ParseEvent::Start(ref name, _) if name == "ptype" => (),
+ ParseEvent::End(ref name) if name == "ptype" => (),
+ ParseEvent::Start(ref name, _) if name == "name" => break,
+ event => panic!("Expected binding, found: {:?}", event),
+ }
+ }
+
+ // consume identifier
+ let ident = underscore_keyword(self.consume_characters());
+ self.consume_end_element("name");
+
+ // consume the type suffix
+ loop {
+ match self.next().unwrap() {
+ ParseEvent::Text(text) => ty.push_str(&text),
+ ParseEvent::End(ref name) if name == outside_tag => break,
+ event => panic!("Expected binding, found: {:?}", event),
+ }
+ }
+
+ Binding {
+ ident: ident,
+ ty: to_rust_ty(ty),
+ group: get_attribute(&attributes, "group"),
+ }
+ }
+}
+
+impl<T> Parse for T where T: Sized + Iterator<Item = ParseEvent> {}
+
+fn get_attribute(attribs: &[Attribute], key: &str) -> Option<String> {
+ attribs
+ .iter()
+ .find(|attrib| attrib.key == key)
+ .map(|attrib| attrib.value.clone())
+}
+
+trait FromXml {
+ fn convert<P: Parse>(parser: &mut P, a: &[Attribute]) -> Self;
+}
+
+impl FromXml for Require {
+ fn convert<P: Parse>(parser: &mut P, _: &[Attribute]) -> Require {
+ debug!("Doing a FromXml on Require");
+ let (enums, commands) = parser.consume_two("enum", "command", "require");
+ Require {
+ enums: enums,
+ commands: commands,
+ }
+ }
+}
+
+impl FromXml for Remove {
+ fn convert<P: Parse>(parser: &mut P, a: &[Attribute]) -> Remove {
+ debug!("Doing a FromXml on Remove");
+ let profile = get_attribute(a, "profile").unwrap();
+ let profile = profile_from_str(&profile).unwrap();
+ let (enums, commands) = parser.consume_two("enum", "command", "remove");
+
+ Remove {
+ profile: profile,
+ enums: enums,
+ commands: commands,
+ }
+ }
+}
+
+impl FromXml for Feature {
+ fn convert<P: Parse>(parser: &mut P, a: &[Attribute]) -> Feature {
+ debug!("Doing a FromXml on Feature");
+ let api = get_attribute(a, "api").unwrap();
+ let api = api_from_str(&api).unwrap().unwrap();
+ let name = get_attribute(a, "name").unwrap();
+ let number = get_attribute(a, "number").unwrap();
+
+ debug!("Found api = {}, name = {}, number = {}", api, name, number);
+
+ let (require, remove) = parser.consume_two("require", "remove", "feature");
+
+ Feature {
+ api: api,
+ name: name,
+ number: number,
+ requires: require,
+ removes: remove,
+ }
+ }
+}
+
+impl FromXml for Extension {
+ fn convert<P: Parse>(parser: &mut P, a: &[Attribute]) -> Extension {
+ debug!("Doing a FromXml on Extension");
+ let name = get_attribute(a, "name").unwrap();
+ let supported = get_attribute(a, "supported")
+ .unwrap()
+ .split('|')
+ .filter_map(|api| {
+ api_from_str(api).unwrap_or_else(|()| panic!("unsupported API `{}`", api))
+ })
+ .collect::<Vec<_>>();
+ let mut require = Vec::new();
+ loop {
+ match parser.next().unwrap() {
+ ParseEvent::Start(ref name, ref attributes) if name == "require" => {
+ require.push(FromXml::convert(parser, &attributes));
+ },
+ ParseEvent::End(ref name) if name == "extension" => break,
+ event => panic!("Unexpected message {:?}", event),
+ }
+ }
+
+ Extension {
+ name: name,
+ supported: supported,
+ requires: require,
+ }
+ }
+}
+
+impl FromXml for String {
+ fn convert<P: Parse>(_: &mut P, a: &[Attribute]) -> String {
+ get_attribute(a, "name").unwrap()
+ }
+}
+
+/// Converts a C style type definition to the Rust equivalent
+pub fn to_rust_ty<T: AsRef<str>>(ty: T) -> Cow<'static, str> {
+ let ty = match ty.as_ref().trim() {
+ // gl.xml types
+ "GLDEBUGPROC" => "types::GLDEBUGPROC",
+ "GLDEBUGPROCAMD" => "types::GLDEBUGPROCAMD",
+ "GLDEBUGPROCARB" => "types::GLDEBUGPROCARB",
+ "GLDEBUGPROCKHR" => "types::GLDEBUGPROCKHR",
+ "GLbitfield" => "types::GLbitfield",
+ "GLboolean" => "types::GLboolean",
+ "GLbyte" => "types::GLbyte",
+ "GLclampd" => "types::GLclampd",
+ "GLclampf" => "types::GLclampf",
+ "GLclampx" => "types::GLclampx",
+ "GLdouble" => "types::GLdouble",
+ "GLeglImageOES" => "types::GLeglImageOES",
+ "GLenum" => "types::GLenum",
+ "GLfixed" => "types::GLfixed",
+ "GLfloat" => "types::GLfloat",
+ "GLhalfNV" => "types::GLhalfNV",
+ "GLhandleARB" => "types::GLhandleARB",
+ "GLint" => "types::GLint",
+ "GLint64" => "types::GLint64",
+ "GLint64EXT" => "types::GLint64EXT",
+ "GLintptr" => "types::GLintptr",
+ "GLintptrARB" => "types::GLintptrARB",
+ "GLshort" => "types::GLshort",
+ "GLsizei" => "types::GLsizei",
+ "GLsizeiptr" => "types::GLsizeiptr",
+ "GLsizeiptrARB" => "types::GLsizeiptrARB",
+ "GLsync" => "types::GLsync",
+ "GLubyte" => "types::GLubyte",
+ "GLuint" => "types::GLuint",
+ "GLuint64" => "types::GLuint64",
+ "GLuint64EXT" => "types::GLuint64EXT",
+ "GLushort" => "types::GLushort",
+ "GLvdpauSurfaceNV" => "types::GLvdpauSurfaceNV",
+ "void" => "()",
+ "GLboolean *" => "*mut types::GLboolean",
+ "GLchar *" => "*mut types::GLchar",
+ "const GLchar*" => "*const types::GLchar",
+ "GLcharARB *" => "*mut types::GLcharARB",
+ "GLdouble *" => "*mut types::GLdouble",
+ "GLenum *" => "*mut types::GLenum",
+ "GLfixed *" => "*mut types::GLfixed",
+ "GLfloat *" => "*mut types::GLfloat",
+ "GLhandleARB *" => "*mut types::GLhandleARB",
+ "GLint *" => "*mut types::GLint",
+ "GLint64 *" => "*mut types::GLint64",
+ "GLint64EXT *" => "*mut types::GLint64EXT",
+ "GLsizei *" => "*mut types::GLsizei",
+ "GLubyte *" => "*mut types::GLubyte",
+ "GLuint *" => "*mut types::GLuint",
+ "GLuint [2]" => "*mut [types::GLuint; 2]",
+ "GLuint64 *" => "*mut types::GLuint64",
+ "GLuint64EXT *" => "*mut types::GLuint64EXT",
+ "GLushort *" => "*mut types::GLushort",
+ "GLvoid *" => "*mut types::GLvoid",
+ "GLvoid **" => "*const *mut types::GLvoid",
+ "void *" => "*mut __gl_imports::raw::c_void",
+ "void **" => "*const *mut __gl_imports::raw::c_void",
+ "const GLboolean *" => "*const types::GLboolean",
+ "const GLbyte *" => "*const types::GLbyte",
+ "const GLchar *" => "*const types::GLchar",
+ "const GLcharARB *" => "*const types::GLcharARB",
+ "const GLclampf *" => "*const types::GLclampf",
+ "const GLdouble *" => "*const types::GLdouble",
+ "const GLenum *" => "*const types::GLenum",
+ "const GLfixed *" => "*const types::GLfixed",
+ "const GLfloat" => "types::GLfloat",
+ "const GLfloat *" => "*const types::GLfloat",
+ "const GLhalfNV *" => "*const types::GLhalfNV",
+ "const GLint *" => "*const types::GLint",
+ "const GLint*" => "*const types::GLint",
+ "const GLint64 *" => "*const types::GLint64",
+ "const GLint64EXT *" => "*const types::GLint64EXT",
+ "const GLintptr *" => "*const types::GLintptr",
+ "const GLshort *" => "*const types::GLshort",
+ "const GLsizei*" |
+ "const GLsizei *" => "*const types::GLsizei",
+ "const GLsizeiptr *" => "*const types::GLsizeiptr",
+ "const GLubyte *" => "*const types::GLubyte",
+ "const GLuint *" => "*const types::GLuint",
+ "const GLuint64 *" => "*const types::GLuint64",
+ "const GLuint64EXT *" => "*const types::GLuint64EXT",
+ "const GLushort *" => "*const types::GLushort",
+ "const GLvdpauSurfaceNV *" => "*const types::GLvdpauSurfaceNV",
+ "const GLvoid *" => "*const types::GLvoid",
+ "const void*" |
+ "const void *" => "*const __gl_imports::raw::c_void",
+ "const void **" => "*const *const __gl_imports::raw::c_void",
+ "const void *const*" => "*const *const __gl_imports::raw::c_void",
+ "const GLboolean **" => "*const *const types::GLboolean",
+ "const GLchar **" => "*const *const types::GLchar",
+ "const GLcharARB **" => "*const *const types::GLcharARB",
+ "const GLvoid **" => "*const *const types::GLvoid",
+ "const GLchar *const*" => "*const *const types::GLchar",
+ "const GLvoid *const*" => "*const *const types::GLvoid",
+ "struct _cl_context *" => "*const types::_cl_context",
+ "struct _cl_event *" => "*const types::_cl_event",
+ "GLuint[2]" => "[Gluint; 2]",
+
+ // glx.xml types
+ "Bool" => "types::Bool",
+ "Colormap" => "types::Colormap",
+ "DMbuffer" => "types::DMbuffer",
+ "Font" => "types::Font",
+ "GLXContext" => "types::GLXContext",
+ "GLXContextID" => "types::GLXContextID",
+ "GLXDrawable" => "types::GLXDrawable",
+ "GLXFBConfig" => "types::GLXFBConfig",
+ "GLXFBConfigSGIX" => "types::GLXFBConfigSGIX",
+ "GLXPbuffer" => "types::GLXPbuffer",
+ "GLXPbufferSGIX" => "types::GLXPbufferSGIX",
+ "GLXPixmap" => "types::GLXPixmap",
+ "GLXVideoCaptureDeviceNV" => "types::GLXVideoCaptureDeviceNV",
+ "GLXVideoDeviceNV" => "types::GLXVideoDeviceNV",
+ "GLXVideoSourceSGIX" => "types::GLXVideoSourceSGIX",
+ "GLXWindow" => "types::GLXWindow",
+ // "GLboolean" => "types::GLboolean",
+ // "GLenum" => "types::GLenum",
+ // "GLint" => "types::GLint",
+ // "GLsizei" => "types::GLsizei",
+ // "GLuint" => "types::GLuint",
+ "Pixmap" => "types::Pixmap",
+ "Status" => "types::Status",
+ "VLNode" => "types::VLNode",
+ "VLPath" => "types::VLPath",
+ "VLServer" => "types::VLServer",
+ "Window" => "types::Window",
+ "__GLXextFuncPtr" => "types::__GLXextFuncPtr",
+ "const GLXContext" => "const types::GLXContext",
+ "float" => "__gl_imports::raw::c_float",
+ "int" => "__gl_imports::raw::c_int",
+ "int64_t" => "i64",
+ "unsigned int" => "__gl_imports::raw::c_uint",
+ "unsigned long" => "__gl_imports::raw::c_ulong",
+ // "void " => "()",
+ "DMparams *" => "*mut types::DMparams",
+ "Display *" => "*mut types::Display",
+ "GLXFBConfig *" => "*mut types::GLXFBConfig",
+ "GLXFBConfigSGIX *" => "*mut types::GLXFBConfigSGIX",
+ "GLXHyperpipeConfigSGIX *" => "*mut types::GLXHyperpipeConfigSGIX",
+ "GLXHyperpipeNetworkSGIX *" => "*mut types::GLXHyperpipeNetworkSGIX",
+ "GLXVideoCaptureDeviceNV *" => "*mut types::GLXVideoCaptureDeviceNV",
+ "GLXVideoDeviceNV *" => "*mut types::GLXVideoDeviceNV",
+ // "GLuint *" => "*mut types::GLuint",
+ "XVisualInfo *" => "*mut types::XVisualInfo",
+ // "const GLubyte *" => "*GLubyte",
+ "const char *" => "*const __gl_imports::raw::c_char",
+ "const int *" => "*const __gl_imports::raw::c_int",
+ // "const void *" => "*const __gl_imports::raw::c_void",
+ "int *" => "*mut __gl_imports::raw::c_int",
+ "int32_t *" => "*mut i32",
+ "int64_t *" => "*mut i64",
+ "long *" => "*mut __gl_imports::raw::c_long",
+ "unsigned int *" => "*mut __gl_imports::raw::c_uint",
+ "unsigned long *" => "*mut __gl_imports::raw::c_ulong",
+ // "void *" => "*mut __gl_imports::raw::c_void",
+
+ // wgl.xml types
+ "BOOL" => "types::BOOL",
+ "DWORD" => "types::DWORD",
+ "FLOAT" => "types::FLOAT",
+ // "GLbitfield" => "types::GLbitfield",
+ // "GLboolean" => "types::GLboolean",
+ // "GLenum" => "types::GLenum",
+ // "GLfloat" => "types::GLfloat",
+ // "GLint" => "types::GLint",
+ // "GLsizei" => "types::GLsizei",
+ // "GLuint" => "types::GLuint",
+ // "GLushort" => "types::GLushort",
+ "HANDLE" => "types::HANDLE",
+ "HDC" => "types::HDC",
+ "HENHMETAFILE" => "types::HENHMETAFILE",
+ "HGLRC" => "types::HGLRC",
+ "HGPUNV" => "types::HGPUNV",
+ "HPBUFFERARB" => "types::HPBUFFERARB",
+ "HPBUFFEREXT" => "types::HPBUFFEREXT",
+ "HPVIDEODEV" => "types::HPVIDEODEV",
+ "HVIDEOINPUTDEVICENV" => "types::HVIDEOINPUTDEVICENV",
+ "HVIDEOOUTPUTDEVICENV" => "types::HVIDEOOUTPUTDEVICENV",
+ "INT" => "types::INT",
+ "INT64" => "types::INT64",
+ "LPCSTR" => "types::LPCSTR",
+ "LPGLYPHMETRICSFLOAT" => "types::LPGLYPHMETRICSFLOAT",
+ "LPVOID" => "types::LPVOID",
+ "PGPU_DEVICE" => "types::PGPU_DEVICE",
+ "PROC" => "types::PROC",
+ "UINT" => "types::UINT",
+ "VOID" => "types::VOID",
+ // "int " => "__gl_imports::raw::c_int",
+ // "unsigned int " => "__gl_imports::raw::c_uint",
+ // "void " => "()",
+ "BOOL *" => "*mut types::BOOL",
+ "DWORD *" => "*mut types::DWORD",
+ "FLOAT *" => "*mut types::FLOAT",
+ // "GLuint *" => "*mut types::GLuint",
+ "HANDLE *" => "*mut types::HANDLE",
+ "HGPUNV *" => "*mut types::HGPUNV",
+ "HPVIDEODEV *" => "*mut types::HPVIDEODEV",
+ "HVIDEOINPUTDEVICENV *" => "*mut types::HVIDEOINPUTDEVICENV",
+ "HVIDEOOUTPUTDEVICENV *" => "*mut types::HVIDEOOUTPUTDEVICENV",
+ "INT32 *" => "*mut types::INT32",
+ "INT64 *" => "*mut types::INT64",
+ "UINT *" => "*mut types::UINT",
+ "USHORT *" => "*mut types::USHORT",
+ "const COLORREF *" => "*const types::COLORREF",
+ "const DWORD *" => "*const types::DWORD",
+ "const FLOAT *" => "*const types::FLOAT",
+ // "const GLushort *" => "*const types::GLushort",
+ "const HANDLE *" => "*const types::HANDLE",
+ "const HGPUNV *" => "*const types::HGPUNV",
+ "const LAYERPLANEDESCRIPTOR *" => "*const types::LAYERPLANEDESCRIPTOR",
+ "const LPVOID *" => "*const types::LPVOID",
+ "const PIXELFORMATDESCRIPTOR *" => "*const types::IXELFORMATDESCRIPTOR",
+ "const USHORT *" => "*const types::USHORT",
+ // "const char *" => "*const __gl_imports::raw::c_char",
+ // "const int *" => "*const __gl_imports::raw::c_int",
+ "float *" => "*mut __gl_imports::raw::c_float",
+ // "int *" => "*mut __gl_imports::raw::c_int",
+ // "unsigned long *" => "*mut __gl_imports::raw::c_ulong",
+ // "void *" => "*mut __gl_imports::raw::c_void",
+
+ // elx.xml types
+ "khronos_utime_nanoseconds_t" => "types::khronos_utime_nanoseconds_t",
+ "khronos_uint64_t" => "types::khronos_uint64_t",
+ "khronos_ssize_t" => "types::khronos_ssize_t",
+ "EGLNativeDisplayType" => "types::EGLNativeDisplayType",
+ "EGLNativePixmapType" => "types::EGLNativePixmapType",
+ "EGLNativeWindowType" => "types::EGLNativeWindowType",
+ "EGLint" => "types::EGLint",
+ "EGLint *" => "*mut types::EGLint",
+ "const EGLint *" => "*const types::EGLint",
+ "NativeDisplayType" => "types::NativeDisplayType",
+ "NativePixmapType" => "types::NativePixmapType",
+ "NativeWindowType" => "types::NativeWindowType",
+ //"Bool" => "types::Bool",
+ "EGLBoolean" => "types::EGLBoolean",
+ "EGLenum" => "types::EGLenum",
+ "EGLAttribKHR" => "types::EGLAttribKHR",
+ "EGLAttrib" => "types::EGLAttrib",
+ "EGLAttrib *" => "*mut types::EGLAttrib",
+ "const EGLAttrib *" => "*const types::EGLAttrib",
+ "const EGLattrib *" => "*const types::EGLAttrib", // Due to a typo in khronos_api/api_angle/scripts/egl_angle_ext.xml - see brendanzab/gl-rs#491
+ "EGLConfig" => "types::EGLConfig",
+ "EGLConfig *" => "*mut types::EGLConfig",
+ "EGLContext" => "types::EGLContext",
+ "EGLDeviceEXT" => "types::EGLDeviceEXT",
+ "EGLDisplay" => "types::EGLDisplay",
+ "EGLSurface" => "types::EGLSurface",
+ "EGLClientBuffer" => "types::EGLClientBuffer",
+ "__eglMustCastToProperFunctionPointerType" => {
+ "types::__eglMustCastToProperFunctionPointerType"
+ },
+ "EGLImageKHR" => "types::EGLImageKHR",
+ "EGLImage" => "types::EGLImage",
+ "EGLOutputLayerEXT" => "types::EGLOutputLayerEXT",
+ "EGLOutputPortEXT" => "types::EGLOutputPortEXT",
+ "EGLSyncKHR" => "types::EGLSyncKHR",
+ "EGLSync" => "types::EGLSync",
+ "EGLTimeKHR" => "types::EGLTimeKHR",
+ "EGLTime" => "types::EGLTime",
+ "EGLSyncNV" => "types::EGLSyncNV",
+ "EGLTimeNV" => "types::EGLTimeNV",
+ "EGLuint64NV" => "types::EGLuint64NV",
+ "EGLStreamKHR" => "types::EGLStreamKHR",
+ "EGLuint64KHR" => "types::EGLuint64KHR",
+ "EGLNativeFileDescriptorKHR" => "types::EGLNativeFileDescriptorKHR",
+ "EGLsizeiANDROID" => "types::EGLsizeiANDROID",
+ "EGLSetBlobFuncANDROID" => "types::EGLSetBlobFuncANDROID",
+ "EGLGetBlobFuncANDROID" => "types::EGLGetBlobFuncANDROID",
+ "EGLClientPixmapHI" => "types::EGLClientPixmapHI",
+ "struct EGLClientPixmapHI *" => "*const types::EGLClientPixmapHI",
+ "const EGLAttribKHR *" => "*const types::EGLAttribKHR",
+ "const EGLuint64KHR *" => "*const types::EGLuint64KHR",
+ "EGLAttribKHR *" => "*mut types::EGLAttribKHR",
+ "EGLDeviceEXT *" => "*mut types::EGLDeviceEXT",
+ "EGLNativeDisplayType *" => "*mut types::EGLNativeDisplayType",
+ "EGLNativePixmapType *" => "*mut types::EGLNativePixmapType",
+ "EGLNativeWindowType *" => "*mut types::EGLNativeWindowType",
+ "EGLOutputLayerEXT *" => "*mut types::EGLOutputLayerEXT",
+ "EGLTimeKHR *" => "*mut types::EGLTimeKHR",
+ "EGLOutputPortEXT *" => "*mut types::EGLOutputPortEXT",
+ "EGLuint64KHR *" => "*mut types::EGLuint64KHR",
+ "const struct AHardwareBuffer *" => "*const __gl_imports::raw::c_void", // humm
+
+ "GLeglClientBufferEXT" => "types::GLeglClientBufferEXT",
+ "GLVULKANPROCNV" => "types::GLVULKANPROCNV",
+ "EGLDEBUGPROCKHR" => "types::EGLDEBUGPROCKHR",
+ "EGLObjectKHR" => "types::EGLObjectKHR",
+ "EGLLabelKHR" => "types::EGLLabelKHR",
+ "EGLnsecsANDROID" => "types::EGLnsecsANDROID",
+ "EGLnsecsANDROID *" => "*mut types::EGLnsecsANDROID",
+ "EGLBoolean *" => "*mut types::EGLBoolean",
+
+ // failure
+ _ => panic!("Type conversion not implemented for `{}`", ty.as_ref()),
+ };
+
+ Cow::Borrowed(ty)
+}
+
+#[cfg(test)]
+mod tests {
+ mod underscore_numeric_prefix {
+ use registry::parse;
+
+ #[test]
+ fn test_numeric_prefix() {
+ assert_eq!(parse::underscore_numeric_prefix("3"), "_3");
+ assert_eq!(parse::underscore_numeric_prefix("123_FOO"), "_123_FOO");
+ }
+
+ #[test]
+ fn test_non_numeric_prefix() {
+ assert_eq!(parse::underscore_numeric_prefix(""), "");
+ assert_eq!(parse::underscore_numeric_prefix("A"), "A");
+ assert_eq!(parse::underscore_numeric_prefix("FOO"), "FOO");
+ }
+ }
+
+ mod underscore_keyword {
+ use registry::parse;
+
+ #[test]
+ fn test_keyword() {
+ assert_eq!(parse::underscore_keyword("in".to_string()), "in_");
+ assert_eq!(parse::underscore_keyword("ref".to_string()), "ref_");
+ assert_eq!(parse::underscore_keyword("type".to_string()), "type_");
+ }
+
+ #[test]
+ fn test_non_keyword() {
+ assert_eq!(parse::underscore_keyword("foo".to_string()), "foo");
+ assert_eq!(parse::underscore_keyword("bar".to_string()), "bar");
+ }
+ }
+ mod make_enum {
+ use registry::parse;
+
+ #[test]
+ fn test_cast_0() {
+ let e = parse::make_enum(
+ "FOO".to_string(),
+ None,
+ "((EGLint)-1)".to_string(),
+ Some("BAR".to_string()),
+ );
+ assert_eq!(e.ident, "FOO");
+ assert_eq!((&*e.ty, &*e.value), ("EGLint", "-1"));
+ assert_eq!(e.alias, Some("BAR".to_string()));
+ }
+
+ #[test]
+ fn test_cast_1() {
+ let e = parse::make_enum(
+ "FOO".to_string(),
+ None,
+ "((EGLint)(-1))".to_string(),
+ Some("BAR".to_string()),
+ );
+ assert_eq!(e.ident, "FOO");
+ assert_eq!((&*e.ty, &*e.value), ("EGLint", "(-1)"));
+ assert_eq!(e.alias, Some("BAR".to_string()));
+ }
+
+ #[test]
+ fn test_no_type() {
+ let e = parse::make_enum(
+ "FOO".to_string(),
+ None,
+ "value".to_string(),
+ Some("BAR".to_string()),
+ );
+ assert_eq!(e.ident, "FOO");
+ assert_eq!(e.value, "value");
+ assert_eq!(e.alias, Some("BAR".to_string()));
+ assert_eq!(e.ty, "GLenum");
+ assert_eq!(e.cast, false);
+ }
+
+ #[test]
+ fn test_u() {
+ let e = parse::make_enum(
+ "FOO".to_string(),
+ Some("u".to_string()),
+ String::new(),
+ None,
+ );
+ assert_eq!(e.ty, "GLuint");
+ }
+
+ #[test]
+ fn test_ull() {
+ let e = parse::make_enum(
+ "FOO".to_string(),
+ Some("ull".to_string()),
+ String::new(),
+ None,
+ );
+ assert_eq!(e.ty, "GLuint64");
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_unknown_type() {
+ parse::make_enum(
+ "FOO".to_string(),
+ Some("blargh".to_string()),
+ String::new(),
+ None,
+ );
+ }
+
+ #[test]
+ fn test_value_str() {
+ let e = parse::make_enum("FOO".to_string(), None, "\"hi\"".to_string(), None);
+ assert_eq!(e.ty, "&'static str");
+ }
+
+ #[test]
+ fn test_ident_true() {
+ let e = parse::make_enum("TRUE".to_string(), None, String::new(), None);
+ assert_eq!(e.ty, "GLboolean");
+ }
+
+ #[test]
+ fn test_ident_false() {
+ let e = parse::make_enum("FALSE".to_string(), None, String::new(), None);
+ assert_eq!(e.ty, "GLboolean");
+ }
+ }
+
+ mod make_egl_enum {
+ use registry::parse;
+
+ #[test]
+ fn test_cast_egl() {
+ let e = parse::make_egl_enum(
+ "FOO".to_string(),
+ None,
+ "EGL_CAST(EGLint,-1)".to_string(),
+ Some("BAR".to_string()),
+ );
+ assert_eq!(e.ident, "FOO");
+ assert_eq!((&*e.ty, &*e.value), ("EGLint", "-1"));
+ assert_eq!(e.alias, Some("BAR".to_string()));
+ }
+
+ #[test]
+ fn test_ident_true() {
+ let e = parse::make_egl_enum("TRUE".to_string(), None, "1234".to_string(), None);
+ assert_eq!(e.ty, "EGLBoolean");
+ }
+
+ #[test]
+ fn test_ident_false() {
+ let e = parse::make_egl_enum("FALSE".to_string(), None, "1234".to_string(), None);
+ assert_eq!(e.ty, "EGLBoolean");
+ }
+
+ #[test]
+ fn test_ull() {
+ let e = parse::make_egl_enum(
+ "FOO".to_string(),
+ Some("ull".to_string()),
+ "1234".to_string(),
+ None,
+ );
+ assert_eq!(e.ty, "EGLuint64KHR");
+ }
+
+ #[test]
+ fn test_negative_value() {
+ let e = parse::make_egl_enum("FOO".to_string(), None, "-1".to_string(), None);
+ assert_eq!(e.ty, "EGLint");
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_unknown_type() {
+ parse::make_egl_enum(
+ "FOO".to_string(),
+ Some("blargh".to_string()),
+ String::new(),
+ None,
+ );
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_unknown_value() {
+ parse::make_egl_enum("FOO".to_string(), None, "a".to_string(), None);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_empty_value() {
+ parse::make_egl_enum("FOO".to_string(), None, String::new(), None);
+ }
+ }
+
+ mod parse_event {
+ mod from_xml {
+ use xml::attribute::OwnedAttribute;
+ use xml::common::XmlVersion;
+ use xml::name::OwnedName;
+ use xml::namespace::Namespace;
+ use xml::reader::XmlEvent;
+
+ use registry::parse::{Attribute, ParseEvent};
+
+ #[test]
+ fn test_start_event() {
+ let given = XmlEvent::StartElement {
+ name: OwnedName::local("element"),
+ attributes: vec![
+ OwnedAttribute::new(OwnedName::local("attr1"), "val1"),
+ OwnedAttribute::new(OwnedName::local("attr2"), "val2"),
+ ],
+ namespace: Namespace::empty(),
+ };
+ let expected = ParseEvent::Start(
+ "element".to_string(),
+ vec![
+ Attribute::new("attr1", "val1"),
+ Attribute::new("attr2", "val2"),
+ ],
+ );
+ assert_eq!(ParseEvent::from_xml(given), Some(expected));
+ }
+
+ #[test]
+ fn test_end_element() {
+ let given = XmlEvent::EndElement {
+ name: OwnedName::local("element"),
+ };
+ let expected = ParseEvent::End("element".to_string());
+ assert_eq!(ParseEvent::from_xml(given), Some(expected));
+ }
+
+ #[test]
+ fn test_characters() {
+ let given = XmlEvent::Characters("text".to_string());
+ let expected = ParseEvent::Text("text".to_string());
+ assert_eq!(ParseEvent::from_xml(given), Some(expected));
+ }
+
+ #[test]
+ fn test_start_document() {
+ let given = XmlEvent::StartDocument {
+ version: XmlVersion::Version10,
+ encoding: "".to_string(),
+ standalone: None,
+ };
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+
+ #[test]
+ fn test_end_document() {
+ let given = XmlEvent::EndDocument;
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+
+ #[test]
+ fn test_processing_instruction() {
+ let given = XmlEvent::ProcessingInstruction {
+ name: "".to_string(),
+ data: None,
+ };
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+
+ #[test]
+ fn test_cdata() {
+ let given = XmlEvent::CData("CData".to_string());
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+
+ #[test]
+ fn test_comment() {
+ let given = XmlEvent::Comment("Comment".to_string());
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+
+ #[test]
+ fn test_whitespace() {
+ let given = XmlEvent::Whitespace("Whitespace".to_string());
+ assert_eq!(ParseEvent::from_xml(given), None);
+ }
+ }
+ }
+}