├── .gitignore ├── .gitmodules ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md ├── gl ├── Cargo.toml ├── README.md ├── build.rs ├── examples │ ├── basic.rs │ └── triangle.rs └── src │ └── lib.rs ├── gl_generator ├── Cargo.toml ├── README.md ├── generators │ ├── debug_struct_gen.rs │ ├── global_gen.rs │ ├── mod.rs │ ├── static_gen.rs │ ├── static_struct_gen.rs │ ├── struct_gen.rs │ └── templates │ │ └── types │ │ ├── egl.rs │ │ ├── gl.rs │ │ ├── glx.rs │ │ └── wgl.rs ├── lib.rs └── registry │ ├── mod.rs │ └── parse.rs ├── khronos_api ├── Cargo.toml ├── README.md ├── build.rs └── src │ └── lib.rs ├── rustfmt.toml ├── tests ├── test_add_registries │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── test_gen_symbols │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── test_no_warnings │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── test_symbols │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── test_unstable_api │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── test_webgl_stdweb │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs └── test_with_extensions │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs ├── webgl_generator ├── Cargo.toml ├── README.md ├── lib.rs ├── utils.rs ├── webgl_generators │ ├── mod.rs │ └── stdweb_gen.rs └── webgl_registry │ ├── mod.rs │ ├── named.rs │ ├── registry.rs │ └── types.rs └── webgl_stdweb ├── Cargo.toml ├── README.md ├── build.rs └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_store 2 | target 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "khronos_api/api"] 2 | path = khronos_api/api 3 | url = https://github.com/KhronosGroup/OpenGL-Registry.git 4 | [submodule "khronos_api/api_egl"] 5 | path = khronos_api/api_egl 6 | url = https://github.com/KhronosGroup/EGL-Registry.git 7 | [submodule "khronos_api/api_webgl"] 8 | path = khronos_api/api_webgl 9 | url = https://github.com/KhronosGroup/WebGL.git 10 | [submodule "khronos_api/api_angle"] 11 | path = khronos_api/api_angle 12 | url = https://github.com/google/angle.git 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | rust: 4 | - nightly 5 | - beta 6 | - stable 7 | 8 | cache: cargo 9 | 10 | script: 11 | - travis_wait cargo build --all 12 | - travis_wait cargo test --all 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "gl", 4 | "gl_generator", 5 | "webgl_stdweb", 6 | "webgl_generator", 7 | "tests/test_add_registries", 8 | "tests/test_gen_symbols", 9 | "tests/test_no_warnings", 10 | "tests/test_symbols", 11 | "tests/test_unstable_api", 12 | "tests/test_with_extensions", 13 | "tests/test_webgl_stdweb", 14 | "khronos_api", 15 | ] 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gl-rs 2 | 3 | [![Build Status](https://travis-ci.org/brendanzab/gl-rs.svg?branch=master)](https://travis-ci.org/brendanzab/gl-rs) 4 | 5 | ## Overview 6 | 7 | This repository contains the necessary building blocks for OpenGL wrapper 8 | libraries. For more information on each crate, see their respective READMEs 9 | listed below. 10 | 11 | The following crates are contained in this repository: 12 | 13 | ### gl 14 | 15 | [![Version](https://img.shields.io/crates/v/gl.svg)](https://crates.io/crates/gl) [![License](https://img.shields.io/crates/l/gl.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) [![Downloads](https://img.shields.io/crates/d/gl.svg)](https://crates.io/crates/gl) 16 | 17 | [README](https://github.com/brendanzab/gl-rs/tree/master/gl) 18 | 19 | An OpenGL function pointer loader for the Rust Programming Language. 20 | 21 | ```toml 22 | [dependencies] 23 | gl = "0.14.0" 24 | ``` 25 | 26 | ### gl_generator 27 | 28 | [![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) 29 | 30 | [README](https://github.com/brendanzab/gl-rs/tree/master/gl_generator) 31 | 32 | Code generators for creating bindings to the Khronos OpenGL APIs. 33 | 34 | ```toml 35 | [build-dependencies] 36 | gl_generator = "0.14.0" 37 | ``` 38 | 39 | ### khronos_api 40 | 41 | [![Version](https://img.shields.io/crates/v/khronos_api.svg)](https://crates.io/crates/khronos_api) [![License](https://img.shields.io/crates/l/khronos_api.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) [![Downloads](https://img.shields.io/crates/d/khronos_api.svg)](https://crates.io/crates/khronos_api) 42 | 43 | [README](https://github.com/brendanzab/gl-rs/tree/master/khronos_api) 44 | 45 | The Khronos XML API Registry, exposed as byte string constants. 46 | 47 | ```toml 48 | [build-dependencies] 49 | khronos_api = "3.1.0" 50 | ``` 51 | 52 | #### Compiling from source 53 | 54 | `khronos_api` makes use of git submodules. You will need to initialize these before building: 55 | 56 | ```sh 57 | git submodule update --init 58 | ``` 59 | 60 | ### webgl_generator 61 | 62 | [![Version](https://img.shields.io/crates/v/webgl_generator.svg)](https://crates.io/crates/webgl_generator) [![License](https://img.shields.io/crates/l/webgl_generator.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) [![Downloads](https://img.shields.io/crates/d/webgl_generator.svg)](https://crates.io/crates/webgl_generator) 63 | 64 | [README](https://github.com/brendanzab/gl-rs/tree/master/webgl_generator) 65 | 66 | Code generators for creating bindings to the WebGL APIs. 67 | 68 | ```toml 69 | [build-dependencies] 70 | webgl_generator = "0.2.0" 71 | ``` 72 | 73 | ### webgl-stdweb 74 | 75 | [![Version](https://img.shields.io/crates/v/webgl_stdweb.svg)](https://crates.io/crates/webgl_stdweb) [![License](https://img.shields.io/crates/l/webgl_stdweb.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) [![Downloads](https://img.shields.io/crates/d/webgl_stdweb.svg)](https://crates.io/crates/webgl_stdweb) 76 | 77 | [README](https://github.com/brendanzab/gl-rs/tree/master/webgl_stdweb) 78 | 79 | WebGL bindings using stdweb 80 | 81 | ```toml 82 | [build-dependencies] 83 | webgl_stdweb = "0.3.0" 84 | ``` 85 | -------------------------------------------------------------------------------- /gl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gl" 3 | version = "0.14.0" 4 | authors = [ 5 | "Brendan Zabarauskas ", 6 | "Corey Richardson", 7 | "Arseny Kapoulkine", 8 | ] 9 | description = "OpenGL bindings" 10 | license = "Apache-2.0" 11 | build = "build.rs" 12 | documentation = "https://docs.rs/gl" 13 | homepage = "https://github.com/brendanzab/gl-rs/" 14 | repository = "https://github.com/brendanzab/gl-rs/" 15 | readme = "README.md" 16 | categories = ["api-bindings", "rendering::graphics-api"] 17 | keywords = ["gl", "egl", "opengl", "khronos"] 18 | 19 | [build-dependencies] 20 | gl_generator = { version = "0.14.0", path = "../gl_generator" } 21 | 22 | [dev-dependencies] 23 | glutin = "0.24" 24 | -------------------------------------------------------------------------------- /gl/README.md: -------------------------------------------------------------------------------- 1 | # gl-rs 2 | 3 | [![Version](https://img.shields.io/crates/v/gl.svg)](https://crates.io/crates/gl) 4 | [![License](https://img.shields.io/crates/l/gl.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) 5 | [![Downloads](https://img.shields.io/crates/d/gl.svg)](https://crates.io/crates/gl) 6 | 7 | An OpenGL function pointer loader for the Rust Programming Language. 8 | 9 | ```toml 10 | [dependencies] 11 | gl = "0.14.0" 12 | ``` 13 | 14 | ## Basic usage 15 | 16 | You can import the pointer style loader and type aliases like so: 17 | 18 | ```rust 19 | extern crate gl; 20 | // include the OpenGL type aliases 21 | use gl::types::*; 22 | ``` 23 | 24 | You must load the function pointers into their respective function pointers 25 | using the `load_with` function. You must supply a loader function from your 26 | context library. This is how it would look using [glfw-rs](https://github.com/PistonDevelopers/glfw-rs): 27 | 28 | ```rust 29 | // the supplied function must be of the type: 30 | // `&fn(symbol: &'static str) -> *const std::os::raw::c_void` 31 | // `window` is a glfw::Window 32 | gl::load_with(|s| window.get_proc_address(s) as *const _); 33 | 34 | // loading a specific function pointer 35 | gl::Viewport::load_with(|s| window.get_proc_address(s) as *const _); 36 | ``` 37 | 38 | Calling a function that has not been loaded will result in a failure like: 39 | `panic!("gl::Viewport was not loaded")`, which avoids a segfault. This feature 40 | does not cause any run time overhead because the failing functions are 41 | assigned only when `load_with` is called. 42 | 43 | All OpenGL function calls are `unsafe`. 44 | 45 | ```rust 46 | // accessing an enum 47 | gl::TEXTURE_2D; 48 | 49 | // calling a function 50 | unsafe { gl::DrawArrays(gl::TRIANGLES, 0, 3) }; 51 | ``` 52 | 53 | Each function pointer has an associated boolean value allowing you to 54 | check if a function has been loaded at run time. The function accesses a 55 | corresponding global boolean that is set when `load_with` is called, so there 56 | shouldn't be much overhead. 57 | 58 | ```rust 59 | if gl::Viewport::is_loaded() { 60 | // do something... 61 | } 62 | ``` 63 | -------------------------------------------------------------------------------- /gl/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; 18 | use std::env; 19 | use std::fs::File; 20 | use std::path::Path; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap(); 25 | 26 | Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []) 27 | .write_bindings(GlobalGenerator, &mut file) 28 | .unwrap(); 29 | } 30 | -------------------------------------------------------------------------------- /gl/examples/basic.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl; 16 | extern crate glutin; 17 | 18 | fn main() { 19 | let event_loop = glutin::event_loop::EventLoop::new(); 20 | let window = glutin::window::WindowBuilder::new(); 21 | let gl_window = glutin::ContextBuilder::new() 22 | .build_windowed(window, &event_loop) 23 | .unwrap(); 24 | 25 | // It is essential to make the context current before calling `gl::load_with`. 26 | let gl_window = unsafe { gl_window.make_current().unwrap() }; 27 | 28 | // Load the OpenGL function pointers 29 | gl::load_with(|symbol| gl_window.get_proc_address(symbol)); 30 | 31 | event_loop.run(move |event, _, control_flow| { 32 | use glutin::event::{Event, WindowEvent}; 33 | use glutin::event_loop::ControlFlow; 34 | *control_flow = ControlFlow::Wait; 35 | match event { 36 | Event::LoopDestroyed => return, 37 | Event::WindowEvent { event, .. } => match event { 38 | WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit, 39 | _ => (), 40 | }, 41 | Event::RedrawRequested(_) => { 42 | unsafe { 43 | gl::ClearColor(0.3, 0.3, 0.3, 1.0); 44 | gl::Clear(gl::COLOR_BUFFER_BIT); 45 | } 46 | gl_window.swap_buffers().unwrap(); 47 | }, 48 | _ => (), 49 | } 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /gl/examples/triangle.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl; 16 | extern crate glutin; 17 | 18 | use gl::types::*; 19 | use std::ffi::CString; 20 | use std::mem; 21 | use std::ptr; 22 | use std::str; 23 | 24 | // Vertex data 25 | static VERTEX_DATA: [GLfloat; 6] = [0.0, 0.5, 0.5, -0.5, -0.5, -0.5]; 26 | 27 | // Shader sources 28 | static VS_SRC: &'static str = " 29 | #version 150 30 | in vec2 position; 31 | 32 | void main() { 33 | gl_Position = vec4(position, 0.0, 1.0); 34 | }"; 35 | 36 | static FS_SRC: &'static str = " 37 | #version 150 38 | out vec4 out_color; 39 | 40 | void main() { 41 | out_color = vec4(1.0, 1.0, 1.0, 1.0); 42 | }"; 43 | 44 | fn compile_shader(src: &str, ty: GLenum) -> GLuint { 45 | let shader; 46 | unsafe { 47 | shader = gl::CreateShader(ty); 48 | // Attempt to compile the shader 49 | let c_str = CString::new(src.as_bytes()).unwrap(); 50 | gl::ShaderSource(shader, 1, &c_str.as_ptr(), ptr::null()); 51 | gl::CompileShader(shader); 52 | 53 | // Get the compile status 54 | let mut status = gl::FALSE as GLint; 55 | gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status); 56 | 57 | // Fail on error 58 | if status != (gl::TRUE as GLint) { 59 | let mut len = 0; 60 | gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len); 61 | let mut buf = Vec::with_capacity(len as usize); 62 | buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character 63 | gl::GetShaderInfoLog( 64 | shader, 65 | len, 66 | ptr::null_mut(), 67 | buf.as_mut_ptr() as *mut GLchar, 68 | ); 69 | panic!( 70 | "{}", 71 | str::from_utf8(&buf) 72 | .ok() 73 | .expect("ShaderInfoLog not valid utf8") 74 | ); 75 | } 76 | } 77 | shader 78 | } 79 | 80 | fn link_program(vs: GLuint, fs: GLuint) -> GLuint { 81 | unsafe { 82 | let program = gl::CreateProgram(); 83 | gl::AttachShader(program, vs); 84 | gl::AttachShader(program, fs); 85 | gl::LinkProgram(program); 86 | // Get the link status 87 | let mut status = gl::FALSE as GLint; 88 | gl::GetProgramiv(program, gl::LINK_STATUS, &mut status); 89 | 90 | // Fail on error 91 | if status != (gl::TRUE as GLint) { 92 | let mut len: GLint = 0; 93 | gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len); 94 | let mut buf = Vec::with_capacity(len as usize); 95 | buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character 96 | gl::GetProgramInfoLog( 97 | program, 98 | len, 99 | ptr::null_mut(), 100 | buf.as_mut_ptr() as *mut GLchar, 101 | ); 102 | panic!( 103 | "{}", 104 | str::from_utf8(&buf) 105 | .ok() 106 | .expect("ProgramInfoLog not valid utf8") 107 | ); 108 | } 109 | program 110 | } 111 | } 112 | 113 | fn main() { 114 | let event_loop = glutin::event_loop::EventLoop::new(); 115 | let window = glutin::window::WindowBuilder::new(); 116 | let gl_window = glutin::ContextBuilder::new() 117 | .build_windowed(window, &event_loop) 118 | .unwrap(); 119 | 120 | // It is essential to make the context current before calling `gl::load_with`. 121 | let gl_window = unsafe { gl_window.make_current() }.unwrap(); 122 | 123 | // Load the OpenGL function pointers 124 | gl::load_with(|symbol| gl_window.get_proc_address(symbol)); 125 | 126 | // Create GLSL shaders 127 | let vs = compile_shader(VS_SRC, gl::VERTEX_SHADER); 128 | let fs = compile_shader(FS_SRC, gl::FRAGMENT_SHADER); 129 | let program = link_program(vs, fs); 130 | 131 | let mut vao = 0; 132 | let mut vbo = 0; 133 | 134 | unsafe { 135 | // Create Vertex Array Object 136 | gl::GenVertexArrays(1, &mut vao); 137 | gl::BindVertexArray(vao); 138 | 139 | // Create a Vertex Buffer Object and copy the vertex data to it 140 | gl::GenBuffers(1, &mut vbo); 141 | gl::BindBuffer(gl::ARRAY_BUFFER, vbo); 142 | gl::BufferData( 143 | gl::ARRAY_BUFFER, 144 | (VERTEX_DATA.len() * mem::size_of::()) as GLsizeiptr, 145 | mem::transmute(&VERTEX_DATA[0]), 146 | gl::STATIC_DRAW, 147 | ); 148 | 149 | // Use shader program 150 | gl::UseProgram(program); 151 | gl::BindFragDataLocation(program, 0, CString::new("out_color").unwrap().as_ptr()); 152 | 153 | // Specify the layout of the vertex data 154 | let pos_attr = gl::GetAttribLocation(program, CString::new("position").unwrap().as_ptr()); 155 | gl::EnableVertexAttribArray(pos_attr as GLuint); 156 | gl::VertexAttribPointer( 157 | pos_attr as GLuint, 158 | 2, 159 | gl::FLOAT, 160 | gl::FALSE as GLboolean, 161 | 0, 162 | ptr::null(), 163 | ); 164 | } 165 | 166 | event_loop.run(move |event, _, control_flow| { 167 | use glutin::event::{Event, WindowEvent}; 168 | use glutin::event_loop::ControlFlow; 169 | *control_flow = ControlFlow::Wait; 170 | match event { 171 | Event::LoopDestroyed => return, 172 | Event::WindowEvent { event, .. } => match event { 173 | WindowEvent::CloseRequested => { 174 | // Cleanup 175 | unsafe { 176 | gl::DeleteProgram(program); 177 | gl::DeleteShader(fs); 178 | gl::DeleteShader(vs); 179 | gl::DeleteBuffers(1, &vbo); 180 | gl::DeleteVertexArrays(1, &vao); 181 | } 182 | *control_flow = ControlFlow::Exit 183 | }, 184 | _ => (), 185 | }, 186 | Event::RedrawRequested(_) => { 187 | unsafe { 188 | // Clear the screen to black 189 | gl::ClearColor(0.3, 0.3, 0.3, 1.0); 190 | gl::Clear(gl::COLOR_BUFFER_BIT); 191 | // Draw a triangle from the 3 vertices 192 | gl::DrawArrays(gl::TRIANGLES, 0, 3); 193 | } 194 | gl_window.swap_buffers().unwrap(); 195 | }, 196 | _ => (), 197 | } 198 | }); 199 | } 200 | -------------------------------------------------------------------------------- /gl/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! # Usage 16 | //! 17 | //! You can import the pointer style loader and type aliases like so: 18 | //! 19 | //! ~~~no_run 20 | //! # #![allow(unused_imports)] 21 | //! extern crate gl; 22 | //! # fn main() { 23 | //! // include the OpenGL type aliases 24 | //! use gl::types::*; 25 | //! # } 26 | //! ~~~ 27 | //! 28 | //! You must load the function pointers into their respective function pointers 29 | //! using the `load_with` function. You must supply a loader function from your 30 | //! context library. This is how it would look using [glfw-rs](https://github.com/PistonDevelopers/glfw-rs): 31 | //! 32 | //! ~~~ignore 33 | //! // the supplied function must be of the type: 34 | //! // `&fn(symbol: &'static str) -> *const std::os::raw::c_void` 35 | //! // `window` is a glfw::Window 36 | //! gl::load_with(|s| window.get_proc_address(s) as *const _); 37 | //! 38 | //! // loading a specific function pointer 39 | //! gl::Viewport::load_with(|s| window.get_proc_address(s) as *const _); 40 | //! ~~~ 41 | //! 42 | //! Calling a function that has not been loaded will result in a failure like: 43 | //! `panic!("gl::Viewport was not loaded")`, which avoids a segfault. This feature 44 | //! does not cause any run time overhead because the failing functions are 45 | //! assigned only when `load_with` is called. 46 | //! 47 | //! All OpenGL function calls are `unsafe`. 48 | //! 49 | //! ~~~no_run 50 | //! # #![allow(path_statement)] 51 | //! # extern crate gl; 52 | //! # fn main() { 53 | //! // accessing an enum 54 | //! gl::TEXTURE_2D; 55 | //! 56 | //! // calling a function 57 | //! unsafe { gl::DrawArrays(gl::TRIANGLES, 0, 3) }; 58 | //! # } 59 | //! ~~~ 60 | //! 61 | //! Each function pointer has an associated boolean value allowing you to 62 | //! check if a function has been loaded at run time. The function accesses a 63 | //! corresponding global boolean that is set when `load_with` is called, so there 64 | //! shouldn't be much overhead. 65 | //! 66 | //! ~~~no_run 67 | //! if gl::Viewport::is_loaded() { 68 | //! // do something... 69 | //! } 70 | //! ~~~ 71 | //! 72 | 73 | #![crate_name = "gl"] 74 | #![crate_type = "lib"] 75 | 76 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 77 | -------------------------------------------------------------------------------- /gl_generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gl_generator" 3 | version = "0.14.1" 4 | authors = [ 5 | "Brendan Zabarauskas ", 6 | "Corey Richardson", 7 | "Arseny Kapoulkine", 8 | ] 9 | description = "Code generators for creating bindings to the Khronos OpenGL APIs." 10 | license = "Apache-2.0" 11 | documentation = "https://docs.rs/gl_generator" 12 | homepage = "https://github.com/brendanzab/gl-rs/" 13 | repository = "https://github.com/brendanzab/gl-rs/" 14 | readme = "README.md" 15 | categories = ["api-bindings", "rendering::graphics-api"] 16 | keywords = ["gl", "egl", "opengl", "khronos"] 17 | 18 | [lib] 19 | name = "gl_generator" 20 | path = "lib.rs" 21 | 22 | [features] 23 | unstable_generator_utils = [] 24 | 25 | [dependencies] 26 | khronos_api = { version = "3.2.0", path = "../khronos_api" } 27 | log = "0.4" 28 | xml-rs = "0.8" 29 | -------------------------------------------------------------------------------- /gl_generator/README.md: -------------------------------------------------------------------------------- 1 | # gl_generator 2 | 3 | [![Version](https://img.shields.io/crates/v/gl_generator.svg)](https://crates.io/crates/gl_generator) 4 | [![License](https://img.shields.io/crates/l/gl_generator.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) 5 | [![Downloads](https://img.shields.io/crates/d/gl_generator.svg)](https://crates.io/crates/gl_generator) 6 | 7 | Code generators for creating bindings to the Khronos OpenGL APIs. 8 | 9 | ## Usage 10 | 11 | If you need a specific version of OpenGL, or you need a different API 12 | (OpenGL ES, EGL, WGL, GLX), or if you need certain extensions, you should use 13 | the `gl_generator` crate. 14 | 15 | See [gfx_gl](https://github.com/gfx-rs/gfx_gl) for an example of using a 16 | custom OpenGL loader for a project. 17 | 18 | Add this to your `Cargo.toml`: 19 | 20 | ```toml 21 | [build-dependencies] 22 | gl_generator = "0.14.0" 23 | ``` 24 | 25 | Under the `[package]` section, add: 26 | 27 | ```toml 28 | build = "build.rs" 29 | ``` 30 | 31 | Create a `build.rs` to pull your specific version/API: 32 | 33 | ```rust 34 | extern crate gl_generator; 35 | 36 | use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; 37 | use std::env; 38 | use std::fs::File; 39 | use std::path::Path; 40 | 41 | fn main() { 42 | let dest = env::var("OUT_DIR").unwrap(); 43 | let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap(); 44 | 45 | Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []) 46 | .write_bindings(GlobalGenerator, &mut file) 47 | .unwrap(); 48 | } 49 | ``` 50 | 51 | Then use it like this: 52 | 53 | ```rust 54 | mod gl { 55 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 56 | } 57 | 58 | /// Simple loading example 59 | fn main() { 60 | let window = ...; 61 | 62 | // Assuming `window` is a glfw::Window, made current 63 | gl::load_with(|s| window.get_proc_address(s) as *const _); 64 | } 65 | ``` 66 | 67 | The `build.rs` file will generate all the OpenGL functions in a file named, 68 | `bindings.rs` plus all enumerations, and all types in the `types` submodule. 69 | 70 | ## Generator types 71 | 72 | ### Global generator 73 | 74 | The global generator is the one used by default by the `gl` crate. See the 75 | [README](https://github.com/brendanzab/gl-rs/tree/master/gl) for more details. 76 | 77 | ### Struct generator 78 | 79 | The struct generator is a cleaner alternative to the global generator. 80 | 81 | The main difference is that you must call `gl::Gl::load_with` instead of 82 | `gl::load_with`, and this functions returns a struct of type `Gl`. The OpenGL 83 | functions are not static functions but member functions in this `Gl` struct. 84 | This is important when the GL functions are associated with the current 85 | context, as is true on Windows. 86 | 87 | The enumerations and types are still static and available in a similar way as 88 | in the global generator. 89 | 90 | ### Static generator 91 | 92 | The static generator generates plain old bindings. You don't need to load the 93 | functions. 94 | 95 | This generator should only be used only if the platform you are compiling for 96 | is guaranteed to support the requested API. Otherwise you will get a 97 | compilation error. 98 | For example, you can use it for WGL and OpenGL 1.1 on Windows or GLX and 99 | OpenGL 1.3 on Linux, because Windows and Linux are guaranteed to provide 100 | implementations for these APIs. 101 | 102 | You will need to manually provide the linkage. For example to use WGL or 103 | OpenGL 1.1 on Windows, you will need to add 104 | `#[link="OpenGL32.lib"] extern {}` somewhere in your code. 105 | 106 | ### Custom Generators 107 | 108 | The `gl_generator` can be extended with custom generators. This is a niche 109 | feature useful only in very rare cases. To create a custom generator, implement 110 | the `gl_generator::Generator` trait. See the source of the 111 | `gl_generator::generators` module for examples. 112 | 113 | Various utility functions are provided in the `generators` module, but the api 114 | is unstable, so it has been placed behind a feature flag. In access these 115 | functions, you will need to add the `"unstable_generator_utils"` feature to 116 | your `Cargo.toml`: 117 | 118 | ```toml 119 | [build-dependencies.gl_generator] 120 | version = "0.14.0" 121 | features = ["unstable_generator_utils"] 122 | ``` 123 | 124 | ## Extra features 125 | 126 | The global and struct generators will attempt to use fallbacks functions when 127 | they are available. For example, if `glGenFramebuffers` cannot be loaded it will 128 | also attempt to load `glGenFramebuffersEXT` as a fallback. 129 | -------------------------------------------------------------------------------- /gl_generator/generators/debug_struct_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::Registry; 16 | use std::io; 17 | 18 | #[allow(missing_copy_implementations)] 19 | pub struct DebugStructGenerator; 20 | 21 | impl super::Generator for DebugStructGenerator { 22 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 23 | where 24 | W: io::Write, 25 | { 26 | write_header(dest)?; 27 | write_type_aliases(registry, dest)?; 28 | write_enums(registry, dest)?; 29 | write_fnptr_struct_def(dest)?; 30 | write_panicking_fns(registry, dest)?; 31 | write_struct(registry, dest)?; 32 | write_impl(registry, dest)?; 33 | Ok(()) 34 | } 35 | } 36 | 37 | /// Creates a `__gl_imports` module which contains all the external symbols that we need for the 38 | /// bindings. 39 | fn write_header(dest: &mut W) -> io::Result<()> 40 | where 41 | W: io::Write, 42 | { 43 | writeln!( 44 | dest, 45 | r#" 46 | mod __gl_imports {{ 47 | pub use std::mem; 48 | pub use std::marker::Send; 49 | pub use std::os::raw; 50 | }} 51 | "# 52 | ) 53 | } 54 | 55 | /// Creates a `types` module which contains all the type aliases. 56 | /// 57 | /// See also `generators::gen_types`. 58 | fn write_type_aliases(registry: &Registry, dest: &mut W) -> io::Result<()> 59 | where 60 | W: io::Write, 61 | { 62 | writeln!( 63 | dest, 64 | r#" 65 | pub mod types {{ 66 | #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)] 67 | "# 68 | )?; 69 | 70 | super::gen_types(registry.api, dest)?; 71 | 72 | writeln!(dest, "}}") 73 | } 74 | 75 | /// Creates all the `` elements at the root of the bindings. 76 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 77 | where 78 | W: io::Write, 79 | { 80 | for enm in ®istry.enums { 81 | super::gen_enum_item(enm, "types::", dest)?; 82 | } 83 | 84 | Ok(()) 85 | } 86 | 87 | /// Creates a `FnPtr` structure which contains the store for a single binding. 88 | fn write_fnptr_struct_def(dest: &mut W) -> io::Result<()> 89 | where 90 | W: io::Write, 91 | { 92 | writeln!( 93 | dest, 94 | " 95 | #[allow(dead_code, missing_copy_implementations)] 96 | #[derive(Clone)] 97 | pub struct FnPtr {{ 98 | /// The function pointer that will be used when calling the function. 99 | f: *const __gl_imports::raw::c_void, 100 | /// True if the pointer points to a real function, false if points to a `panic!` fn. 101 | is_loaded: bool, 102 | }} 103 | 104 | impl FnPtr {{ 105 | /// Creates a `FnPtr` from a load attempt. 106 | fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{ 107 | if ptr.is_null() {{ 108 | FnPtr {{ 109 | f: missing_fn_panic as *const __gl_imports::raw::c_void, 110 | is_loaded: false 111 | }} 112 | }} else {{ 113 | FnPtr {{ f: ptr, is_loaded: true }} 114 | }} 115 | }} 116 | 117 | /// Returns `true` if the function has been successfully loaded. 118 | /// 119 | /// If it returns `false`, calling the corresponding function will fail. 120 | #[inline] 121 | #[allow(dead_code)] 122 | pub fn is_loaded(&self) -> bool {{ 123 | self.is_loaded 124 | }} 125 | }} 126 | " 127 | ) 128 | } 129 | 130 | /// Creates a `panicking` module which contains one function per GL command. 131 | /// 132 | /// These functions are the mocks that are called if the real function could not be loaded. 133 | fn write_panicking_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 134 | where 135 | W: io::Write, 136 | { 137 | writeln!( 138 | dest, 139 | "#[inline(never)] 140 | fn missing_fn_panic() -> ! {{ 141 | panic!(\"{api} function was not loaded\") 142 | }}", 143 | api = registry.api 144 | ) 145 | } 146 | 147 | /// Creates a structure which stores all the `FnPtr` of the bindings. 148 | /// 149 | /// The name of the struct corresponds to the namespace. 150 | fn write_struct(registry: &Registry, dest: &mut W) -> io::Result<()> 151 | where 152 | W: io::Write, 153 | { 154 | writeln!( 155 | dest, 156 | " 157 | #[allow(non_camel_case_types, non_snake_case, dead_code)] 158 | #[derive(Clone)] 159 | pub struct {api} {{", 160 | api = super::gen_struct_name(registry.api) 161 | )?; 162 | 163 | for cmd in ®istry.cmds { 164 | if let Some(v) = registry.aliases.get(&cmd.proto.ident) { 165 | writeln!(dest, "/// Fallbacks: {}", v.join(", "))?; 166 | } 167 | writeln!(dest, "pub {name}: FnPtr,", name = cmd.proto.ident)?; 168 | } 169 | writeln!(dest, "_priv: ()")?; 170 | 171 | writeln!(dest, "}}") 172 | } 173 | 174 | /// Creates the `impl` of the structure created by `write_struct`. 175 | fn write_impl(registry: &Registry, dest: &mut W) -> io::Result<()> 176 | where 177 | W: io::Write, 178 | { 179 | writeln!(dest, 180 | "impl {api} {{ 181 | /// Load each OpenGL symbol using a custom load function. This allows for the 182 | /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`. 183 | /// 184 | /// ~~~ignore 185 | /// let gl = Gl::load_with(|s| glfw.get_proc_address(s)); 186 | /// ~~~ 187 | #[allow(dead_code, unused_variables)] 188 | pub fn load_with(mut loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{ 189 | #[inline(never)] 190 | fn do_metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void, 191 | symbol: &'static str, 192 | symbols: &[&'static str]) 193 | -> *const __gl_imports::raw::c_void {{ 194 | let mut ptr = loadfn(symbol); 195 | if ptr.is_null() {{ 196 | for &sym in symbols {{ 197 | ptr = loadfn(sym); 198 | if !ptr.is_null() {{ break; }} 199 | }} 200 | }} 201 | ptr 202 | }} 203 | let mut metaloadfn = |symbol: &'static str, symbols: &[&'static str]| {{ 204 | do_metaloadfn(&mut loadfn, symbol, symbols) 205 | }}; 206 | {api} {{", 207 | api = super::gen_struct_name(registry.api))?; 208 | 209 | for cmd in ®istry.cmds { 210 | writeln!( 211 | dest, 212 | "{name}: FnPtr::new(metaloadfn(\"{symbol}\", &[{fallbacks}])),", 213 | name = cmd.proto.ident, 214 | symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident), 215 | fallbacks = match registry.aliases.get(&cmd.proto.ident) { 216 | Some(fbs) => fbs 217 | .iter() 218 | .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name))) 219 | .collect::>() 220 | .join(", "), 221 | None => format!(""), 222 | }, 223 | )? 224 | } 225 | writeln!(dest, "_priv: ()")?; 226 | 227 | writeln!( 228 | dest, 229 | "}} 230 | }}" 231 | )?; 232 | 233 | for cmd in ®istry.cmds { 234 | let idents = super::gen_parameters(cmd, true, false); 235 | let typed_params = super::gen_parameters(cmd, false, true); 236 | let println = format!( 237 | "println!(\"[OpenGL] {}({})\" {});", 238 | cmd.proto.ident, 239 | (0..idents.len()) 240 | .map(|_| "{:?}".to_string()) 241 | .collect::>() 242 | .join(", "), 243 | idents 244 | .iter() 245 | .zip(typed_params.iter()) 246 | .map(|(name, ty)| if ty.contains("GLDEBUGPROC") { 247 | format!(", \"\"") 248 | } else { 249 | format!(", {}", name) 250 | }) 251 | .collect::>() 252 | .concat() 253 | ); 254 | 255 | writeln!(dest, 256 | "#[allow(non_snake_case, unused_variables, dead_code)] 257 | #[inline] pub unsafe fn {name}(&self, {params}) -> {return_suffix} {{ \ 258 | {println} 259 | let r = __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\ 260 | (self.{name}.f)({idents}); 261 | {print_err} 262 | r 263 | }}", 264 | name = cmd.proto.ident, 265 | params = super::gen_parameters(cmd, true, true).join(", "), 266 | typed_params = typed_params.join(", "), 267 | return_suffix = cmd.proto.ty, 268 | idents = idents.join(", "), 269 | println = println, 270 | print_err = if cmd.proto.ident != "GetError" && 271 | registry 272 | .cmds 273 | .iter() 274 | .find(|cmd| cmd.proto.ident == "GetError") 275 | .is_some() { 276 | format!(r#"match __gl_imports::mem::transmute::<_, extern "system" fn() -> u32> 277 | (self.GetError.f)() {{ 0 => (), r => println!("[OpenGL] ^ GL error triggered: {{}}", r) }}"#) 278 | } else { 279 | format!("") 280 | })? 281 | } 282 | 283 | writeln!( 284 | dest, 285 | "}} 286 | 287 | unsafe impl __gl_imports::Send for {api} {{}}", 288 | api = super::gen_struct_name(registry.api) 289 | ) 290 | } 291 | -------------------------------------------------------------------------------- /gl_generator/generators/global_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::Registry; 16 | use std::io; 17 | 18 | #[allow(missing_copy_implementations)] 19 | pub struct GlobalGenerator; 20 | 21 | impl super::Generator for GlobalGenerator { 22 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 23 | where 24 | W: io::Write, 25 | { 26 | write_header(dest)?; 27 | write_metaloadfn(dest)?; 28 | write_type_aliases(registry, dest)?; 29 | write_enums(registry, dest)?; 30 | write_fns(registry, dest)?; 31 | write_fnptr_struct_def(dest)?; 32 | write_ptrs(registry, dest)?; 33 | write_fn_mods(registry, dest)?; 34 | write_panicking_fns(registry, dest)?; 35 | write_load_fn(registry, dest)?; 36 | Ok(()) 37 | } 38 | } 39 | 40 | /// Creates a `__gl_imports` module which contains all the external symbols that we need for the 41 | /// bindings. 42 | fn write_header(dest: &mut W) -> io::Result<()> 43 | where 44 | W: io::Write, 45 | { 46 | writeln!( 47 | dest, 48 | r#" 49 | mod __gl_imports {{ 50 | pub use std::mem; 51 | pub use std::os::raw; 52 | }} 53 | "# 54 | ) 55 | } 56 | 57 | /// Creates the metaloadfn function for fallbacks 58 | fn write_metaloadfn(dest: &mut W) -> io::Result<()> 59 | where 60 | W: io::Write, 61 | { 62 | writeln!( 63 | dest, 64 | r#" 65 | #[inline(never)] 66 | fn metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void, 67 | symbol: &'static str, 68 | fallbacks: &[&'static str]) -> *const __gl_imports::raw::c_void {{ 69 | let mut ptr = loadfn(symbol); 70 | if ptr.is_null() {{ 71 | for &sym in fallbacks {{ 72 | ptr = loadfn(sym); 73 | if !ptr.is_null() {{ break; }} 74 | }} 75 | }} 76 | ptr 77 | }} 78 | "# 79 | ) 80 | } 81 | 82 | /// Creates a `types` module which contains all the type aliases. 83 | /// 84 | /// See also `generators::gen_types`. 85 | fn write_type_aliases(registry: &Registry, dest: &mut W) -> io::Result<()> 86 | where 87 | W: io::Write, 88 | { 89 | writeln!( 90 | dest, 91 | r#" 92 | pub mod types {{ 93 | #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)] 94 | "# 95 | )?; 96 | 97 | super::gen_types(registry.api, dest)?; 98 | 99 | writeln!( 100 | dest, 101 | " 102 | }} 103 | " 104 | ) 105 | } 106 | 107 | /// Creates all the `` elements at the root of the bindings. 108 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 109 | where 110 | W: io::Write, 111 | { 112 | for enm in ®istry.enums { 113 | super::gen_enum_item(enm, "types::", dest)?; 114 | } 115 | 116 | Ok(()) 117 | } 118 | 119 | /// Creates the functions corresponding to the GL commands. 120 | /// 121 | /// The function calls the corresponding function pointer stored in the `storage` module created 122 | /// by `write_ptrs`. 123 | fn write_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 124 | where 125 | W: io::Write, 126 | { 127 | for cmd in ®istry.cmds { 128 | if let Some(v) = registry.aliases.get(&cmd.proto.ident) { 129 | writeln!(dest, "/// Fallbacks: {}", v.join(", "))?; 130 | } 131 | 132 | writeln!(dest, 133 | "#[allow(non_snake_case, unused_variables, dead_code)] #[inline] 134 | pub unsafe fn {name}({params}) -> {return_suffix} {{ \ 135 | __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\ 136 | (storage::{name}.f)({idents}) \ 137 | }}", 138 | name = cmd.proto.ident, 139 | params = super::gen_parameters(cmd, true, true).join(", "), 140 | typed_params = super::gen_parameters(cmd, false, true).join(", "), 141 | return_suffix = cmd.proto.ty, 142 | idents = super::gen_parameters(cmd, true, false).join(", "), 143 | )?; 144 | } 145 | 146 | Ok(()) 147 | } 148 | 149 | /// Creates a `FnPtr` structure which contains the store for a single binding. 150 | fn write_fnptr_struct_def(dest: &mut W) -> io::Result<()> 151 | where 152 | W: io::Write, 153 | { 154 | writeln!(dest, 155 | " 156 | #[allow(missing_copy_implementations)] 157 | pub struct FnPtr {{ 158 | /// The function pointer that will be used when calling the function. 159 | f: *const __gl_imports::raw::c_void, 160 | /// True if the pointer points to a real function, false if points to a `panic!` fn. 161 | is_loaded: bool, 162 | }} 163 | 164 | impl FnPtr {{ 165 | /// Creates a `FnPtr` from a load attempt. 166 | pub fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{ 167 | if ptr.is_null() {{ 168 | FnPtr {{ f: missing_fn_panic as *const __gl_imports::raw::c_void, is_loaded: false }} 169 | }} else {{ 170 | FnPtr {{ f: ptr, is_loaded: true }} 171 | }} 172 | }} 173 | }} 174 | ") 175 | } 176 | 177 | /// Creates a `storage` module which contains a static `FnPtr` per GL command in the registry. 178 | fn write_ptrs(registry: &Registry, dest: &mut W) -> io::Result<()> 179 | where 180 | W: io::Write, 181 | { 182 | writeln!( 183 | dest, 184 | "mod storage {{ 185 | #![allow(non_snake_case)] 186 | #![allow(non_upper_case_globals)] 187 | use super::__gl_imports::raw; 188 | use super::FnPtr;" 189 | )?; 190 | 191 | for c in ®istry.cmds { 192 | writeln!( 193 | dest, 194 | "pub static mut {name}: FnPtr = FnPtr {{ 195 | f: super::missing_fn_panic as *const raw::c_void, 196 | is_loaded: false 197 | }};", 198 | name = c.proto.ident 199 | )?; 200 | } 201 | 202 | writeln!(dest, "}}") 203 | } 204 | 205 | /// Creates one module for each GL command. 206 | /// 207 | /// Each module contains `is_loaded` and `load_with` which interact with the `storage` module 208 | /// created by `write_ptrs`. 209 | fn write_fn_mods(registry: &Registry, dest: &mut W) -> io::Result<()> 210 | where 211 | W: io::Write, 212 | { 213 | for c in ®istry.cmds { 214 | let fallbacks = match registry.aliases.get(&c.proto.ident) { 215 | Some(v) => { 216 | let names = v 217 | .iter() 218 | .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name[..]))) 219 | .collect::>(); 220 | format!("&[{}]", names.join(", ")) 221 | }, 222 | None => "&[]".to_string(), 223 | }; 224 | let fnname = &c.proto.ident[..]; 225 | let symbol = super::gen_symbol_name(registry.api, &c.proto.ident[..]); 226 | let symbol = &symbol[..]; 227 | 228 | writeln!( 229 | dest, 230 | r##" 231 | #[allow(non_snake_case)] 232 | pub mod {fnname} {{ 233 | use super::{{storage, metaloadfn}}; 234 | use super::__gl_imports::raw; 235 | use super::FnPtr; 236 | 237 | #[inline] 238 | #[allow(dead_code)] 239 | pub fn is_loaded() -> bool {{ 240 | unsafe {{ storage::{fnname}.is_loaded }} 241 | }} 242 | 243 | #[allow(dead_code)] 244 | pub fn load_with(mut loadfn: F) where F: FnMut(&'static str) -> *const raw::c_void {{ 245 | unsafe {{ 246 | storage::{fnname} = FnPtr::new(metaloadfn(&mut loadfn, "{symbol}", {fallbacks})) 247 | }} 248 | }} 249 | }} 250 | "##, 251 | fnname = fnname, 252 | fallbacks = fallbacks, 253 | symbol = symbol 254 | )?; 255 | } 256 | 257 | Ok(()) 258 | } 259 | 260 | /// Creates a `missing_fn_panic` function. 261 | /// 262 | /// This function is the mock that is called if the real function could not be called. 263 | fn write_panicking_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 264 | where 265 | W: io::Write, 266 | { 267 | writeln!( 268 | dest, 269 | "#[inline(never)] 270 | fn missing_fn_panic() -> ! {{ 271 | panic!(\"{api} function was not loaded\") 272 | }} 273 | ", 274 | api = registry.api 275 | ) 276 | } 277 | 278 | /// Creates the `load_with` function. 279 | /// 280 | /// The function calls `load_with` in each module created by `write_fn_mods`. 281 | fn write_load_fn(registry: &Registry, dest: &mut W) -> io::Result<()> 282 | where 283 | W: io::Write, 284 | { 285 | writeln!(dest, 286 | " 287 | /// Load each OpenGL symbol using a custom load function. This allows for the 288 | /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`. 289 | /// ~~~ignore 290 | /// gl::load_with(|s| glfw.get_proc_address(s)); 291 | /// ~~~ 292 | #[allow(dead_code)] 293 | pub fn load_with(mut loadfn: F) where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{ 294 | #[inline(never)] 295 | fn inner(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void) {{ 296 | ")?; 297 | 298 | for c in ®istry.cmds { 299 | writeln!( 300 | dest, 301 | "{cmd_name}::load_with(&mut *loadfn);", 302 | cmd_name = &c.proto.ident[..] 303 | )?; 304 | } 305 | 306 | writeln!( 307 | dest, 308 | " 309 | }} 310 | 311 | inner(&mut loadfn) 312 | }} 313 | " 314 | ) 315 | } 316 | -------------------------------------------------------------------------------- /gl_generator/generators/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::{Cmd, Enum, Registry}; 16 | use std::io; 17 | use Api; 18 | 19 | pub mod debug_struct_gen; 20 | pub mod global_gen; 21 | pub mod static_gen; 22 | pub mod static_struct_gen; 23 | pub mod struct_gen; 24 | 25 | /// Trait for a bindings generator. 26 | /// 27 | /// See https://github.com/brendanzab/gl-rs/tree/master/gl_generator#generator-types 28 | pub trait Generator { 29 | /// Builds the GL bindings. 30 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 31 | where 32 | W: io::Write; 33 | } 34 | 35 | pub fn gen_struct_name(api: Api) -> &'static str { 36 | match api { 37 | Api::Gl => "Gl", 38 | Api::Glx => "Glx", 39 | Api::Wgl => "Wgl", 40 | Api::Egl => "Egl", 41 | Api::GlCore => "GlCore", 42 | Api::Gles1 => "Gles1", 43 | Api::Gles2 => "Gles2", 44 | Api::Glsc2 => "Glsc2", 45 | } 46 | } 47 | 48 | /// This function generates a `const name: type = value;` item. 49 | pub fn gen_enum_item(enm: &Enum, types_prefix: &str, dest: &mut W) -> io::Result<()> 50 | where 51 | W: io::Write, 52 | { 53 | writeln!(dest, 54 | "#[allow(dead_code, non_upper_case_globals)] pub const {ident}: {types_prefix}{ty} = {value}{cast_suffix};", 55 | ident = enm.ident, 56 | types_prefix = if enm.ty == "&'static str" { "" } else { types_prefix }, 57 | ty = enm.ty, 58 | value = enm.value, 59 | cast_suffix = match enm.cast { 60 | true => format!(" as {}{}", types_prefix, enm.ty), 61 | false => String::new(), 62 | }, 63 | ) 64 | } 65 | 66 | /// Generates all the type aliases for a namespace. 67 | /// 68 | /// Aliases are either `pub type = ...` or `#[repr(C)] pub struct ... { ... }` and contain all the 69 | /// things that we can't obtain from the XML files. 70 | pub fn gen_types(api: Api, dest: &mut W) -> io::Result<()> 71 | where 72 | W: io::Write, 73 | { 74 | if let Api::Egl = api { 75 | writeln!(dest, "{}", include_str!("templates/types/egl.rs"))?; 76 | return Ok(()); 77 | } 78 | 79 | writeln!(dest, "{}", include_str!("templates/types/gl.rs"))?; 80 | 81 | match api { 82 | Api::Glx => writeln!(dest, "{}", include_str!("templates/types/glx.rs"))?, 83 | Api::Wgl => writeln!(dest, "{}", include_str!("templates/types/wgl.rs"))?, 84 | _ => {}, 85 | } 86 | 87 | Ok(()) 88 | } 89 | 90 | /// Generates the list of Rust `Arg`s that a `Cmd` requires. 91 | pub fn gen_parameters(cmd: &Cmd, with_idents: bool, with_types: bool) -> Vec { 92 | cmd.params 93 | .iter() 94 | .map(|binding| { 95 | // returning 96 | if with_idents && with_types { 97 | format!("{}: {}", binding.ident, binding.ty) 98 | } else if with_types { 99 | format!("{}", binding.ty) 100 | } else if with_idents { 101 | format!("{}", binding.ident) 102 | } else { 103 | panic!() 104 | } 105 | }) 106 | .collect() 107 | } 108 | 109 | /// Generates the native symbol name of a `Cmd`. 110 | /// 111 | /// Example results: `"glClear"`, `"wglCreateContext"`, etc. 112 | pub fn gen_symbol_name(api: Api, cmd: &str) -> String { 113 | match api { 114 | Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => format!("gl{}", cmd), 115 | Api::Glx => format!("glX{}", cmd), 116 | Api::Wgl => format!("wgl{}", cmd), 117 | Api::Egl => format!("egl{}", cmd), 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /gl_generator/generators/static_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::Registry; 16 | use std::io; 17 | 18 | #[allow(missing_copy_implementations)] 19 | pub struct StaticGenerator; 20 | 21 | impl super::Generator for StaticGenerator { 22 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 23 | where 24 | W: io::Write, 25 | { 26 | write_header(dest)?; 27 | write_type_aliases(registry, dest)?; 28 | write_enums(registry, dest)?; 29 | write_fns(registry, dest)?; 30 | Ok(()) 31 | } 32 | } 33 | 34 | /// Creates a `__gl_imports` module which contains all the external symbols that we need for the 35 | /// bindings. 36 | fn write_header(dest: &mut W) -> io::Result<()> 37 | where 38 | W: io::Write, 39 | { 40 | writeln!( 41 | dest, 42 | r#" 43 | mod __gl_imports {{ 44 | pub use std::mem; 45 | pub use std::os::raw; 46 | }} 47 | "# 48 | ) 49 | } 50 | 51 | /// Creates a `types` module which contains all the type aliases. 52 | /// 53 | /// See also `generators::gen_types`. 54 | fn write_type_aliases(registry: &Registry, dest: &mut W) -> io::Result<()> 55 | where 56 | W: io::Write, 57 | { 58 | writeln!( 59 | dest, 60 | r#" 61 | pub mod types {{ 62 | #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)] 63 | "# 64 | )?; 65 | 66 | super::gen_types(registry.api, dest)?; 67 | 68 | writeln!( 69 | dest, 70 | " 71 | }} 72 | " 73 | ) 74 | } 75 | 76 | /// Creates all the `` elements at the root of the bindings. 77 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 78 | where 79 | W: io::Write, 80 | { 81 | for enm in ®istry.enums { 82 | super::gen_enum_item(enm, "types::", dest)?; 83 | } 84 | 85 | Ok(()) 86 | } 87 | 88 | /// io::Writes all functions corresponding to the GL bindings. 89 | /// 90 | /// These are foreign functions, they don't have any content. 91 | fn write_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 92 | where 93 | W: io::Write, 94 | { 95 | writeln!( 96 | dest, 97 | " 98 | #[allow(non_snake_case, unused_variables, dead_code)] 99 | extern \"system\" {{" 100 | )?; 101 | 102 | for cmd in ®istry.cmds { 103 | writeln!( 104 | dest, 105 | "#[link_name=\"{symbol}\"] 106 | pub fn {name}({params}) -> {return_suffix};", 107 | symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident), 108 | name = cmd.proto.ident, 109 | params = super::gen_parameters(cmd, true, true).join(", "), 110 | return_suffix = cmd.proto.ty, 111 | )?; 112 | } 113 | 114 | writeln!(dest, "}}") 115 | } 116 | -------------------------------------------------------------------------------- /gl_generator/generators/static_struct_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::Registry; 16 | use std::io; 17 | 18 | #[allow(missing_copy_implementations)] 19 | pub struct StaticStructGenerator; 20 | 21 | impl super::Generator for StaticStructGenerator { 22 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 23 | where 24 | W: io::Write, 25 | { 26 | write_header(dest)?; 27 | write_type_aliases(registry, dest)?; 28 | write_enums(registry, dest)?; 29 | write_struct(registry, dest)?; 30 | write_impl(registry, dest)?; 31 | write_fns(registry, dest)?; 32 | Ok(()) 33 | } 34 | } 35 | 36 | /// Creates a `__gl_imports` module which contains all the external symbols that we need for the 37 | /// bindings. 38 | fn write_header(dest: &mut W) -> io::Result<()> 39 | where 40 | W: io::Write, 41 | { 42 | writeln!( 43 | dest, 44 | r#" 45 | mod __gl_imports {{ 46 | pub use std::mem; 47 | pub use std::os::raw; 48 | }} 49 | "# 50 | ) 51 | } 52 | 53 | /// Creates a `types` module which contains all the type aliases. 54 | /// 55 | /// See also `generators::gen_types`. 56 | fn write_type_aliases(registry: &Registry, dest: &mut W) -> io::Result<()> 57 | where 58 | W: io::Write, 59 | { 60 | writeln!( 61 | dest, 62 | r#" 63 | pub mod types {{ 64 | #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)] 65 | "# 66 | )?; 67 | 68 | super::gen_types(registry.api, dest)?; 69 | 70 | writeln!(dest, "}}") 71 | } 72 | 73 | /// Creates all the `` elements at the root of the bindings. 74 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 75 | where 76 | W: io::Write, 77 | { 78 | for enm in ®istry.enums { 79 | super::gen_enum_item(enm, "types::", dest)?; 80 | } 81 | 82 | Ok(()) 83 | } 84 | 85 | /// Creates a stub structure. 86 | /// 87 | /// The name of the struct corresponds to the namespace. 88 | fn write_struct(registry: &Registry, dest: &mut W) -> io::Result<()> 89 | where 90 | W: io::Write, 91 | { 92 | writeln!( 93 | dest, 94 | " 95 | #[allow(non_camel_case_types, non_snake_case, dead_code)] 96 | #[derive(Copy, Clone)] 97 | pub struct {api};", 98 | api = super::gen_struct_name(registry.api), 99 | ) 100 | } 101 | 102 | /// Creates the `impl` of the structure created by `write_struct`. 103 | fn write_impl(registry: &Registry, dest: &mut W) -> io::Result<()> 104 | where 105 | W: io::Write, 106 | { 107 | writeln!(dest, 108 | "impl {api} {{ 109 | /// Stub function. 110 | #[allow(dead_code)] 111 | pub fn load_with(mut _loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{ 112 | {api} 113 | }}", 114 | api = super::gen_struct_name(registry.api), 115 | )?; 116 | 117 | for cmd in ®istry.cmds { 118 | writeln!( 119 | dest, 120 | "#[allow(non_snake_case)] 121 | // #[allow(unused_variables)] 122 | #[allow(dead_code)] 123 | #[inline] 124 | pub unsafe fn {name}(&self, {typed_params}) -> {return_suffix} {{ 125 | {name}({idents}) 126 | }}", 127 | name = cmd.proto.ident, 128 | typed_params = super::gen_parameters(cmd, true, true).join(", "), 129 | return_suffix = cmd.proto.ty, 130 | idents = super::gen_parameters(cmd, true, false).join(", "), 131 | )?; 132 | } 133 | 134 | writeln!(dest, "}}") 135 | } 136 | 137 | /// io::Writes all functions corresponding to the GL bindings. 138 | /// 139 | /// These are foreign functions, they don't have any content. 140 | fn write_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 141 | where 142 | W: io::Write, 143 | { 144 | writeln!( 145 | dest, 146 | " 147 | #[allow(non_snake_case)] 148 | #[allow(unused_variables)] 149 | #[allow(dead_code)] 150 | extern \"system\" {{" 151 | )?; 152 | 153 | for cmd in ®istry.cmds { 154 | writeln!( 155 | dest, 156 | "#[link_name=\"{symbol}\"] fn {name}({params}) -> {return_suffix};", 157 | symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident), 158 | name = cmd.proto.ident, 159 | params = super::gen_parameters(cmd, true, true).join(", "), 160 | return_suffix = cmd.proto.ty, 161 | )?; 162 | } 163 | 164 | writeln!(dest, "}}") 165 | } 166 | -------------------------------------------------------------------------------- /gl_generator/generators/struct_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use registry::Registry; 16 | use std::io; 17 | 18 | #[allow(missing_copy_implementations)] 19 | pub struct StructGenerator; 20 | 21 | impl super::Generator for StructGenerator { 22 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 23 | where 24 | W: io::Write, 25 | { 26 | write_header(dest)?; 27 | write_type_aliases(registry, dest)?; 28 | write_enums(registry, dest)?; 29 | write_fnptr_struct_def(dest)?; 30 | write_panicking_fns(registry, dest)?; 31 | write_struct(registry, dest)?; 32 | write_impl(registry, dest)?; 33 | Ok(()) 34 | } 35 | } 36 | 37 | /// Creates a `__gl_imports` module which contains all the external symbols that we need for the 38 | /// bindings. 39 | fn write_header(dest: &mut W) -> io::Result<()> 40 | where 41 | W: io::Write, 42 | { 43 | writeln!( 44 | dest, 45 | r#" 46 | mod __gl_imports {{ 47 | pub use std::mem; 48 | pub use std::marker::Send; 49 | pub use std::os::raw; 50 | }} 51 | "# 52 | ) 53 | } 54 | 55 | /// Creates a `types` module which contains all the type aliases. 56 | /// 57 | /// See also `generators::gen_types`. 58 | fn write_type_aliases(registry: &Registry, dest: &mut W) -> io::Result<()> 59 | where 60 | W: io::Write, 61 | { 62 | writeln!( 63 | dest, 64 | r#" 65 | pub mod types {{ 66 | #![allow(non_camel_case_types, non_snake_case, dead_code, missing_copy_implementations)] 67 | "# 68 | )?; 69 | 70 | super::gen_types(registry.api, dest)?; 71 | 72 | writeln!(dest, "}}") 73 | } 74 | 75 | /// Creates all the `` elements at the root of the bindings. 76 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 77 | where 78 | W: io::Write, 79 | { 80 | for enm in ®istry.enums { 81 | super::gen_enum_item(enm, "types::", dest)?; 82 | } 83 | 84 | Ok(()) 85 | } 86 | 87 | /// Creates a `FnPtr` structure which contains the store for a single binding. 88 | fn write_fnptr_struct_def(dest: &mut W) -> io::Result<()> 89 | where 90 | W: io::Write, 91 | { 92 | writeln!( 93 | dest, 94 | " 95 | #[allow(dead_code, missing_copy_implementations)] 96 | #[derive(Clone)] 97 | pub struct FnPtr {{ 98 | /// The function pointer that will be used when calling the function. 99 | f: *const __gl_imports::raw::c_void, 100 | /// True if the pointer points to a real function, false if points to a `panic!` fn. 101 | is_loaded: bool, 102 | }} 103 | 104 | impl FnPtr {{ 105 | /// Creates a `FnPtr` from a load attempt. 106 | fn new(ptr: *const __gl_imports::raw::c_void) -> FnPtr {{ 107 | if ptr.is_null() {{ 108 | FnPtr {{ 109 | f: missing_fn_panic as *const __gl_imports::raw::c_void, 110 | is_loaded: false 111 | }} 112 | }} else {{ 113 | FnPtr {{ f: ptr, is_loaded: true }} 114 | }} 115 | }} 116 | 117 | /// Returns `true` if the function has been successfully loaded. 118 | /// 119 | /// If it returns `false`, calling the corresponding function will fail. 120 | #[inline] 121 | #[allow(dead_code)] 122 | pub fn is_loaded(&self) -> bool {{ 123 | self.is_loaded 124 | }} 125 | }} 126 | " 127 | ) 128 | } 129 | 130 | /// Creates a `panicking` module which contains one function per GL command. 131 | /// 132 | /// These functions are the mocks that are called if the real function could not be loaded. 133 | fn write_panicking_fns(registry: &Registry, dest: &mut W) -> io::Result<()> 134 | where 135 | W: io::Write, 136 | { 137 | writeln!( 138 | dest, 139 | "#[inline(never)] 140 | fn missing_fn_panic() -> ! {{ 141 | panic!(\"{api} function was not loaded\") 142 | }}", 143 | api = registry.api 144 | ) 145 | } 146 | 147 | /// Creates a structure which stores all the `FnPtr` of the bindings. 148 | /// 149 | /// The name of the struct corresponds to the namespace. 150 | fn write_struct(registry: &Registry, dest: &mut W) -> io::Result<()> 151 | where 152 | W: io::Write, 153 | { 154 | writeln!( 155 | dest, 156 | " 157 | #[allow(non_camel_case_types, non_snake_case, dead_code)] 158 | #[derive(Clone)] 159 | pub struct {api} {{", 160 | api = super::gen_struct_name(registry.api) 161 | )?; 162 | 163 | for cmd in ®istry.cmds { 164 | if let Some(v) = registry.aliases.get(&cmd.proto.ident) { 165 | writeln!(dest, "/// Fallbacks: {}", v.join(", "))?; 166 | } 167 | writeln!(dest, "pub {name}: FnPtr,", name = cmd.proto.ident)?; 168 | } 169 | writeln!(dest, "_priv: ()")?; 170 | 171 | writeln!(dest, "}}") 172 | } 173 | 174 | /// Creates the `impl` of the structure created by `write_struct`. 175 | fn write_impl(registry: &Registry, dest: &mut W) -> io::Result<()> 176 | where 177 | W: io::Write, 178 | { 179 | writeln!(dest, 180 | "impl {api} {{ 181 | /// Load each OpenGL symbol using a custom load function. This allows for the 182 | /// use of functions like `glfwGetProcAddress` or `SDL_GL_GetProcAddress`. 183 | /// 184 | /// ~~~ignore 185 | /// let gl = Gl::load_with(|s| glfw.get_proc_address(s)); 186 | /// ~~~ 187 | #[allow(dead_code, unused_variables)] 188 | pub fn load_with(mut loadfn: F) -> {api} where F: FnMut(&'static str) -> *const __gl_imports::raw::c_void {{ 189 | #[inline(never)] 190 | fn do_metaloadfn(loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void, 191 | symbol: &'static str, 192 | symbols: &[&'static str]) 193 | -> *const __gl_imports::raw::c_void {{ 194 | let mut ptr = loadfn(symbol); 195 | if ptr.is_null() {{ 196 | for &sym in symbols {{ 197 | ptr = loadfn(sym); 198 | if !ptr.is_null() {{ break; }} 199 | }} 200 | }} 201 | ptr 202 | }} 203 | let mut metaloadfn = |symbol: &'static str, symbols: &[&'static str]| {{ 204 | do_metaloadfn(&mut loadfn, symbol, symbols) 205 | }}; 206 | {api} {{", 207 | api = super::gen_struct_name(registry.api))?; 208 | 209 | for cmd in ®istry.cmds { 210 | writeln!( 211 | dest, 212 | "{name}: FnPtr::new(metaloadfn(\"{symbol}\", &[{fallbacks}])),", 213 | name = cmd.proto.ident, 214 | symbol = super::gen_symbol_name(registry.api, &cmd.proto.ident), 215 | fallbacks = match registry.aliases.get(&cmd.proto.ident) { 216 | Some(fbs) => fbs 217 | .iter() 218 | .map(|name| format!("\"{}\"", super::gen_symbol_name(registry.api, &name))) 219 | .collect::>() 220 | .join(", "), 221 | None => format!(""), 222 | }, 223 | )? 224 | } 225 | 226 | writeln!(dest, "_priv: ()")?; 227 | 228 | writeln!( 229 | dest, 230 | "}} 231 | }}" 232 | )?; 233 | 234 | for cmd in ®istry.cmds { 235 | writeln!(dest, 236 | "#[allow(non_snake_case, unused_variables, dead_code)] 237 | #[inline] pub unsafe fn {name}(&self, {params}) -> {return_suffix} {{ \ 238 | __gl_imports::mem::transmute::<_, extern \"system\" fn({typed_params}) -> {return_suffix}>\ 239 | (self.{name}.f)({idents}) \ 240 | }}", 241 | name = cmd.proto.ident, 242 | params = super::gen_parameters(cmd, true, true).join(", "), 243 | typed_params = super::gen_parameters(cmd, false, true).join(", "), 244 | return_suffix = cmd.proto.ty, 245 | idents = super::gen_parameters(cmd, true, false).join(", "), 246 | )? 247 | } 248 | 249 | writeln!( 250 | dest, 251 | "}} 252 | 253 | unsafe impl __gl_imports::Send for {api} {{}}", 254 | api = super::gen_struct_name(registry.api) 255 | ) 256 | } 257 | -------------------------------------------------------------------------------- /gl_generator/generators/templates/types/egl.rs: -------------------------------------------------------------------------------- 1 | // platform-specific aliases are unknown 2 | // IMPORTANT: these are alises to the same level of the bindings 3 | // the values must be defined by the user 4 | #[allow(dead_code)] 5 | pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t; 6 | #[allow(dead_code)] 7 | pub type khronos_uint64_t = super::khronos_uint64_t; 8 | #[allow(dead_code)] 9 | pub type khronos_ssize_t = super::khronos_ssize_t; 10 | pub type EGLNativeDisplayType = super::EGLNativeDisplayType; 11 | #[allow(dead_code)] 12 | pub type EGLNativePixmapType = super::EGLNativePixmapType; 13 | #[allow(dead_code)] 14 | pub type EGLNativeWindowType = super::EGLNativeWindowType; 15 | pub type EGLint = super::EGLint; 16 | #[allow(dead_code)] 17 | pub type NativeDisplayType = super::NativeDisplayType; 18 | #[allow(dead_code)] 19 | pub type NativePixmapType = super::NativePixmapType; 20 | #[allow(dead_code)] 21 | pub type NativeWindowType = super::NativeWindowType; 22 | 23 | // EGL alises 24 | pub type Bool = EGLBoolean; // TODO: not sure 25 | pub type EGLBoolean = super::__gl_imports::raw::c_uint; 26 | pub type EGLenum = super::__gl_imports::raw::c_uint; 27 | pub type EGLAttribKHR = isize; 28 | pub type EGLAttrib = isize; 29 | pub type EGLConfig = *const super::__gl_imports::raw::c_void; 30 | pub type EGLContext = *const super::__gl_imports::raw::c_void; 31 | pub type EGLDeviceEXT = *const super::__gl_imports::raw::c_void; 32 | pub type EGLDisplay = *const super::__gl_imports::raw::c_void; 33 | pub type EGLSurface = *const super::__gl_imports::raw::c_void; 34 | pub type EGLClientBuffer = *const super::__gl_imports::raw::c_void; 35 | pub enum __eglMustCastToProperFunctionPointerType_fn {} 36 | pub type __eglMustCastToProperFunctionPointerType = 37 | *mut __eglMustCastToProperFunctionPointerType_fn; 38 | pub type EGLImageKHR = *const super::__gl_imports::raw::c_void; 39 | pub type EGLImage = *const super::__gl_imports::raw::c_void; 40 | pub type EGLOutputLayerEXT = *const super::__gl_imports::raw::c_void; 41 | pub type EGLOutputPortEXT = *const super::__gl_imports::raw::c_void; 42 | pub type EGLSyncKHR = *const super::__gl_imports::raw::c_void; 43 | pub type EGLSync = *const super::__gl_imports::raw::c_void; 44 | pub type EGLTimeKHR = khronos_utime_nanoseconds_t; 45 | pub type EGLTime = khronos_utime_nanoseconds_t; 46 | pub type EGLSyncNV = *const super::__gl_imports::raw::c_void; 47 | pub type EGLTimeNV = khronos_utime_nanoseconds_t; 48 | pub type EGLuint64NV = khronos_utime_nanoseconds_t; 49 | pub type EGLStreamKHR = *const super::__gl_imports::raw::c_void; 50 | pub type EGLuint64KHR = khronos_uint64_t; 51 | pub type EGLNativeFileDescriptorKHR = super::__gl_imports::raw::c_int; 52 | pub type EGLsizeiANDROID = khronos_ssize_t; 53 | pub type EGLSetBlobFuncANDROID = extern "system" fn(*const super::__gl_imports::raw::c_void, 54 | EGLsizeiANDROID, 55 | *const super::__gl_imports::raw::c_void, 56 | EGLsizeiANDROID) 57 | -> (); 58 | pub type EGLGetBlobFuncANDROID = extern "system" fn(*const super::__gl_imports::raw::c_void, 59 | EGLsizeiANDROID, 60 | *mut super::__gl_imports::raw::c_void, 61 | EGLsizeiANDROID) 62 | -> EGLsizeiANDROID; 63 | 64 | #[repr(C)] 65 | pub struct EGLClientPixmapHI { 66 | pData: *const super::__gl_imports::raw::c_void, 67 | iWidth: EGLint, 68 | iHeight: EGLint, 69 | iStride: EGLint, 70 | } 71 | -------------------------------------------------------------------------------- /gl_generator/generators/templates/types/gl.rs: -------------------------------------------------------------------------------- 1 | // Common types from OpenGL 1.1 2 | pub type GLenum = super::__gl_imports::raw::c_uint; 3 | pub type GLboolean = super::__gl_imports::raw::c_uchar; 4 | pub type GLbitfield = super::__gl_imports::raw::c_uint; 5 | pub type GLvoid = super::__gl_imports::raw::c_void; 6 | pub type GLbyte = super::__gl_imports::raw::c_char; 7 | pub type GLshort = super::__gl_imports::raw::c_short; 8 | pub type GLint = super::__gl_imports::raw::c_int; 9 | pub type GLclampx = super::__gl_imports::raw::c_int; 10 | pub type GLubyte = super::__gl_imports::raw::c_uchar; 11 | pub type GLushort = super::__gl_imports::raw::c_ushort; 12 | pub type GLuint = super::__gl_imports::raw::c_uint; 13 | pub type GLsizei = super::__gl_imports::raw::c_int; 14 | pub type GLfloat = super::__gl_imports::raw::c_float; 15 | pub type GLclampf = super::__gl_imports::raw::c_float; 16 | pub type GLdouble = super::__gl_imports::raw::c_double; 17 | pub type GLclampd = super::__gl_imports::raw::c_double; 18 | pub type GLeglImageOES = *const super::__gl_imports::raw::c_void; 19 | pub type GLchar = super::__gl_imports::raw::c_char; 20 | pub type GLcharARB = super::__gl_imports::raw::c_char; 21 | 22 | #[cfg(target_os = "macos")] 23 | pub type GLhandleARB = *const super::__gl_imports::raw::c_void; 24 | #[cfg(not(target_os = "macos"))] 25 | pub type GLhandleARB = super::__gl_imports::raw::c_uint; 26 | 27 | pub type GLhalfARB = super::__gl_imports::raw::c_ushort; 28 | pub type GLhalf = super::__gl_imports::raw::c_ushort; 29 | 30 | // Must be 32 bits 31 | pub type GLfixed = GLint; 32 | 33 | pub type GLintptr = isize; 34 | pub type GLsizeiptr = isize; 35 | pub type GLint64 = i64; 36 | pub type GLuint64 = u64; 37 | pub type GLintptrARB = isize; 38 | pub type GLsizeiptrARB = isize; 39 | pub type GLint64EXT = i64; 40 | pub type GLuint64EXT = u64; 41 | 42 | pub enum __GLsync {} 43 | pub type GLsync = *const __GLsync; 44 | 45 | // compatible with OpenCL cl_context 46 | pub enum _cl_context {} 47 | pub enum _cl_event {} 48 | 49 | pub type GLDEBUGPROC = Option; 56 | pub type GLDEBUGPROCARB = Option; 63 | pub type GLDEBUGPROCKHR = Option; 70 | 71 | // GLES 1 types 72 | // "pub type GLclampx = i32;", 73 | 74 | // GLES 1/2 types (tagged for GLES 1) 75 | // "pub type GLbyte = i8;", 76 | // "pub type GLubyte = u8;", 77 | // "pub type GLfloat = GLfloat;", 78 | // "pub type GLclampf = GLfloat;", 79 | // "pub type GLfixed = i32;", 80 | // "pub type GLint64 = i64;", 81 | // "pub type GLuint64 = u64;", 82 | // "pub type GLintptr = intptr_t;", 83 | // "pub type GLsizeiptr = ssize_t;", 84 | 85 | // GLES 1/2 types (tagged for GLES 2 - attribute syntax is limited) 86 | // "pub type GLbyte = i8;", 87 | // "pub type GLubyte = u8;", 88 | // "pub type GLfloat = GLfloat;", 89 | // "pub type GLclampf = GLfloat;", 90 | // "pub type GLfixed = i32;", 91 | // "pub type GLint64 = i64;", 92 | // "pub type GLuint64 = u64;", 93 | // "pub type GLint64EXT = i64;", 94 | // "pub type GLuint64EXT = u64;", 95 | // "pub type GLintptr = intptr_t;", 96 | // "pub type GLsizeiptr = ssize_t;", 97 | 98 | // GLES 2 types (none currently) 99 | 100 | // Vendor extension types 101 | pub type GLDEBUGPROCAMD = Option; 107 | pub type GLhalfNV = super::__gl_imports::raw::c_ushort; 108 | pub type GLvdpauSurfaceNV = GLintptr; 109 | -------------------------------------------------------------------------------- /gl_generator/generators/templates/types/glx.rs: -------------------------------------------------------------------------------- 1 | pub type XID = super::__gl_imports::raw::c_ulong; 2 | pub type Bool = super::__gl_imports::raw::c_int; // Not sure if this is correct... 3 | pub enum Display {} 4 | 5 | pub type Font = XID; 6 | pub type Pixmap = XID; 7 | pub enum Visual {} // TODO: not sure 8 | pub type VisualID = super::__gl_imports::raw::c_ulong; // TODO: not sure 9 | pub type Window = XID; 10 | pub type GLXFBConfigID = XID; 11 | pub type GLXFBConfig = *const super::__gl_imports::raw::c_void; 12 | pub type GLXContextID = XID; 13 | pub type GLXContext = *const super::__gl_imports::raw::c_void; 14 | pub type GLXPixmap = XID; 15 | pub type GLXDrawable = XID; 16 | pub type GLXWindow = XID; 17 | pub type GLXPbuffer = XID; 18 | pub enum __GLXextFuncPtr_fn {} 19 | pub type __GLXextFuncPtr = *mut __GLXextFuncPtr_fn; 20 | pub type GLXVideoCaptureDeviceNV = XID; 21 | pub type GLXVideoDeviceNV = super::__gl_imports::raw::c_int; 22 | pub type GLXVideoSourceSGIX = XID; 23 | pub type GLXFBConfigIDSGIX = XID; 24 | pub type GLXFBConfigSGIX = *const super::__gl_imports::raw::c_void; 25 | pub type GLXPbufferSGIX = XID; 26 | 27 | #[repr(C)] 28 | pub struct XVisualInfo { 29 | pub visual: *mut Visual, 30 | pub visualid: VisualID, 31 | pub screen: super::__gl_imports::raw::c_int, 32 | pub depth: super::__gl_imports::raw::c_int, 33 | pub class: super::__gl_imports::raw::c_int, 34 | pub red_mask: super::__gl_imports::raw::c_ulong, 35 | pub green_mask: super::__gl_imports::raw::c_ulong, 36 | pub blue_mask: super::__gl_imports::raw::c_ulong, 37 | pub colormap_size: super::__gl_imports::raw::c_int, 38 | pub bits_per_rgb: super::__gl_imports::raw::c_int, 39 | } 40 | 41 | #[repr(C)] 42 | pub struct GLXPbufferClobberEvent { 43 | pub event_type: super::__gl_imports::raw::c_int, // GLX_DAMAGED or GLX_SAVED 44 | pub draw_type: super::__gl_imports::raw::c_int, // GLX_WINDOW or GLX_PBUFFER 45 | pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server 46 | pub send_event: Bool, // true if this came for SendEvent request 47 | pub display: *const Display, // display the event was read from 48 | pub drawable: GLXDrawable, // XID of Drawable 49 | pub buffer_mask: super::__gl_imports::raw::c_uint, // mask indicating which buffers are affected 50 | pub aux_buffer: super::__gl_imports::raw::c_uint, // which aux buffer was affected 51 | pub x: super::__gl_imports::raw::c_int, 52 | pub y: super::__gl_imports::raw::c_int, 53 | pub width: super::__gl_imports::raw::c_int, 54 | pub height: super::__gl_imports::raw::c_int, 55 | pub count: super::__gl_imports::raw::c_int, // if nonzero, at least this many more 56 | } 57 | 58 | #[repr(C)] 59 | pub struct GLXBufferSwapComplete { 60 | pub type_: super::__gl_imports::raw::c_int, 61 | pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server 62 | pub send_event: Bool, // true if this came from a SendEvent request 63 | pub display: *const Display, // Display the event was read from 64 | pub drawable: GLXDrawable, // drawable on which event was requested in event mask 65 | pub event_type: super::__gl_imports::raw::c_int, 66 | pub ust: i64, 67 | pub msc: i64, 68 | pub sbc: i64, 69 | } 70 | 71 | // typedef union __GLXEvent { 72 | // GLXPbufferClobberEvent glxpbufferclobber; 73 | // GLXBufferSwapComplete glxbufferswapcomplete; 74 | // long pad[24]; 75 | // } 76 | 77 | #[repr(C)] 78 | pub struct GLXBufferClobberEventSGIX { 79 | pub type_: super::__gl_imports::raw::c_int, 80 | pub serial: super::__gl_imports::raw::c_ulong, // # of last request processed by server 81 | pub send_event: Bool, // true if this came for SendEvent request 82 | pub display: *const Display, // display the event was read from 83 | pub drawable: GLXDrawable, // i.d. of Drawable 84 | pub event_type: super::__gl_imports::raw::c_int, // GLX_DAMAGED_SGIX or GLX_SAVED_SGIX 85 | pub draw_type: super::__gl_imports::raw::c_int, // GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX 86 | pub mask: super::__gl_imports::raw::c_uint, // mask indicating which buffers are affected 87 | pub x: super::__gl_imports::raw::c_int, 88 | pub y: super::__gl_imports::raw::c_int, 89 | pub width: super::__gl_imports::raw::c_int, 90 | pub height: super::__gl_imports::raw::c_int, 91 | pub count: super::__gl_imports::raw::c_int, // if nonzero, at least this many more 92 | } 93 | 94 | #[repr(C)] 95 | pub struct GLXHyperpipeNetworkSGIX { 96 | pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] 97 | pub networkId: super::__gl_imports::raw::c_int, 98 | } 99 | 100 | #[repr(C)] 101 | pub struct GLXHyperpipeConfigSGIX { 102 | pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] 103 | pub channel: super::__gl_imports::raw::c_int, 104 | pub participationType: super::__gl_imports::raw::c_uint, 105 | pub timeSlice: super::__gl_imports::raw::c_int, 106 | } 107 | 108 | #[repr(C)] 109 | pub struct GLXPipeRect { 110 | pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] 111 | pub srcXOrigin: super::__gl_imports::raw::c_int, 112 | pub srcYOrigin: super::__gl_imports::raw::c_int, 113 | pub srcWidth: super::__gl_imports::raw::c_int, 114 | pub srcHeight: super::__gl_imports::raw::c_int, 115 | pub destXOrigin: super::__gl_imports::raw::c_int, 116 | pub destYOrigin: super::__gl_imports::raw::c_int, 117 | pub destWidth: super::__gl_imports::raw::c_int, 118 | pub destHeight: super::__gl_imports::raw::c_int, 119 | } 120 | 121 | #[repr(C)] 122 | pub struct GLXPipeRectLimits { 123 | pub pipeName: [super::__gl_imports::raw::c_char; 80], // Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] 124 | pub XOrigin: super::__gl_imports::raw::c_int, 125 | pub YOrigin: super::__gl_imports::raw::c_int, 126 | pub maxHeight: super::__gl_imports::raw::c_int, 127 | pub maxWidth: super::__gl_imports::raw::c_int, 128 | } 129 | -------------------------------------------------------------------------------- /gl_generator/generators/templates/types/wgl.rs: -------------------------------------------------------------------------------- 1 | // From WinNT.h 2 | 3 | pub type CHAR = super::__gl_imports::raw::c_char; 4 | pub type HANDLE = PVOID; 5 | pub type LONG = super::__gl_imports::raw::c_long; 6 | pub type LPCSTR = *const super::__gl_imports::raw::c_char; 7 | pub type VOID = (); 8 | // #define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name 9 | pub type HPBUFFERARB = *const super::__gl_imports::raw::c_void; 10 | pub type HPBUFFEREXT = *const super::__gl_imports::raw::c_void; 11 | pub type HVIDEOOUTPUTDEVICENV = *const super::__gl_imports::raw::c_void; 12 | pub type HPVIDEODEV = *const super::__gl_imports::raw::c_void; 13 | pub type HPGPUNV = *const super::__gl_imports::raw::c_void; 14 | pub type HGPUNV = *const super::__gl_imports::raw::c_void; 15 | pub type HVIDEOINPUTDEVICENV = *const super::__gl_imports::raw::c_void; 16 | 17 | // From Windef.h 18 | 19 | pub type BOOL = super::__gl_imports::raw::c_int; 20 | pub type BYTE = super::__gl_imports::raw::c_uchar; 21 | pub type COLORREF = DWORD; 22 | pub type FLOAT = super::__gl_imports::raw::c_float; 23 | pub type HDC = HANDLE; 24 | pub type HENHMETAFILE = HANDLE; 25 | pub type HGLRC = *const super::__gl_imports::raw::c_void; 26 | pub type INT = super::__gl_imports::raw::c_int; 27 | pub type PVOID = *const super::__gl_imports::raw::c_void; 28 | pub type LPVOID = *const super::__gl_imports::raw::c_void; 29 | pub enum __PROC_fn {} 30 | pub type PROC = *mut __PROC_fn; 31 | 32 | #[repr(C)] 33 | pub struct RECT { 34 | left: LONG, 35 | top: LONG, 36 | right: LONG, 37 | bottom: LONG, 38 | } 39 | 40 | pub type UINT = super::__gl_imports::raw::c_uint; 41 | pub type USHORT = super::__gl_imports::raw::c_ushort; 42 | pub type WORD = super::__gl_imports::raw::c_ushort; 43 | 44 | // From BaseTsd.h 45 | 46 | pub type INT32 = i32; 47 | pub type INT64 = i64; 48 | 49 | // From IntSafe.h 50 | 51 | pub type DWORD = super::__gl_imports::raw::c_ulong; 52 | 53 | // From Wingdi.h 54 | 55 | #[repr(C)] 56 | pub struct POINTFLOAT { 57 | pub x: FLOAT, 58 | pub y: FLOAT, 59 | } 60 | 61 | #[repr(C)] 62 | pub struct GLYPHMETRICSFLOAT { 63 | pub gmfBlackBoxX: FLOAT, 64 | pub gmfBlackBoxY: FLOAT, 65 | pub gmfptGlyphOrigin: POINTFLOAT, 66 | pub gmfCellIncX: FLOAT, 67 | pub gmfCellIncY: FLOAT, 68 | } 69 | pub type LPGLYPHMETRICSFLOAT = *const GLYPHMETRICSFLOAT; 70 | 71 | #[repr(C)] 72 | pub struct LAYERPLANEDESCRIPTOR { 73 | pub nSize: WORD, 74 | pub nVersion: WORD, 75 | pub dwFlags: DWORD, 76 | pub iPixelType: BYTE, 77 | pub cColorBits: BYTE, 78 | pub cRedBits: BYTE, 79 | pub cRedShift: BYTE, 80 | pub cGreenBits: BYTE, 81 | pub cGreenShift: BYTE, 82 | pub cBlueBits: BYTE, 83 | pub cBlueShift: BYTE, 84 | pub cAlphaBits: BYTE, 85 | pub cAlphaShift: BYTE, 86 | pub cAccumBits: BYTE, 87 | pub cAccumRedBits: BYTE, 88 | pub cAccumGreenBits: BYTE, 89 | pub cAccumBlueBits: BYTE, 90 | pub cAccumAlphaBits: BYTE, 91 | pub cDepthBits: BYTE, 92 | pub cStencilBits: BYTE, 93 | pub cAuxBuffers: BYTE, 94 | pub iLayerType: BYTE, 95 | pub bReserved: BYTE, 96 | pub crTransparent: COLORREF, 97 | } 98 | 99 | #[repr(C)] 100 | pub struct PIXELFORMATDESCRIPTOR { 101 | pub nSize: WORD, 102 | pub nVersion: WORD, 103 | pub dwFlags: DWORD, 104 | pub iPixelType: BYTE, 105 | pub cColorBits: BYTE, 106 | pub cRedBits: BYTE, 107 | pub cRedShift: BYTE, 108 | pub cGreenBits: BYTE, 109 | pub cGreenShift: BYTE, 110 | pub cBlueBits: BYTE, 111 | pub cBlueShift: BYTE, 112 | pub cAlphaBits: BYTE, 113 | pub cAlphaShift: BYTE, 114 | pub cAccumBits: BYTE, 115 | pub cAccumRedBits: BYTE, 116 | pub cAccumGreenBits: BYTE, 117 | pub cAccumBlueBits: BYTE, 118 | pub cAccumAlphaBits: BYTE, 119 | pub cDepthBits: BYTE, 120 | pub cStencilBits: BYTE, 121 | pub cAuxBuffers: BYTE, 122 | pub iLayerType: BYTE, 123 | pub bReserved: BYTE, 124 | pub dwLayerMask: DWORD, 125 | pub dwVisibleMask: DWORD, 126 | pub dwDamageMask: DWORD, 127 | } 128 | 129 | #[repr(C)] 130 | pub struct _GPU_DEVICE { 131 | cb: DWORD, 132 | DeviceName: [CHAR; 32], 133 | DeviceString: [CHAR; 128], 134 | Flags: DWORD, 135 | rcVirtualScreen: RECT, 136 | } 137 | 138 | pub struct GPU_DEVICE(_GPU_DEVICE); 139 | pub struct PGPU_DEVICE(*const _GPU_DEVICE); 140 | -------------------------------------------------------------------------------- /gl_generator/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! An OpenGL bindings generator. It defines a function named `generate_bindings` which can be 16 | //! used to generate all constants and functions of a given OpenGL version. 17 | //! 18 | //! # Example 19 | //! 20 | //! In `build.rs`: 21 | //! 22 | //! ```no_run 23 | //! extern crate gl_generator; 24 | //! 25 | //! use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; 26 | //! use std::env; 27 | //! use std::fs::File; 28 | //! use std::path::Path; 29 | //! 30 | //! fn main() { 31 | //! let dest = env::var("OUT_DIR").unwrap(); 32 | //! let mut file = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap(); 33 | //! 34 | //! Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []) 35 | //! .write_bindings(GlobalGenerator, &mut file) 36 | //! .unwrap(); 37 | //! } 38 | //! ``` 39 | //! 40 | //! In your project: 41 | //! 42 | //! ```ignore 43 | //! include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs")); 44 | //! ``` 45 | //! 46 | //! # About EGL 47 | //! 48 | //! When you generate bindings for EGL, the following platform-specific types must be declared 49 | //! *at the same level where you include the bindings*: 50 | //! 51 | //! - `khronos_utime_nanoseconds_t` 52 | //! - `khronos_uint64_t` 53 | //! - `khronos_ssize_t` 54 | //! - `EGLNativeDisplayType` 55 | //! - `EGLNativePixmapType` 56 | //! - `EGLNativeWindowType` 57 | //! - `EGLint` 58 | //! - `NativeDisplayType` 59 | //! - `NativePixmapType` 60 | //! - `NativeWindowType` 61 | //! 62 | 63 | #[macro_use] 64 | extern crate log; 65 | extern crate xml; 66 | 67 | #[cfg(feature = "unstable_generator_utils")] 68 | pub mod generators; 69 | #[cfg(not(feature = "unstable_generator_utils"))] 70 | mod generators; 71 | 72 | mod registry; 73 | 74 | pub use generators::debug_struct_gen::DebugStructGenerator; 75 | pub use generators::global_gen::GlobalGenerator; 76 | pub use generators::static_gen::StaticGenerator; 77 | pub use generators::static_struct_gen::StaticStructGenerator; 78 | pub use generators::struct_gen::StructGenerator; 79 | pub use generators::Generator; 80 | 81 | pub use registry::*; 82 | -------------------------------------------------------------------------------- /gl_generator/registry/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate khronos_api; 16 | 17 | use std::borrow::Cow; 18 | use std::collections::{BTreeMap, BTreeSet}; 19 | use std::fmt; 20 | use std::hash::{Hash, Hasher}; 21 | use std::io; 22 | use std::ops::{Add, AddAssign}; 23 | 24 | use Generator; 25 | 26 | mod parse; 27 | 28 | const BYTE_ORDER_MARK: &'static [u8] = &[0xef, 0xbb, 0xbf]; 29 | 30 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 31 | pub enum Api { 32 | Gl, 33 | Glx, 34 | Wgl, 35 | Egl, 36 | GlCore, 37 | Gles1, 38 | Gles2, 39 | Glsc2, 40 | } 41 | 42 | impl fmt::Display for Api { 43 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 44 | match *self { 45 | Api::Gl => write!(fmt, "gl"), 46 | Api::Glx => write!(fmt, "glx"), 47 | Api::Wgl => write!(fmt, "wgl"), 48 | Api::Egl => write!(fmt, "egl"), 49 | Api::GlCore => write!(fmt, "glcore"), 50 | Api::Gles1 => write!(fmt, "gles1"), 51 | Api::Gles2 => write!(fmt, "gles2"), 52 | Api::Glsc2 => write!(fmt, "glsc2"), 53 | } 54 | } 55 | } 56 | 57 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 58 | pub enum Fallbacks { 59 | All, 60 | None, 61 | } 62 | 63 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 64 | pub enum Profile { 65 | Core, 66 | Compatibility, 67 | } 68 | 69 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 70 | pub struct Enum { 71 | pub ident: String, 72 | pub value: String, 73 | pub cast: bool, 74 | pub alias: Option, 75 | pub ty: Cow<'static, str>, 76 | } 77 | 78 | impl Hash for Enum { 79 | fn hash(&self, state: &mut H) { 80 | self.ident.hash(state); 81 | } 82 | } 83 | 84 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 85 | pub struct Binding { 86 | pub ident: String, 87 | pub ty: Cow<'static, str>, 88 | pub group: Option, 89 | } 90 | 91 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 92 | pub struct Group { 93 | pub ident: String, 94 | pub enums_type: Option, 95 | pub enums: Vec, 96 | } 97 | 98 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 99 | pub struct Cmd { 100 | pub proto: Binding, 101 | pub params: Vec, 102 | pub alias: Option, 103 | pub vecequiv: Option, 104 | pub glx: Option, 105 | } 106 | 107 | impl Hash for Cmd { 108 | fn hash(&self, state: &mut H) { 109 | self.proto.ident.hash(state); 110 | } 111 | } 112 | 113 | #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 114 | pub struct GlxOpcode { 115 | pub opcode: String, 116 | pub name: Option, 117 | } 118 | 119 | #[derive(Clone, Debug, PartialEq, Eq)] 120 | pub struct Registry { 121 | pub api: Api, 122 | pub enums: BTreeSet, 123 | pub cmds: BTreeSet, 124 | pub aliases: BTreeMap>, 125 | pub groups: BTreeMap, 126 | } 127 | 128 | impl Registry { 129 | pub fn new<'a, Exts>( 130 | api: Api, 131 | version: (u8, u8), 132 | profile: Profile, 133 | fallbacks: Fallbacks, 134 | extensions: Exts, 135 | ) -> Registry 136 | where 137 | Exts: AsRef<[&'a str]>, 138 | { 139 | let (major, minor) = version; 140 | let extensions = extensions.as_ref().iter().map(<&str>::to_string).collect(); 141 | 142 | let filter = parse::Filter { 143 | api, 144 | fallbacks, 145 | extensions, 146 | version: format!("{}.{}", major, minor), 147 | profile, 148 | }; 149 | 150 | let src_raw = match api { 151 | Api::Gl | Api::GlCore | Api::Gles1 | Api::Gles2 | Api::Glsc2 => khronos_api::GL_XML, 152 | Api::Glx => khronos_api::GLX_XML, 153 | Api::Wgl => khronos_api::WGL_XML, 154 | Api::Egl => khronos_api::EGL_XML, 155 | }; 156 | 157 | let src = if &src_raw[..BYTE_ORDER_MARK.len()] == BYTE_ORDER_MARK { 158 | &src_raw[BYTE_ORDER_MARK.len()..] 159 | } else { 160 | src_raw 161 | }; 162 | 163 | let mut registry = parse::from_xml(src, &filter, true); 164 | if filter.extensions.iter().any(|e| e.starts_with("GL_ANGLE_")) { 165 | registry += parse::from_xml(khronos_api::GL_ANGLE_EXT_XML, &filter, false); 166 | } 167 | if filter 168 | .extensions 169 | .iter() 170 | .any(|e| e.starts_with("EGL_ANGLE_")) 171 | { 172 | registry += parse::from_xml(khronos_api::EGL_ANGLE_EXT_XML, &filter, false); 173 | } 174 | registry 175 | } 176 | 177 | pub fn write_bindings(&self, generator: G, output: &mut W) -> io::Result<()> 178 | where 179 | G: Generator, 180 | W: io::Write, 181 | { 182 | generator.write(&self, output) 183 | } 184 | 185 | /// Returns a set of all the types used in the supplied registry. This is useful 186 | /// for working out what conversions are needed for the specific registry. 187 | pub fn get_tys(&self) -> BTreeSet<&str> { 188 | let mut tys = BTreeSet::new(); 189 | for def in &self.cmds { 190 | tys.insert(def.proto.ty.as_ref()); 191 | for param in &def.params { 192 | tys.insert(param.ty.as_ref()); 193 | } 194 | } 195 | tys 196 | } 197 | } 198 | 199 | impl Add for Registry { 200 | type Output = Registry; 201 | 202 | fn add(mut self, other: Registry) -> Registry { 203 | self += other; 204 | self 205 | } 206 | } 207 | 208 | impl AddAssign for Registry { 209 | fn add_assign(&mut self, other: Self) { 210 | self.enums.extend(other.enums); 211 | self.cmds.extend(other.cmds); 212 | self.aliases.extend(other.aliases); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /khronos_api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "khronos_api" 3 | version = "3.2.0" 4 | authors = [ 5 | "Brendan Zabarauskas ", 6 | "Corey Richardson", 7 | "Arseny Kapoulkine", 8 | "Pierre Krieger ", 9 | ] 10 | description = "The Khronos XML API Registry, exposed as byte string constants." 11 | license = "Apache-2.0" 12 | documentation = "https://docs.rs/khronos_api" 13 | homepage = "https://github.com/brendanzab/gl-rs/" 14 | repository = "https://github.com/brendanzab/gl-rs/" 15 | readme = "README.md" 16 | 17 | # Only include what we need here. The git submodules are quite large, and would 18 | # exceed the maximimum crate size if we didn't do this 19 | include = [ 20 | "/README.md", 21 | "/src/**/*", 22 | "/Cargo.toml", 23 | "/build.rs", 24 | "/api/xml/**/*.xml", 25 | "/api_angle/scripts/**/*.xml", 26 | "/api_egl/api/**/*.xml", 27 | "/api_webgl/specs/latest/**/*.idl", 28 | "/api_webgl/extensions/**/extension.xml", 29 | ] 30 | 31 | categories = ["rendering::graphics-api"] 32 | keywords = ["gl", "egl", "opengl", "khronos"] 33 | -------------------------------------------------------------------------------- /khronos_api/README.md: -------------------------------------------------------------------------------- 1 | # khronos_api 2 | 3 | [![Version](https://img.shields.io/crates/v/khronos_api.svg)](https://crates.io/crates/khronos_api) 4 | [![License](https://img.shields.io/crates/l/khronos_api.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) 5 | [![Downloads](https://img.shields.io/crates/d/khronos_api.svg)](https://crates.io/crates/khronos_api) 6 | 7 | The Khronos XML API Registry, exposed as byte string constants. 8 | 9 | ```toml 10 | [build-dependencies] 11 | khronos_api = "3.1.0" 12 | ``` 13 | 14 | The following constants are provided: 15 | 16 | - `GL_XML`: the contents of [`gl.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/gl.xml) 17 | - `EGL_XML`: the contents of [`egl.xml`](https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml) 18 | - `WGL_XML`: the contents of [`wgl.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/wgl.xml) 19 | - `GLX_XML`: the contents of [`glx.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/glx.xml) 20 | - `GL_ANGLE_EXT_XML`: the contents of [`gl_angle_ext.xml`](https://github.com/google/angle/blob/master/scripts/gl_angle_ext.xml) 21 | - `EGL_ANGLE_EXT_XML`: the contents of [`egl_angle_ext.xml`](https://github.com/google/angle/blob/master/scripts/egl_angle_ext.xml) 22 | - `WEBGL_IDL`: the contents of [`webgl.idl`](https://github.com/KhronosGroup/WebGL/blob/master/specs/latest/1.0/webgl.idl) 23 | - `WEBGL2_IDL`: the contents of [`webgl2.idl`](https://github.com/KhronosGroup/WebGL/blob/master/specs/latest/2.0/webgl2.idl) 24 | - `WEBGL_EXT_XML`: the contents of the WebGL extension XML files, discovered by a build script 25 | -------------------------------------------------------------------------------- /khronos_api/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // This build script is used to discover all of the accepted extensions 16 | // described in the Khronos WebGL repository, and construct a static slice 17 | // containing the XML specifications for all of them. 18 | use std::env; 19 | use std::fs::File; 20 | use std::io::Write; 21 | use std::path::*; 22 | 23 | fn main() { 24 | // Create and open a file in the output directory to contain our generated rust code 25 | let dest = env::var("OUT_DIR").unwrap(); 26 | let mut file = File::create(&Path::new(&dest).join("webgl_exts.rs")).unwrap(); 27 | 28 | // Find the absolute path to the folder containing the WebGL extensions. 29 | // The absolute path is needed, because we don't know where the output 30 | // directory will be, and `include_bytes!(..)` resolves paths relative to the 31 | // containing file. 32 | let root = env::current_dir().unwrap().join("api_webgl/extensions"); 33 | 34 | // Generate a slice literal, looking like this: 35 | // `&[&*include_bytes!(..), &*include_bytes!(..), ..]` 36 | writeln!(file, "&[").unwrap(); 37 | 38 | // The slice will have one entry for each WebGL extension. To find the 39 | // extensions we mirror the behaviour of the `api_webgl/extensions/find-exts` 40 | // shell script. 41 | let mut paths: Vec<_> = root.read_dir().unwrap().map(|e| e.unwrap().path()).collect(); 42 | // Sort the list of paths in order for the webgl_exts.rs file to be created 43 | // deterministically. 44 | paths.sort(); 45 | for path in paths { 46 | let ext_name = path.file_name().unwrap().to_str().unwrap(); 47 | 48 | // Each item which is a directory, and is not named `template`, may be 49 | // an extension. 50 | if path.is_dir() && ext_name != "template" { 51 | // If the directory contains a file named `extension.xml`, then this 52 | // really is an extension. 53 | let ext_path = path.join("extension.xml"); 54 | if ext_path.is_file() { 55 | // Include the XML file, making sure to use an absolute path. 56 | writeln!(file, "&*include_bytes!({:?}),", ext_path.to_str().unwrap()).unwrap(); 57 | } 58 | } 59 | } 60 | 61 | // Close the slice 62 | writeln!(file, "]").unwrap(); 63 | } 64 | -------------------------------------------------------------------------------- /khronos_api/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! This crates contains the sources of the official OpenGL repository. 16 | 17 | // NOTE: if any new files are added to here, ensue they are also covered 18 | // in the `include` section of the `Cargo.toml`. 19 | 20 | /// The contents of [`gl.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/gl.xml) 21 | pub const GL_XML: &'static [u8] = include_bytes!("../api/xml/gl.xml"); 22 | 23 | /// The contents of [`egl.xml`](https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml) 24 | pub const EGL_XML: &'static [u8] = include_bytes!("../api_egl/api/egl.xml"); 25 | 26 | /// The contents of [`wgl.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/wgl.xml) 27 | pub const WGL_XML: &'static [u8] = include_bytes!("../api/xml/wgl.xml"); 28 | 29 | /// The contents of [`glx.xml`](https://github.com/KhronosGroup/OpenGL-Registry/blob/master/xml/glx.xml) 30 | pub const GLX_XML: &'static [u8] = include_bytes!("../api/xml/glx.xml"); 31 | 32 | /// The contents of [`gl_angle_ext.xml`](https://github.com/google/angle/blob/master/scripts/gl_angle_ext.xml) 33 | pub const GL_ANGLE_EXT_XML: &'static [u8] = include_bytes!("../api_angle/scripts/gl_angle_ext.xml"); 34 | 35 | /// The contents of [`egl_angle_ext.xml`](https://github.com/google/angle/blob/master/scripts/egl_angle_ext.xml) 36 | pub const EGL_ANGLE_EXT_XML: &'static [u8] = 37 | include_bytes!("../api_angle/scripts/egl_angle_ext.xml"); 38 | 39 | /// The contents of [`webgl.idl`](https://github.com/KhronosGroup/WebGL/blob/master/specs/latest/1.0/webgl.idl) 40 | pub const WEBGL_IDL: &'static [u8] = include_bytes!("../api_webgl/specs/latest/1.0/webgl.idl"); 41 | 42 | /// The contents of [`webgl2.idl`](https://github.com/KhronosGroup/WebGL/blob/master/specs/latest/2.0/webgl2.idl) 43 | pub const WEBGL2_IDL: &'static [u8] = include_bytes!("../api_webgl/specs/latest/2.0/webgl2.idl"); 44 | 45 | /// The contents of the WebGL extension XML files 46 | /// These are discovered via a build script to avoid having to list each extension by name. 47 | pub const WEBGL_EXT_XML: &'static [&'static [u8]] = 48 | include!(concat!(env!("OUT_DIR"), "/webgl_exts.rs")); 49 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | unstable_features = true 2 | match_block_trailing_comma = true 3 | -------------------------------------------------------------------------------- /tests/test_add_registries/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_add_registries" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | gl_generator = { path = "../../gl_generator" } 12 | -------------------------------------------------------------------------------- /tests/test_add_registries/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::*; 18 | use std::env; 19 | use std::fs::File; 20 | use std::path::*; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file = File::create(&Path::new(&dest).join("test_add_registries.rs")).unwrap(); 25 | 26 | let registry0 = Registry::new(Api::Gl, (3, 2), Profile::Core, Fallbacks::All, []); 27 | let registry1 = Registry::new(Api::Gl, (3, 2), Profile::Core, Fallbacks::All, []); 28 | 29 | (registry0 + registry1) 30 | .write_bindings(GlobalGenerator, &mut file) 31 | .unwrap(); 32 | } 33 | -------------------------------------------------------------------------------- /tests/test_add_registries/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod gl { 16 | include!(concat!(env!("OUT_DIR"), "/test_add_registries.rs")); 17 | } 18 | -------------------------------------------------------------------------------- /tests/test_gen_symbols/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_gen_symbols" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | gl_generator = { path = "../../gl_generator" } 12 | -------------------------------------------------------------------------------- /tests/test_gen_symbols/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::*; 18 | use std::env; 19 | use std::fs::File; 20 | use std::io::prelude::*; 21 | use std::path::*; 22 | 23 | fn main() { 24 | let dest = env::var("OUT_DIR").unwrap(); 25 | let mut file = File::create(&Path::new(&dest).join("test_gen_symbols.rs")).unwrap(); 26 | 27 | writeln!(&mut file, "mod gl {{").unwrap(); 28 | Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []) 29 | .write_bindings(GlobalGenerator, &mut file) 30 | .unwrap(); 31 | writeln!(&mut file, "}}").unwrap(); 32 | 33 | writeln!(&mut file, "mod gles1 {{").unwrap(); 34 | Registry::new(Api::Gles1, (1, 1), Profile::Core, Fallbacks::All, []) 35 | .write_bindings(GlobalGenerator, &mut file) 36 | .unwrap(); 37 | writeln!(&mut file, "}}").unwrap(); 38 | 39 | writeln!(&mut file, "mod gles2 {{").unwrap(); 40 | Registry::new(Api::Gles2, (3, 1), Profile::Core, Fallbacks::All, []) 41 | .write_bindings(GlobalGenerator, &mut file) 42 | .unwrap(); 43 | writeln!(&mut file, "}}").unwrap(); 44 | 45 | writeln!(&mut file, "mod glsc2 {{").unwrap(); 46 | Registry::new(Api::Glsc2, (3, 1), Profile::Core, Fallbacks::All, []) 47 | .write_bindings(GlobalGenerator, &mut file) 48 | .unwrap(); 49 | writeln!(&mut file, "}}").unwrap(); 50 | 51 | writeln!(&mut file, "mod glx {{").unwrap(); 52 | Registry::new(Api::Glx, (1, 4), Profile::Core, Fallbacks::All, []) 53 | .write_bindings(GlobalGenerator, &mut file) 54 | .unwrap(); 55 | writeln!(&mut file, "}}").unwrap(); 56 | 57 | writeln!(&mut file, "mod wgl {{").unwrap(); 58 | Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, []) 59 | .write_bindings(GlobalGenerator, &mut file) 60 | .unwrap(); 61 | writeln!(&mut file, "}}").unwrap(); 62 | 63 | writeln!(&mut file, "mod egl {{ {}", build_egl_symbols()).unwrap(); 64 | Registry::new(Api::Egl, (1, 5), Profile::Core, Fallbacks::All, []) 65 | .write_bindings(GlobalGenerator, &mut file) 66 | .unwrap(); 67 | writeln!(&mut file, "}}").unwrap(); 68 | } 69 | 70 | fn build_egl_symbols() -> &'static str { 71 | " 72 | #![allow(non_camel_case_types)] 73 | 74 | use std::os::raw; 75 | 76 | pub type khronos_utime_nanoseconds_t = raw::c_int; 77 | pub type khronos_uint64_t = u64; 78 | pub type khronos_ssize_t = isize; 79 | pub type EGLNativeDisplayType = *const raw::c_void; 80 | pub type EGLNativePixmapType = *const raw::c_void; 81 | pub type EGLNativeWindowType = *const raw::c_void; 82 | pub type EGLint = raw::c_int; 83 | pub type NativeDisplayType = *const raw::c_void; 84 | pub type NativePixmapType = *const raw::c_void; 85 | pub type NativeWindowType = *const raw::c_void; 86 | " 87 | } 88 | -------------------------------------------------------------------------------- /tests/test_gen_symbols/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::os::raw; 16 | 17 | include!(concat!(env!("OUT_DIR"), "/test_gen_symbols.rs")); 18 | 19 | pub fn compile_test_gl() { 20 | unsafe { 21 | gl::Clear(gl::COLOR_BUFFER_BIT); 22 | let _: raw::c_uint = gl::CreateProgram(); 23 | gl::CompileShader(5); 24 | gl::GetActiveUniformBlockiv( 25 | 0, 26 | 0, 27 | gl::UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, 28 | std::ptr::null_mut(), 29 | ); 30 | 31 | let _: *mut raw::c_void = gl::MapBuffer(0, 0); 32 | } 33 | } 34 | 35 | pub fn compile_test_gles1() { 36 | unsafe { 37 | gles1::Clear(gles1::COLOR_BUFFER_BIT); 38 | } 39 | } 40 | 41 | pub fn compile_test_gles2() { 42 | unsafe { 43 | gles2::Clear(gles2::COLOR_BUFFER_BIT); 44 | let _: raw::c_uint = gles2::CreateProgram(); 45 | gles2::CompileShader(5); 46 | } 47 | } 48 | 49 | pub fn compile_test_glsc2() { 50 | unsafe { 51 | glsc2::Clear(glsc2::COLOR_BUFFER_BIT); 52 | } 53 | } 54 | 55 | pub fn compile_test_glx() { 56 | unsafe { 57 | let _ = glx::GetProcAddress(std::mem::MaybeUninit::uninit().assume_init()); 58 | glx::SwapBuffers( 59 | std::mem::MaybeUninit::uninit().assume_init(), 60 | std::mem::MaybeUninit::uninit().assume_init(), 61 | ); 62 | } 63 | } 64 | 65 | pub fn compile_test_wgl() { 66 | unsafe { 67 | let _: wgl::types::HGLRC = 68 | wgl::CreateContext(std::mem::MaybeUninit::uninit().assume_init()); 69 | } 70 | } 71 | 72 | pub fn compile_test_egl() { 73 | unsafe { 74 | let _ = [ 75 | egl::SURFACE_TYPE, 76 | egl::WINDOW_BIT, 77 | egl::BLUE_SIZE, 78 | 8, 79 | egl::GREEN_SIZE, 80 | 8, 81 | egl::RED_SIZE, 82 | 8, 83 | egl::NONE, 84 | ]; 85 | 86 | let _ = egl::GetDisplay(egl::DEFAULT_DISPLAY); 87 | egl::Terminate(std::mem::MaybeUninit::uninit().assume_init()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tests/test_no_warnings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_no_warnings" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | gl_generator = { path = "../../gl_generator" } 12 | -------------------------------------------------------------------------------- /tests/test_no_warnings/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::*; 18 | use std::env; 19 | use std::fs::File; 20 | use std::io::prelude::*; 21 | use std::path::*; 22 | 23 | fn main() { 24 | let dest = env::var("OUT_DIR").unwrap(); 25 | let mut file = File::create(&Path::new(&dest).join("test_no_warnings.rs")).unwrap(); 26 | 27 | // Gl 28 | 29 | let gl_registry = Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []); 30 | 31 | writeln!(&mut file, "mod gl_global {{").unwrap(); 32 | gl_registry 33 | .write_bindings(GlobalGenerator, &mut file) 34 | .unwrap(); 35 | writeln!(&mut file, "}}").unwrap(); 36 | 37 | writeln!(&mut file, "mod gl_static {{").unwrap(); 38 | gl_registry 39 | .write_bindings(StaticGenerator, &mut file) 40 | .unwrap(); 41 | writeln!(&mut file, "}}").unwrap(); 42 | 43 | writeln!(&mut file, "mod gl_struct {{").unwrap(); 44 | gl_registry 45 | .write_bindings(StructGenerator, &mut file) 46 | .unwrap(); 47 | writeln!(&mut file, "}}").unwrap(); 48 | 49 | writeln!(&mut file, "mod gl_static_struct {{").unwrap(); 50 | gl_registry 51 | .write_bindings(StaticStructGenerator, &mut file) 52 | .unwrap(); 53 | writeln!(&mut file, "}}").unwrap(); 54 | 55 | writeln!(&mut file, "mod gl_debug_struct {{").unwrap(); 56 | gl_registry 57 | .write_bindings(DebugStructGenerator, &mut file) 58 | .unwrap(); 59 | writeln!(&mut file, "}}").unwrap(); 60 | 61 | // Glx 62 | 63 | let glx_registry = Registry::new(Api::Glx, (1, 4), Profile::Core, Fallbacks::All, []); 64 | 65 | writeln!(&mut file, "mod glx_global {{").unwrap(); 66 | glx_registry 67 | .write_bindings(GlobalGenerator, &mut file) 68 | .unwrap(); 69 | writeln!(&mut file, "}}").unwrap(); 70 | 71 | writeln!(&mut file, "mod glx_static {{").unwrap(); 72 | glx_registry 73 | .write_bindings(StaticGenerator, &mut file) 74 | .unwrap(); 75 | writeln!(&mut file, "}}").unwrap(); 76 | 77 | writeln!(&mut file, "mod glx_struct {{").unwrap(); 78 | glx_registry 79 | .write_bindings(StructGenerator, &mut file) 80 | .unwrap(); 81 | writeln!(&mut file, "}}").unwrap(); 82 | 83 | writeln!(&mut file, "mod glx_static_struct {{").unwrap(); 84 | glx_registry 85 | .write_bindings(StaticStructGenerator, &mut file) 86 | .unwrap(); 87 | writeln!(&mut file, "}}").unwrap(); 88 | 89 | writeln!(&mut file, "mod glx_debug_struct {{").unwrap(); 90 | glx_registry 91 | .write_bindings(DebugStructGenerator, &mut file) 92 | .unwrap(); 93 | writeln!(&mut file, "}}").unwrap(); 94 | 95 | // Wgl 96 | 97 | let wgl_registry = Registry::new(Api::Wgl, (1, 0), Profile::Core, Fallbacks::All, []); 98 | 99 | writeln!(&mut file, "mod wgl_global {{").unwrap(); 100 | wgl_registry 101 | .write_bindings(GlobalGenerator, &mut file) 102 | .unwrap(); 103 | writeln!(&mut file, "}}").unwrap(); 104 | 105 | writeln!(&mut file, "mod wgl_static {{").unwrap(); 106 | wgl_registry 107 | .write_bindings(StaticGenerator, &mut file) 108 | .unwrap(); 109 | writeln!(&mut file, "}}").unwrap(); 110 | 111 | writeln!(&mut file, "mod wgl_struct {{").unwrap(); 112 | wgl_registry 113 | .write_bindings(StructGenerator, &mut file) 114 | .unwrap(); 115 | writeln!(&mut file, "}}").unwrap(); 116 | 117 | writeln!(&mut file, "mod wgl_static_struct {{").unwrap(); 118 | wgl_registry 119 | .write_bindings(StaticStructGenerator, &mut file) 120 | .unwrap(); 121 | writeln!(&mut file, "}}").unwrap(); 122 | 123 | writeln!(&mut file, "mod wgl_debug_struct {{").unwrap(); 124 | wgl_registry 125 | .write_bindings(DebugStructGenerator, &mut file) 126 | .unwrap(); 127 | writeln!(&mut file, "}}").unwrap(); 128 | 129 | // Gles1 130 | 131 | let gles1_registry = Registry::new(Api::Gles1, (1, 1), Profile::Core, Fallbacks::All, []); 132 | 133 | writeln!(&mut file, "mod gles1_global {{").unwrap(); 134 | gles1_registry 135 | .write_bindings(GlobalGenerator, &mut file) 136 | .unwrap(); 137 | writeln!(&mut file, "}}").unwrap(); 138 | 139 | writeln!(&mut file, "mod gles1_static {{").unwrap(); 140 | gles1_registry 141 | .write_bindings(StaticGenerator, &mut file) 142 | .unwrap(); 143 | writeln!(&mut file, "}}").unwrap(); 144 | 145 | writeln!(&mut file, "mod gles1_struct {{").unwrap(); 146 | gles1_registry 147 | .write_bindings(StructGenerator, &mut file) 148 | .unwrap(); 149 | writeln!(&mut file, "}}").unwrap(); 150 | 151 | writeln!(&mut file, "mod gles1_static_struct {{").unwrap(); 152 | gles1_registry 153 | .write_bindings(StaticStructGenerator, &mut file) 154 | .unwrap(); 155 | writeln!(&mut file, "}}").unwrap(); 156 | 157 | writeln!(&mut file, "mod gles1_debug_struct {{").unwrap(); 158 | gles1_registry 159 | .write_bindings(DebugStructGenerator, &mut file) 160 | .unwrap(); 161 | writeln!(&mut file, "}}").unwrap(); 162 | 163 | // Gles2 164 | 165 | let gles2_registry = Registry::new(Api::Gles2, (3, 1), Profile::Core, Fallbacks::All, []); 166 | 167 | writeln!(&mut file, "mod gles2_global {{").unwrap(); 168 | gles2_registry 169 | .write_bindings(GlobalGenerator, &mut file) 170 | .unwrap(); 171 | writeln!(&mut file, "}}").unwrap(); 172 | 173 | writeln!(&mut file, "mod gles2_static {{").unwrap(); 174 | gles2_registry 175 | .write_bindings(StaticGenerator, &mut file) 176 | .unwrap(); 177 | writeln!(&mut file, "}}").unwrap(); 178 | 179 | writeln!(&mut file, "mod gles2_struct {{").unwrap(); 180 | gles2_registry 181 | .write_bindings(StructGenerator, &mut file) 182 | .unwrap(); 183 | writeln!(&mut file, "}}").unwrap(); 184 | 185 | writeln!(&mut file, "mod gles2_static_struct {{").unwrap(); 186 | gles2_registry 187 | .write_bindings(StaticStructGenerator, &mut file) 188 | .unwrap(); 189 | writeln!(&mut file, "}}").unwrap(); 190 | 191 | writeln!(&mut file, "mod gles2_debug_struct {{").unwrap(); 192 | gles2_registry 193 | .write_bindings(DebugStructGenerator, &mut file) 194 | .unwrap(); 195 | writeln!(&mut file, "}}").unwrap(); 196 | 197 | // Egl 198 | 199 | let egl_registry = Registry::new(Api::Egl, (1, 5), Profile::Core, Fallbacks::All, []); 200 | 201 | writeln!(&mut file, "mod egl_global {{ {}", build_egl_symbols()).unwrap(); 202 | egl_registry 203 | .write_bindings(GlobalGenerator, &mut file) 204 | .unwrap(); 205 | writeln!(&mut file, "}}").unwrap(); 206 | 207 | writeln!(&mut file, "mod egl_static {{ {}", build_egl_symbols()).unwrap(); 208 | egl_registry 209 | .write_bindings(StaticGenerator, &mut file) 210 | .unwrap(); 211 | writeln!(&mut file, "}}").unwrap(); 212 | 213 | writeln!(&mut file, "mod egl_struct {{ {}", build_egl_symbols()).unwrap(); 214 | egl_registry 215 | .write_bindings(StructGenerator, &mut file) 216 | .unwrap(); 217 | writeln!(&mut file, "}}").unwrap(); 218 | 219 | writeln!( 220 | &mut file, 221 | "mod egl_static_struct {{ {}", 222 | build_egl_symbols() 223 | ) 224 | .unwrap(); 225 | egl_registry 226 | .write_bindings(StaticStructGenerator, &mut file) 227 | .unwrap(); 228 | writeln!(&mut file, "}}").unwrap(); 229 | 230 | writeln!(&mut file, "mod egl_debug_struct {{ {}", build_egl_symbols()).unwrap(); 231 | egl_registry 232 | .write_bindings(DebugStructGenerator, &mut file) 233 | .unwrap(); 234 | writeln!(&mut file, "}}").unwrap(); 235 | } 236 | 237 | fn build_egl_symbols() -> &'static str { 238 | " 239 | #![allow(non_camel_case_types)] 240 | 241 | use std::os::raw; 242 | 243 | pub type khronos_utime_nanoseconds_t = raw::c_int; 244 | pub type khronos_uint64_t = u64; 245 | pub type khronos_ssize_t = isize; 246 | pub type EGLNativeDisplayType = *const raw::c_void; 247 | pub type EGLNativePixmapType = *const raw::c_void; 248 | pub type EGLNativeWindowType = *const raw::c_void; 249 | pub type EGLint = raw::c_int; 250 | pub type NativeDisplayType = *const raw::c_void; 251 | pub type NativePixmapType = *const raw::c_void; 252 | pub type NativeWindowType = *const raw::c_void; 253 | " 254 | } 255 | -------------------------------------------------------------------------------- /tests/test_no_warnings/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Making sure that no warning is generated by code from generate_gl_bindings! 16 | #![deny(warnings)] 17 | 18 | include!(concat!(env!("OUT_DIR"), "/test_no_warnings.rs")); 19 | -------------------------------------------------------------------------------- /tests/test_symbols/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_symbols" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | gl_generator = { path = "../../gl_generator" } 12 | -------------------------------------------------------------------------------- /tests/test_symbols/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::*; 18 | use std::env; 19 | use std::fs::File; 20 | use std::path::*; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file = File::create(&Path::new(&dest).join("test_symbols.rs")).unwrap(); 25 | 26 | Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []) 27 | .write_bindings(GlobalGenerator, &mut file) 28 | .unwrap(); 29 | } 30 | -------------------------------------------------------------------------------- /tests/test_symbols/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::os::raw; 16 | 17 | pub mod gl { 18 | include!(concat!(env!("OUT_DIR"), "/test_symbols.rs")); 19 | } 20 | 21 | pub fn compile_test_symbols_exist() { 22 | unsafe { 23 | gl::Clear(gl::COLOR_BUFFER_BIT); 24 | let _: raw::c_uint = gl::CreateProgram(); 25 | gl::CompileShader(5); 26 | gl::GetActiveUniformBlockiv( 27 | 0, 28 | 0, 29 | gl::UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER, 30 | std::ptr::null_mut(), 31 | ); 32 | } 33 | } 34 | 35 | #[test] 36 | fn test_fallback_works() { 37 | fn loader(name: &str) -> *const raw::c_void { 38 | match name { 39 | "glGenFramebuffers" => 0 as *const raw::c_void, 40 | "glGenFramebuffersEXT" => 42 as *const raw::c_void, 41 | name => panic!("test tried to load {} unexpectedly!", name), 42 | } 43 | }; 44 | 45 | gl::GenFramebuffers::load_with(loader); 46 | assert!(gl::GenFramebuffers::is_loaded()); 47 | } 48 | -------------------------------------------------------------------------------- /tests/test_unstable_api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_unstable_api" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies.gl_generator] 11 | path = "../../gl_generator" 12 | features = ["unstable_generator_utils"] 13 | -------------------------------------------------------------------------------- /tests/test_unstable_api/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::generators; 18 | 19 | fn main() { 20 | let _ = generators::gen_struct_name; 21 | let _ = generators::gen_enum_item::>; 22 | let _ = generators::gen_types::>; 23 | let _ = generators::gen_parameters; 24 | let _ = generators::gen_symbol_name; 25 | } 26 | -------------------------------------------------------------------------------- /tests/test_unstable_api/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | -------------------------------------------------------------------------------- /tests/test_webgl_stdweb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_webgl_stdweb" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [dependencies] 11 | stdweb = "0.4" 12 | stdweb-derive = "0.5" 13 | serde = "1.0" 14 | serde_derive = "1.0" 15 | 16 | [build-dependencies] 17 | webgl_generator = { path = "../../webgl_generator" } 18 | -------------------------------------------------------------------------------- /tests/test_webgl_stdweb/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate webgl_generator; 16 | 17 | use std::env; 18 | use std::fs::File; 19 | use std::path::*; 20 | use webgl_generator::*; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file1 = File::create(&Path::new(&dest).join("test_webgl_stdweb.rs")).unwrap(); 25 | let mut file2 = File::create(&Path::new(&dest).join("test_webgl2_stdweb.rs")).unwrap(); 26 | 27 | Registry::new(Api::WebGl, Exts::ALL) 28 | .write_bindings(StdwebGenerator, &mut file1) 29 | .unwrap(); 30 | 31 | Registry::new(Api::WebGl2, Exts::ALL) 32 | .write_bindings(StdwebGenerator, &mut file2) 33 | .unwrap(); 34 | } 35 | -------------------------------------------------------------------------------- /tests/test_webgl_stdweb/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![allow(unused_parens, non_camel_case_types)] 16 | 17 | #[macro_use] 18 | extern crate serde_derive; 19 | #[macro_use] 20 | extern crate stdweb; 21 | #[macro_use] 22 | extern crate stdweb_derive; 23 | 24 | mod webgl { 25 | include!(concat!(env!("OUT_DIR"), "/test_webgl_stdweb.rs")); 26 | } 27 | 28 | mod webgl2 { 29 | include!(concat!(env!("OUT_DIR"), "/test_webgl2_stdweb.rs")); 30 | } 31 | -------------------------------------------------------------------------------- /tests/test_with_extensions/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test_with_extensions" 3 | version = "0.0.0" 4 | build = "build.rs" 5 | publish = false 6 | 7 | [lib] 8 | path = "lib.rs" 9 | 10 | [build-dependencies] 11 | gl_generator = { path = "../../gl_generator" } 12 | -------------------------------------------------------------------------------- /tests/test_with_extensions/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate gl_generator; 16 | 17 | use gl_generator::*; 18 | use std::env; 19 | use std::fs::File; 20 | use std::path::*; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file = File::create(&Path::new(&dest).join("test_symbols.rs")).unwrap(); 25 | let extensions = ["GL_ARB_debug_output"]; 26 | 27 | Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, extensions) 28 | .write_bindings(GlobalGenerator, &mut file) 29 | .unwrap(); 30 | } 31 | -------------------------------------------------------------------------------- /tests/test_with_extensions/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | pub mod gl { 16 | include!(concat!(env!("OUT_DIR"), "/test_symbols.rs")); 17 | } 18 | 19 | pub fn compile_test_symbols_exist() { 20 | let _ = gl::DebugMessageControlARB; 21 | let _ = gl::DebugMessageInsertARB; 22 | let _ = gl::DebugMessageCallbackARB; 23 | let _ = gl::GetDebugMessageLogARB; 24 | 25 | assert_eq!(gl::DEBUG_OUTPUT_SYNCHRONOUS_ARB, 0x8242); 26 | assert_eq!(gl::MAX_DEBUG_MESSAGE_LENGTH_ARB, 0x9143); 27 | assert_eq!(gl::MAX_DEBUG_LOGGED_MESSAGES_ARB, 0x9144); 28 | assert_eq!(gl::DEBUG_LOGGED_MESSAGES_ARB, 0x9145); 29 | assert_eq!(gl::DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB, 0x8243); 30 | assert_eq!(gl::DEBUG_CALLBACK_FUNCTION_ARB, 0x8244); 31 | assert_eq!(gl::DEBUG_CALLBACK_USER_PARAM_ARB, 0x8245); 32 | assert_eq!(gl::DEBUG_SOURCE_API_ARB, 0x8246); 33 | assert_eq!(gl::DEBUG_SOURCE_WINDOW_SYSTEM_ARB, 0x8247); 34 | assert_eq!(gl::DEBUG_SOURCE_SHADER_COMPILER_ARB, 0x8248); 35 | assert_eq!(gl::DEBUG_SOURCE_THIRD_PARTY_ARB, 0x8249); 36 | assert_eq!(gl::DEBUG_SOURCE_APPLICATION_ARB, 0x824A); 37 | assert_eq!(gl::DEBUG_SOURCE_OTHER_ARB, 0x824B); 38 | assert_eq!(gl::DEBUG_TYPE_ERROR_ARB, 0x824C); 39 | assert_eq!(gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, 0x824D); 40 | assert_eq!(gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB, 0x824E); 41 | assert_eq!(gl::DEBUG_TYPE_PORTABILITY_ARB, 0x824F); 42 | assert_eq!(gl::DEBUG_TYPE_PERFORMANCE_ARB, 0x8250); 43 | assert_eq!(gl::DEBUG_TYPE_OTHER_ARB, 0x8251); 44 | assert_eq!(gl::DEBUG_SEVERITY_HIGH_ARB, 0x9146); 45 | assert_eq!(gl::DEBUG_SEVERITY_MEDIUM_ARB, 0x9147); 46 | assert_eq!(gl::DEBUG_SEVERITY_LOW_ARB, 0x9148); 47 | } 48 | -------------------------------------------------------------------------------- /webgl_generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webgl_generator" 3 | version = "0.2.0" 4 | authors = [ 5 | "Diggory Blake", 6 | ] 7 | description = "Code generators for creating bindings to the WebGL APIs." 8 | license = "Apache-2.0" 9 | documentation = "https://docs.rs/webgl_generator" 10 | homepage = "https://github.com/brendanzab/gl-rs/" 11 | repository = "https://github.com/brendanzab/gl-rs/" 12 | readme = "README.md" 13 | categories = ["api-bindings", "rendering::graphics-api"] 14 | keywords = ["webgl"] 15 | 16 | [lib] 17 | name = "webgl_generator" 18 | path = "lib.rs" 19 | 20 | [dependencies] 21 | khronos_api = { version = "3.1.0", path = "../khronos_api" } 22 | webidl = { version = "0.9" } 23 | heck = { version = "0.3" } 24 | RustyXML = "0.3" 25 | html2runes = "1.0" 26 | regex = "1.3" 27 | -------------------------------------------------------------------------------- /webgl_generator/README.md: -------------------------------------------------------------------------------- 1 | # webgl_generator 2 | 3 | [![Version](https://img.shields.io/crates/v/webgl_generator.svg)](https://crates.io/crates/webgl_generator) 4 | [![License](https://img.shields.io/crates/l/webgl_generator.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) 5 | [![Downloads](https://img.shields.io/crates/d/webgl_generator.svg)](https://crates.io/crates/webgl_generator) 6 | 7 | Code generators for creating bindings to the WebGL APIs. 8 | 9 | ## Usage 10 | 11 | See `tests/test_webgl_stdweb` for an example of how to use these generators. 12 | 13 | ## Generator types 14 | 15 | ### Stdweb generator 16 | 17 | The stdweb generator is currently the only supported webgl generator. This generator 18 | uses `stdweb` to bind the relevant javascript APIs, and integrates with the `stdweb` 19 | `RenderingContext` trait. 20 | 21 | ```toml 22 | [build-dependencies] 23 | webgl_generator = "0.2.0" 24 | ``` 25 | -------------------------------------------------------------------------------- /webgl_generator/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! A WebGL bindings generator. It defines a function named `Registry::write_bindings` which can be 16 | //! used to generate all constants and functions of a given WebGL version. 17 | //! 18 | //! See the `webgl` crate for an example of use. 19 | extern crate heck; 20 | extern crate html2runes; 21 | extern crate khronos_api; 22 | extern crate regex; 23 | extern crate webidl; 24 | extern crate xml; 25 | 26 | mod utils; 27 | mod webgl_generators; 28 | mod webgl_registry; 29 | 30 | pub use webgl_generators::stdweb_gen::StdwebGenerator; 31 | pub use webgl_generators::Generator; 32 | 33 | pub use webgl_registry::*; 34 | -------------------------------------------------------------------------------- /webgl_generator/utils.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::str; 3 | 4 | use webidl::{self, ast}; 5 | 6 | /// Helper method for inserting into a BTreeMap-based multi-map 7 | pub fn multimap_insert(m: &mut BTreeMap>, key: K, value: V) { 8 | let v = m.entry(key).or_insert_with(Vec::new); 9 | if !v.contains(&value) { 10 | v.push(value); 11 | } 12 | } 13 | 14 | /// Helper method for appending to a BTreeMap-based multi-map 15 | pub fn multimap_append( 16 | m: &mut BTreeMap>, 17 | other: BTreeMap>, 18 | ) { 19 | for (k, v) in other { 20 | for value in v { 21 | multimap_insert(m, k.clone(), value); 22 | } 23 | } 24 | } 25 | 26 | /// Best-effort attempt to render HTML into a doc-comment which can 27 | /// be placed in the generated code. 28 | pub fn convert_html_to_doc_comment(html: &str) -> String { 29 | use regex::RegexBuilder; 30 | 31 | // Create doc comments 32 | let doc_comment_regex = RegexBuilder::new("^").multi_line(true).build().unwrap(); 33 | 34 | let md = html2runes::markdown::convert_string(html); 35 | let mut doc = doc_comment_regex.replace_all(md.trim_end(), "/// ").into(); 36 | doc += "\n"; 37 | doc 38 | } 39 | 40 | /// Appends an underscore to a name if it conflicts with a reserved word. 41 | pub fn unreserve>(name: S) -> String { 42 | const RESERVED_WORDS: &'static [&'static str] = &[ 43 | "as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", 44 | "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", 45 | "return", "Self", "self", "static", "struct", "super", "trait", "true", "type", "unsafe", 46 | "use", "where", "while", "abstract", "alignof", "become", "box", "do", "final", "macro", 47 | "offsetof", "override", "priv", "proc", "pure", "sizeof", "typeof", "unsized", "virtual", 48 | "yield", 49 | ]; 50 | 51 | let mut s = name.into(); 52 | if RESERVED_WORDS.contains(&&*s) { 53 | s += "_"; 54 | } 55 | s 56 | } 57 | 58 | /// Converts to lower snake-case 59 | pub fn snake(name: &str) -> String { 60 | use heck::SnakeCase; 61 | name.to_snake_case() 62 | } 63 | 64 | /// Converts to upper snake-case 65 | pub fn shouty_snake(name: &str) -> String { 66 | use heck::ShoutySnakeCase; 67 | name.to_shouty_snake_case() 68 | } 69 | 70 | /// Converts to upper camel case 71 | pub fn camel(name: &str) -> String { 72 | use heck::CamelCase; 73 | name.to_camel_case() 74 | } 75 | 76 | /// Parse WebIDL content into an AST 77 | pub fn parse_defs(src: &[u8]) -> Vec { 78 | let src = str::from_utf8(src).expect("IDL contained invalid UTF-8"); 79 | 80 | match webidl::parse_string(src) { 81 | Ok(defs) => defs, 82 | Err(error) => panic!("Failed to parse IDL:\n{}\nError: {:?}", src, error), 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /webgl_generator/webgl_generators/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::io; 16 | 17 | use webgl_registry::Registry; 18 | 19 | pub mod stdweb_gen; 20 | 21 | /// Trait for a webgl bindings generator. 22 | pub trait Generator { 23 | /// Builds the WebGL bindings. 24 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 25 | where 26 | W: io::Write; 27 | } 28 | -------------------------------------------------------------------------------- /webgl_generator/webgl_generators/stdweb_gen.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::collections::BTreeSet; 16 | use std::io; 17 | 18 | use utils::*; 19 | use webgl_registry::*; 20 | 21 | #[allow(missing_copy_implementations)] 22 | #[derive(Debug)] 23 | pub struct StdwebGenerator; 24 | 25 | #[derive(Clone, Debug)] 26 | struct GenericContext { 27 | args: BTreeSet, 28 | constraints: Vec, 29 | } 30 | 31 | impl GenericContext { 32 | pub fn new() -> Self { 33 | GenericContext { 34 | args: BTreeSet::new(), 35 | constraints: Vec::new(), 36 | } 37 | } 38 | pub fn arg(&mut self, desired_name: &str) -> String { 39 | for i in 0.. { 40 | let name = format!("{}{}", desired_name, i); 41 | if !self.args.contains(&name) { 42 | self.args.insert(name.clone()); 43 | return name; 44 | } 45 | } 46 | unreachable!() 47 | } 48 | pub fn constrain(&mut self, constraint: String) { 49 | self.constraints.push(constraint); 50 | } 51 | pub fn args(&self) -> String { 52 | if self.args.is_empty() { 53 | String::new() 54 | } else { 55 | let args: Vec<_> = self.args.iter().cloned().collect(); 56 | format!("<{}>", args.join(", ")) 57 | } 58 | } 59 | pub fn constraints(&self) -> String { 60 | if self.constraints.is_empty() { 61 | String::new() 62 | } else { 63 | format!(" where {}", self.constraints.join(", ")) 64 | } 65 | } 66 | } 67 | 68 | #[derive(Clone, Debug)] 69 | enum ArgWrapper { 70 | None, 71 | AsTypedArray, 72 | AsArrayBufferView, 73 | Optional(Box), 74 | Sequence(Box), 75 | DoubleCast, 76 | Once, 77 | } 78 | 79 | impl ArgWrapper { 80 | fn wrap(&self, arg: &str) -> String { 81 | match self { 82 | &ArgWrapper::None => arg.into(), 83 | &ArgWrapper::AsTypedArray => format!("unsafe {{ {}.as_typed_array() }}", arg), 84 | &ArgWrapper::AsArrayBufferView => { 85 | format!("unsafe {{ {}.as_array_buffer_view() }}", arg) 86 | }, 87 | &ArgWrapper::Optional(ref inner) => { 88 | format!("{}.map(|inner| {})", arg, inner.wrap("inner")) 89 | }, 90 | &ArgWrapper::Sequence(ref inner) => format!( 91 | "{}.iter().map(|inner| {}).collect::>()", 92 | arg, 93 | inner.wrap("inner") 94 | ), 95 | &ArgWrapper::DoubleCast => format!("({} as f64)", arg), 96 | &ArgWrapper::Once => format!("Once({})", arg), 97 | } 98 | } 99 | } 100 | 101 | #[derive(Clone, Debug)] 102 | struct ProcessedArg { 103 | type_: String, 104 | wrapper: ArgWrapper, 105 | optional: bool, 106 | } 107 | 108 | impl ProcessedArg { 109 | fn simple>(name: S) -> ProcessedArg { 110 | ProcessedArg { 111 | type_: name.into(), 112 | wrapper: ArgWrapper::None, 113 | optional: false, 114 | } 115 | } 116 | } 117 | 118 | fn process_arg_type_kind( 119 | type_kind: &TypeKind, 120 | registry: &Registry, 121 | gc: &mut GenericContext, 122 | ) -> ProcessedArg { 123 | let (name, flat_kind) = type_kind.flatten(registry); 124 | match flat_kind { 125 | &TypeKind::Primitive(ref p) => match p { 126 | &Primitive::I64 => ProcessedArg { 127 | type_: name.unwrap().into(), 128 | wrapper: ArgWrapper::DoubleCast, 129 | optional: false, 130 | }, 131 | &Primitive::U64 => ProcessedArg { 132 | type_: name.unwrap().into(), 133 | wrapper: ArgWrapper::DoubleCast, 134 | optional: false, 135 | }, 136 | _ => ProcessedArg::simple(name.unwrap()), 137 | }, 138 | &TypeKind::String => ProcessedArg::simple("&str"), 139 | &TypeKind::ArrayBuffer => ProcessedArg::simple("&ArrayBuffer"), 140 | &TypeKind::BufferSource => ProcessedArg::simple("&ArrayBuffer"), 141 | &TypeKind::CanvasElement => ProcessedArg::simple("&CanvasElement"), 142 | &TypeKind::TypedArray(ref p) => { 143 | let lt = gc.arg("'a"); 144 | let gp = gc.arg("T"); 145 | gc.constrain(format!("{}: AsTypedArray<{}, {}>", gp, lt, p.name())); 146 | ProcessedArg { 147 | type_: gp, 148 | wrapper: ArgWrapper::AsTypedArray, 149 | optional: false, 150 | } 151 | }, 152 | &TypeKind::ArrayBufferView => { 153 | let lt = gc.arg("'a"); 154 | let gp = gc.arg("T"); 155 | gc.constrain(format!("{}: AsArrayBufferView<{}>", gp, lt)); 156 | ProcessedArg { 157 | type_: gp, 158 | wrapper: ArgWrapper::AsArrayBufferView, 159 | optional: false, 160 | } 161 | }, 162 | &TypeKind::Sequence(ref t) => { 163 | let inner = process_arg_type(t, registry, gc); 164 | ProcessedArg { 165 | type_: format!("&[{}]", inner.type_), 166 | wrapper: match inner.wrapper { 167 | ArgWrapper::None => ArgWrapper::None, 168 | other => ArgWrapper::Sequence(Box::new(other)), 169 | }, 170 | optional: false, 171 | } 172 | }, 173 | &TypeKind::Union(ref ts) => { 174 | let t = ts 175 | .iter() 176 | .filter_map(|t| match t.kind { 177 | TypeKind::TypedArray(_) => Some(t), 178 | TypeKind::Sequence(_) => None, 179 | _ => panic!("Union support is limited!"), 180 | }) 181 | .next() 182 | .expect("Union did not contain a TypedArray"); 183 | 184 | process_arg_type(t, registry, gc) 185 | }, 186 | &TypeKind::Named(ref actual_name) => { 187 | match registry.resolve_type(actual_name) { 188 | &NamedType::Dictionary(_) | &NamedType::Interface(_) => { 189 | ProcessedArg::simple(format!("&{}", name.unwrap())) 190 | }, 191 | &NamedType::Enum(_) => ProcessedArg::simple(name.unwrap()), 192 | &NamedType::Typedef(ref t) => { 193 | // We have to "look through" the typedef, as the correct parameter 194 | // type is not representable using the alias. 195 | assert!(t.optional); 196 | process_arg_type(t, registry, gc) 197 | }, 198 | &NamedType::Callback(_) => { 199 | let gp = gc.arg("F"); 200 | gc.constrain(format!("{}: FnOnce() + 'static", gp)); 201 | ProcessedArg { 202 | type_: gp, 203 | wrapper: ArgWrapper::Once, 204 | optional: false, 205 | } 206 | }, 207 | &NamedType::Mixin(_) => panic!("Mixins are not usable as types!"), 208 | } 209 | }, 210 | &TypeKind::Any | &TypeKind::Object => { 211 | let gp = gc.arg("T"); 212 | gc.constrain(format!("{}: JsSerialize", gp)); 213 | ProcessedArg::simple(gp) 214 | }, 215 | } 216 | } 217 | 218 | fn process_arg_type(type_: &Type, registry: &Registry, gc: &mut GenericContext) -> ProcessedArg { 219 | let mut result = process_arg_type_kind(&type_.kind, registry, gc); 220 | if type_.optional && !result.optional { 221 | result.type_ = format!("Option<{}>", result.type_); 222 | result.wrapper = match result.wrapper { 223 | ArgWrapper::None => ArgWrapper::None, 224 | other => ArgWrapper::Optional(Box::new(other)), 225 | }; 226 | result.optional = true; 227 | } 228 | result 229 | } 230 | 231 | #[derive(Clone, Debug)] 232 | enum ResultWrapper { 233 | TryInto, 234 | Ok, 235 | } 236 | 237 | impl ResultWrapper { 238 | fn wrap(&self, content: &str) -> String { 239 | match self { 240 | &ResultWrapper::TryInto => format!("{}.try_into().unwrap()", content), 241 | &ResultWrapper::Ok => format!("{}.try_into().ok()", content), 242 | } 243 | } 244 | } 245 | 246 | #[derive(Clone, Debug)] 247 | struct ProcessedResult { 248 | type_: String, 249 | wrapper: ResultWrapper, 250 | optional: bool, 251 | } 252 | 253 | impl ProcessedResult { 254 | fn simple>(name: S) -> ProcessedResult { 255 | ProcessedResult { 256 | type_: name.into(), 257 | wrapper: ResultWrapper::TryInto, 258 | optional: false, 259 | } 260 | } 261 | } 262 | 263 | fn process_result_type_kind(type_kind: &TypeKind, registry: &Registry) -> ProcessedResult { 264 | match type_kind { 265 | &TypeKind::Primitive(ref p) => ProcessedResult::simple(p.name()), 266 | &TypeKind::String => ProcessedResult::simple("String"), 267 | &TypeKind::ArrayBuffer | &TypeKind::ArrayBufferView => { 268 | ProcessedResult::simple("ArrayBuffer") 269 | }, 270 | &TypeKind::BufferSource => unimplemented!("BufferSource not supported in output"), 271 | &TypeKind::CanvasElement => ProcessedResult::simple("CanvasElement"), 272 | &TypeKind::TypedArray(ref p) => { 273 | ProcessedResult::simple(format!("TypedArray<{}>", p.name())) 274 | }, 275 | &TypeKind::Sequence(ref t) => { 276 | let inner = process_result_type(t, registry); 277 | ProcessedResult::simple(format!("Vec<{}>", inner.type_)) 278 | }, 279 | &TypeKind::Union(ref ts) => { 280 | let t = ts 281 | .iter() 282 | .filter_map(|t| match t.kind { 283 | TypeKind::TypedArray(_) => Some(t), 284 | TypeKind::Sequence(_) => None, 285 | _ => panic!("Union support is limited!"), 286 | }) 287 | .next() 288 | .expect("Union did not contain a TypedArray"); 289 | 290 | process_result_type(t, registry) 291 | }, 292 | &TypeKind::Named(ref name) => match registry.resolve_type(name) { 293 | &NamedType::Dictionary(_) | &NamedType::Interface(_) | &NamedType::Enum(_) => { 294 | ProcessedResult::simple(name.as_str()) 295 | }, 296 | &NamedType::Typedef(ref t) => { 297 | let inner = process_result_type(t, registry); 298 | ProcessedResult { 299 | type_: name.clone(), 300 | wrapper: inner.wrapper.clone(), 301 | optional: inner.optional, 302 | } 303 | }, 304 | &NamedType::Callback(_) => unimplemented!(), 305 | &NamedType::Mixin(_) => panic!("Mixins are not usable as types!"), 306 | }, 307 | &TypeKind::Any | &TypeKind::Object => ProcessedResult::simple("Value"), 308 | } 309 | } 310 | 311 | fn process_result_type(type_: &Type, registry: &Registry) -> ProcessedResult { 312 | let mut result = process_result_type_kind(&type_.kind, registry); 313 | if type_.optional && !result.optional { 314 | result.type_ = format!("Option<{}>", result.type_); 315 | result.wrapper = ResultWrapper::Ok; 316 | result.optional = true; 317 | } 318 | result 319 | } 320 | 321 | fn write_header(registry: &Registry, dest: &mut W) -> io::Result<()> 322 | where 323 | W: io::Write, 324 | { 325 | writeln!( 326 | dest, 327 | r#" 328 | // {registry:?} 329 | extern crate stdweb; 330 | 331 | use self::stdweb::{{Reference, Value, UnsafeTypedArray, JsSerialize, InstanceOf}}; 332 | use self::stdweb::unstable::{{TryFrom, TryInto}}; 333 | use self::stdweb::web::{{RenderingContext, TypedArray, ArrayBuffer}}; 334 | use self::stdweb::web::html_element::CanvasElement; 335 | 336 | type ConversionError = >::Error; 337 | 338 | pub trait AsTypedArray<'a, T> {{ 339 | type Result: JsSerialize; 340 | 341 | unsafe fn as_typed_array(self) -> Self::Result; 342 | }} 343 | 344 | pub trait AsArrayBufferView<'a> {{ 345 | type Result: JsSerialize; 346 | 347 | unsafe fn as_array_buffer_view(self) -> Self::Result; 348 | }} 349 | 350 | pub trait Extension: TryFrom {{ 351 | const NAME: &'static str; 352 | }} 353 | 354 | macro_rules! define_array {{ 355 | ($elem:ty) => {{ 356 | impl<'a> AsTypedArray<'a, $elem> for &'a TypedArray<$elem> {{ 357 | type Result = Self; 358 | 359 | unsafe fn as_typed_array(self) -> Self::Result {{ self }} 360 | }} 361 | 362 | impl<'a> AsTypedArray<'a, $elem> for &'a [$elem] {{ 363 | type Result = UnsafeTypedArray<'a, $elem>; 364 | 365 | unsafe fn as_typed_array(self) -> Self::Result {{ UnsafeTypedArray::new(self) }} 366 | }} 367 | 368 | impl<'a> AsArrayBufferView<'a> for &'a TypedArray<$elem> {{ 369 | type Result = Self; 370 | 371 | unsafe fn as_array_buffer_view(self) -> Self::Result {{ self }} 372 | }} 373 | 374 | impl<'a> AsArrayBufferView<'a> for &'a [$elem] {{ 375 | type Result = UnsafeTypedArray<'a, $elem>; 376 | 377 | unsafe fn as_array_buffer_view(self) -> Self::Result {{ UnsafeTypedArray::new(self) }} 378 | }} 379 | }} 380 | }} 381 | 382 | define_array!(i8); 383 | define_array!(u8); 384 | define_array!(i16); 385 | define_array!(u16); 386 | define_array!(i32); 387 | define_array!(u32); 388 | define_array!(f32); 389 | define_array!(f64); 390 | "#, 391 | registry = registry 392 | )?; 393 | Ok(()) 394 | } 395 | 396 | impl super::Generator for StdwebGenerator { 397 | fn write(&self, registry: &Registry, dest: &mut W) -> io::Result<()> 398 | where 399 | W: io::Write, 400 | { 401 | write_header(registry, dest)?; 402 | write_typedefs(registry, dest)?; 403 | write_enums(registry, dest)?; 404 | write_dictionaries(registry, dest)?; 405 | write_interfaces(registry, dest)?; 406 | write_extensions(registry, dest)?; 407 | Ok(()) 408 | } 409 | } 410 | 411 | fn write_typedefs(registry: &Registry, dest: &mut W) -> io::Result<()> 412 | where 413 | W: io::Write, 414 | { 415 | for (name, t) in registry.iter_types(NamedType::as_typedef) { 416 | write_typedef(name, t, registry, dest)?; 417 | } 418 | Ok(()) 419 | } 420 | 421 | fn write_typedef(name: &str, type_: &Type, registry: &Registry, dest: &mut W) -> io::Result<()> 422 | where 423 | W: io::Write, 424 | { 425 | writeln!( 426 | dest, 427 | r#"#[allow(dead_code)] pub type {name} = {type_};"#, 428 | name = name, 429 | type_ = process_result_type(type_, registry).type_ 430 | )?; 431 | Ok(()) 432 | } 433 | 434 | fn write_enums(registry: &Registry, dest: &mut W) -> io::Result<()> 435 | where 436 | W: io::Write, 437 | { 438 | for (name, enum_) in registry.iter_types(NamedType::as_enum) { 439 | write_enum(name, enum_, registry, dest)?; 440 | } 441 | Ok(()) 442 | } 443 | 444 | fn write_enum(name: &str, enum_: &Enum, _registry: &Registry, dest: &mut W) -> io::Result<()> 445 | where 446 | W: io::Write, 447 | { 448 | write!( 449 | dest, 450 | r#" 451 | #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 452 | pub enum {name} {{ 453 | "#, 454 | name = name 455 | )?; 456 | 457 | for variant in &enum_.variants { 458 | writeln!( 459 | dest, 460 | r#" 461 | #[serde(rename = "{raw_variant}")] 462 | {variant},"#, 463 | variant = camel(&variant), 464 | raw_variant = variant 465 | )?; 466 | } 467 | 468 | writeln!( 469 | dest, 470 | r#" 471 | }} 472 | js_deserializable!({name}); 473 | js_serializable!({name}); 474 | "#, 475 | name = name 476 | )?; 477 | Ok(()) 478 | } 479 | 480 | fn write_dictionaries(registry: &Registry, dest: &mut W) -> io::Result<()> 481 | where 482 | W: io::Write, 483 | { 484 | for (name, dictionary) in registry.iter_types(NamedType::as_dictionary) { 485 | write_dictionary(name, dictionary, registry, dest)?; 486 | } 487 | Ok(()) 488 | } 489 | 490 | fn write_dictionary( 491 | name: &str, 492 | dictionary: &Dictionary, 493 | registry: &Registry, 494 | dest: &mut W, 495 | ) -> io::Result<()> 496 | where 497 | W: io::Write, 498 | { 499 | if dictionary.is_hidden { 500 | return Ok(()); 501 | } 502 | 503 | write!( 504 | dest, 505 | r#" 506 | #[derive(Debug, Clone, Serialize, Deserialize)] 507 | pub struct {name} {{ 508 | "#, 509 | name = name 510 | )?; 511 | 512 | for (name, field) in dictionary.collect_fields(registry) { 513 | write_field(name, field, registry, dest)?; 514 | } 515 | 516 | writeln!( 517 | dest, 518 | r#" 519 | }} 520 | js_deserializable!({name}); 521 | js_serializable!({name}); 522 | "#, 523 | name = name 524 | )?; 525 | Ok(()) 526 | } 527 | 528 | fn write_field(name: &str, field: &Field, registry: &Registry, dest: &mut W) -> io::Result<()> 529 | where 530 | W: io::Write, 531 | { 532 | let mut serde_attrs = Vec::new(); 533 | let field_name = unreserve(snake(name)); 534 | if field_name != name { 535 | serde_attrs.push(format!(r#"rename = "{}""#, name)); 536 | } 537 | let field_type = process_result_type(&field.type_, registry); 538 | if field_type.optional { 539 | serde_attrs.push(r#"default"#.into()); 540 | serde_attrs.push(r#"skip_serializing_if = "Option::is_none""#.into()); 541 | } 542 | 543 | if !serde_attrs.is_empty() { 544 | write!( 545 | dest, 546 | r#" 547 | #[serde({})]"#, 548 | serde_attrs.join(", ") 549 | )?; 550 | } 551 | 552 | writeln!( 553 | dest, 554 | r#" 555 | {name}: {type_},"#, 556 | name = field_name, 557 | type_ = field_type.type_ 558 | )?; 559 | 560 | Ok(()) 561 | } 562 | 563 | fn write_interfaces(registry: &Registry, dest: &mut W) -> io::Result<()> 564 | where 565 | W: io::Write, 566 | { 567 | for (name, interface) in registry.iter_types(NamedType::as_interface) { 568 | write_interface(name, interface, registry, dest)?; 569 | } 570 | Ok(()) 571 | } 572 | 573 | fn write_interface( 574 | name: &str, 575 | interface: &Interface, 576 | registry: &Registry, 577 | dest: &mut W, 578 | ) -> io::Result<()> 579 | where 580 | W: io::Write, 581 | { 582 | if interface.is_hidden { 583 | return Ok(()); 584 | } 585 | 586 | let mut attrs = String::new(); 587 | let custom_instance_check = if name == "GLContext" { 588 | Some(( 589 | "reference", 590 | "[WebGLRenderingContext, WebGL2RenderingContext].includes(@{{reference}}.constructor)" 591 | .into(), 592 | )) 593 | } else if interface.has_class { 594 | attrs += &format!("#[reference(instance_of = {:?})]\n", name); 595 | None 596 | } else { 597 | Some(("_reference", "true".to_owned())) 598 | }; 599 | 600 | write!( 601 | dest, 602 | r#" 603 | {doc_comment}#[derive(Debug, Clone, ReferenceType)] 604 | {attrs}pub struct {name}(Reference); 605 | 606 | impl {name} {{ 607 | "#, 608 | name = name, 609 | attrs = attrs, 610 | doc_comment = interface.doc_comment 611 | )?; 612 | 613 | for (name, members) in interface.collect_members(registry, &VisitOptions::default()) { 614 | for (index, member) in members.into_iter().enumerate() { 615 | match member { 616 | &Member::Const(ref const_) => { 617 | assert!(index == 0); 618 | write_const(&name, const_, registry, dest)?; 619 | }, 620 | &Member::Attribute(ref attribute) => { 621 | assert!(index == 0); 622 | write_attribute(&name, attribute, registry, dest)?; 623 | }, 624 | &Member::Operation(ref operation) => { 625 | write_operation(&name, index, operation, registry, dest)?; 626 | }, 627 | } 628 | } 629 | } 630 | 631 | writeln!( 632 | dest, 633 | r#" 634 | }} 635 | "# 636 | )?; 637 | 638 | if let Some((param_name, instance_check)) = custom_instance_check { 639 | write!( 640 | dest, 641 | r#" 642 | impl InstanceOf for {name} {{ 643 | #[inline] 644 | fn instance_of({param_name}: &Reference) -> bool {{ 645 | js!( 646 | return {instance_check}; 647 | ).try_into().unwrap() 648 | }} 649 | }} 650 | "#, 651 | param_name = param_name, 652 | name = name, 653 | instance_check = instance_check 654 | )?; 655 | } 656 | 657 | if let Some(rendering_context) = interface.rendering_context { 658 | writeln!( 659 | dest, 660 | r#"impl RenderingContext for {name} {{ 661 | type Error = ConversionError; 662 | fn from_canvas(canvas: &CanvasElement) -> Result {{ 663 | js!( 664 | return @{{canvas}}.getContext("{rendering_context}"); 665 | ).try_into() 666 | }} 667 | }} 668 | "#, 669 | name = name, 670 | rendering_context = rendering_context 671 | )?; 672 | } 673 | 674 | Ok(()) 675 | } 676 | 677 | fn write_const(name: &str, const_: &Const, registry: &Registry, dest: &mut W) -> io::Result<()> 678 | where 679 | W: io::Write, 680 | { 681 | let const_type = process_result_type(&const_.type_, registry); 682 | write!( 683 | dest, 684 | r#" 685 | pub const {name}: {type_} = {value};"#, 686 | name = shouty_snake(name), 687 | type_ = const_type.type_, 688 | value = const_.value 689 | )?; 690 | Ok(()) 691 | } 692 | 693 | fn write_attribute( 694 | name: &str, 695 | attribute: &Attribute, 696 | registry: &Registry, 697 | dest: &mut W, 698 | ) -> io::Result<()> 699 | where 700 | W: io::Write, 701 | { 702 | if attribute.getter { 703 | let result_type = process_result_type(&attribute.type_, registry); 704 | let expr = result_type.wrapper.wrap(&format!( 705 | "(js! {{ return @{{self}}.{raw_name}; }} )", 706 | raw_name = name 707 | )); 708 | 709 | write!( 710 | dest, 711 | r#" 712 | 713 | pub fn {name}(&self) -> {type_} {{ 714 | {expr} 715 | }}"#, 716 | name = unreserve(snake(name)), 717 | type_ = result_type.type_, 718 | expr = expr 719 | )?; 720 | } 721 | if attribute.setter { 722 | let mut gc = GenericContext::new(); 723 | let arg_type = process_arg_type(&attribute.type_, registry, &mut gc); 724 | write!( 725 | dest, 726 | r#" 727 | 728 | pub fn set_{name}{gargs}(&self, value: {type_}){gwhere} {{ 729 | js!( @(no_return) @{{self}}.{raw_name} = @{{{value}}}; ); 730 | }}"#, 731 | name = snake(name), 732 | raw_name = name, 733 | type_ = arg_type.type_, 734 | gargs = gc.args(), 735 | gwhere = gc.constraints(), 736 | value = arg_type.wrapper.wrap("value") 737 | )?; 738 | } 739 | Ok(()) 740 | } 741 | 742 | fn write_get_extension(dest: &mut W) -> io::Result<()> 743 | where 744 | W: io::Write, 745 | { 746 | write!( 747 | dest, 748 | r#" 749 | 750 | pub fn get_extension(&self) -> Option {{ 751 | (js! {{ return @{{self}}.getExtension(@{{E::NAME}}); }} ).try_into().ok() 752 | }}"# 753 | ) 754 | } 755 | 756 | fn write_operation( 757 | name: &str, 758 | index: usize, 759 | operation: &Operation, 760 | registry: &Registry, 761 | dest: &mut W, 762 | ) -> io::Result<()> 763 | where 764 | W: io::Write, 765 | { 766 | match name { 767 | "getExtension" => return write_get_extension(dest), 768 | _ => {}, 769 | } 770 | 771 | let mut rust_name = unreserve(snake(name)); 772 | if index > 0 { 773 | rust_name = format!("{}_{}", rust_name, index); 774 | } 775 | 776 | let mut gc = GenericContext::new(); 777 | 778 | struct OperationArg { 779 | arg: String, 780 | js_arg: String, 781 | } 782 | 783 | let args: Vec<_> = operation 784 | .args 785 | .iter() 786 | .map(|a| { 787 | let processed = process_arg_type(&a.type_, registry, &mut gc); 788 | let arg = format!("{}: {}", unreserve(snake(&a.name)), processed.type_); 789 | let js_arg = format!( 790 | "@{{{}}}", 791 | processed.wrapper.wrap(&unreserve(snake(&a.name))) 792 | ); 793 | OperationArg { arg, js_arg } 794 | }) 795 | .collect(); 796 | 797 | let rust_args = args 798 | .iter() 799 | .map(|a| a.arg.clone()) 800 | .collect::>() 801 | .join(", "); 802 | let js_args = args 803 | .iter() 804 | .map(|a| a.js_arg.clone()) 805 | .collect::>() 806 | .join(", "); 807 | 808 | if let Some(return_type) = operation.return_type.as_ref() { 809 | let result_type = process_result_type(return_type, registry); 810 | let expr = result_type.wrapper.wrap(&format!( 811 | "(js! {{ return @{{self}}.{raw_name}({js_args}); }} )", 812 | raw_name = name, 813 | js_args = js_args 814 | )); 815 | 816 | write!( 817 | dest, 818 | r#" 819 | 820 | {doc_comment}pub fn {name}{gargs}(&self, {args}) -> {return_type}{gwhere} {{ 821 | {expr} 822 | }}"#, 823 | name = rust_name, 824 | gargs = gc.args(), 825 | args = rust_args, 826 | return_type = result_type.type_, 827 | gwhere = gc.constraints(), 828 | expr = expr, 829 | doc_comment = operation.doc_comment 830 | )?; 831 | } else { 832 | write!( 833 | dest, 834 | r#" 835 | 836 | {doc_comment}pub fn {name}{gargs}(&self, {args}){gwhere} {{ 837 | js!( @(no_return) @{{self}}.{raw_name}({js_args}); ); 838 | }}"#, 839 | name = rust_name, 840 | raw_name = name, 841 | gargs = gc.args(), 842 | args = rust_args, 843 | gwhere = gc.constraints(), 844 | js_args = js_args, 845 | doc_comment = operation.doc_comment 846 | )?; 847 | } 848 | Ok(()) 849 | } 850 | 851 | fn write_extensions(registry: &Registry, dest: &mut W) -> io::Result<()> 852 | where 853 | W: io::Write, 854 | { 855 | for name in ®istry.extensions { 856 | write_extension(name, registry, dest)?; 857 | } 858 | Ok(()) 859 | } 860 | 861 | fn write_extension(name: &str, _registry: &Registry, dest: &mut W) -> io::Result<()> 862 | where 863 | W: io::Write, 864 | { 865 | writeln!( 866 | dest, 867 | r#" 868 | impl Extension for {name} {{ 869 | const NAME: &'static str = "{name}"; 870 | }}"#, 871 | name = name 872 | ) 873 | } 874 | -------------------------------------------------------------------------------- /webgl_generator/webgl_registry/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::collections::BTreeMap; 16 | use std::{fmt, str}; 17 | 18 | use khronos_api; 19 | 20 | use utils::convert_html_to_doc_comment; 21 | 22 | pub use self::named::*; 23 | pub use self::registry::*; 24 | pub use self::types::*; 25 | 26 | mod named; 27 | mod registry; 28 | mod types; 29 | 30 | const HIDDEN_NAMES: &'static [&'static str] = &["WebGLObject", "WebGLContextEventInit"]; 31 | const RENDERING_CONTEXTS: &'static [(&'static str, &'static str)] = &[ 32 | ("webgl", "WebGLRenderingContext"), 33 | ("webgl2", "WebGL2RenderingContext"), 34 | ]; 35 | 36 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] 37 | pub enum Api { 38 | WebGl, 39 | WebGl2, 40 | } 41 | 42 | #[derive(Debug)] 43 | struct ExtensionIDL { 44 | pub name: String, 45 | pub idl: String, 46 | pub overview: String, 47 | pub new_funs: BTreeMap, 48 | pub min_api: Api, 49 | } 50 | 51 | pub enum Exts<'a> { 52 | Include(&'a [&'a str]), 53 | Exclude(&'a [&'a str]), 54 | } 55 | 56 | impl<'a> Exts<'a> { 57 | pub const NONE: Exts<'a> = Exts::Include(&[]); 58 | pub const ALL: Exts<'a> = Exts::Exclude(&[]); 59 | 60 | fn enumerate(&self) -> Vec { 61 | use regex::{Regex, RegexBuilder}; 62 | 63 | // The Khronos IDL files are... not quite right, so let's fix them up! 64 | let enum_regex = Regex::new("([(, ])enum\\b").unwrap(); 65 | let missing_semicolon_regex = RegexBuilder::new("^}$").multi_line(true).build().unwrap(); 66 | let shared_callback_regex = Regex::new("\\bAcquireResourcesCallback\\b").unwrap(); 67 | 68 | let mut result = Vec::new(); 69 | for &ext_xml in khronos_api::WEBGL_EXT_XML { 70 | let elem: xml::Element = str::from_utf8(ext_xml).unwrap().parse().unwrap(); 71 | 72 | let overview_html = format!("{}", elem.get_child("overview", None).unwrap()); 73 | 74 | let mut new_funs = BTreeMap::new(); 75 | for new_fun in elem.get_children("newfun", None) { 76 | for f in new_fun.get_children("function", None) { 77 | let name = f.get_attribute("name", None).unwrap().into(); 78 | let f_html = format!("{}", f); 79 | new_funs.insert(name, convert_html_to_doc_comment(&f_html)); 80 | } 81 | } 82 | 83 | let dependencies = elem.get_child("depends", None).unwrap(); 84 | let api_dep = dependencies.get_child("api", None).unwrap(); 85 | 86 | let mut ext = ExtensionIDL { 87 | name: elem.get_child("name", None).unwrap().content_str(), 88 | idl: elem.get_child("idl", None).unwrap().content_str(), 89 | overview: format!( 90 | "/// Extension\n/// \n{}", 91 | convert_html_to_doc_comment(&overview_html) 92 | ), 93 | new_funs, 94 | min_api: match api_dep.get_attribute("version", None).unwrap() { 95 | "1.0" => Api::WebGl, 96 | "2.0" => Api::WebGl2, 97 | other => panic!("Unknown API version: {}", other), 98 | }, 99 | }; 100 | 101 | if match self { 102 | &Exts::Include(names) => names.contains(&&*ext.name), 103 | &Exts::Exclude(names) => !names.contains(&&*ext.name), 104 | } { 105 | ext.idl = enum_regex.replace_all(&ext.idl, "${1}GLenum").into(); 106 | ext.idl = missing_semicolon_regex.replace_all(&ext.idl, "};").into(); 107 | ext.idl = shared_callback_regex 108 | .replace_all(&ext.idl, "AcquireSharedResourcesCallback") 109 | .into(); 110 | result.push(ext); 111 | } 112 | } 113 | 114 | result 115 | } 116 | } 117 | 118 | impl Api { 119 | fn idl_consts(&self) -> &'static [&'static [u8]] { 120 | match *self { 121 | Api::WebGl => &[khronos_api::WEBGL_IDL], 122 | Api::WebGl2 => &[khronos_api::WEBGL_IDL, khronos_api::WEBGL2_IDL], 123 | } 124 | } 125 | } 126 | 127 | impl fmt::Display for Api { 128 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 129 | match *self { 130 | Api::WebGl => write!(fmt, "webgl"), 131 | Api::WebGl2 => write!(fmt, "webgl2"), 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /webgl_generator/webgl_registry/named.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::collections::{BTreeMap, BTreeSet}; 16 | 17 | use super::{Registry, Type}; 18 | use utils::{multimap_append, multimap_insert}; 19 | 20 | #[derive(Debug, Clone)] 21 | pub enum NamedType { 22 | Mixin(Mixin), 23 | Interface(Interface), 24 | Dictionary(Dictionary), 25 | Enum(Enum), 26 | Typedef(Type), 27 | Callback(Callback), 28 | } 29 | 30 | #[derive(Debug, Clone)] 31 | pub struct Mixin { 32 | pub members: BTreeMap>, 33 | } 34 | 35 | #[derive(Debug, Clone)] 36 | pub struct Interface { 37 | pub inherits: Option, 38 | pub mixins: BTreeSet, 39 | pub members: BTreeMap>, 40 | pub is_hidden: bool, 41 | pub has_class: bool, 42 | pub rendering_context: Option<&'static str>, 43 | pub doc_comment: String, 44 | } 45 | 46 | #[derive(Debug, Clone)] 47 | pub struct Dictionary { 48 | pub inherits: Option, 49 | pub fields: BTreeMap, 50 | pub is_hidden: bool, 51 | } 52 | 53 | #[derive(Debug, Clone)] 54 | pub struct Enum { 55 | pub variants: BTreeSet, 56 | } 57 | 58 | #[derive(Debug, PartialEq, Eq, Clone)] 59 | pub struct Callback { 60 | pub args: Vec, 61 | pub return_type: Option, 62 | } 63 | 64 | #[derive(Debug, PartialEq, Eq, Clone)] 65 | pub struct Const { 66 | pub type_: Type, 67 | pub value: String, 68 | } 69 | 70 | #[derive(Debug, Eq, Clone)] 71 | pub struct Argument { 72 | pub name: String, 73 | pub optional: bool, 74 | pub type_: Type, 75 | pub variadic: bool, 76 | } 77 | 78 | #[derive(Debug, PartialEq, Eq, Clone)] 79 | pub struct Operation { 80 | pub args: Vec, 81 | pub return_type: Option, 82 | pub doc_comment: String, 83 | } 84 | 85 | #[derive(Debug, PartialEq, Eq, Clone)] 86 | pub struct Attribute { 87 | pub type_: Type, 88 | pub setter: bool, 89 | pub getter: bool, 90 | } 91 | 92 | #[derive(Debug, PartialEq, Eq, Clone)] 93 | pub enum Member { 94 | Const(Const), 95 | Operation(Operation), 96 | Attribute(Attribute), 97 | } 98 | 99 | #[derive(Debug, Clone)] 100 | pub struct Field { 101 | pub type_: Type, 102 | } 103 | 104 | #[derive(Debug)] 105 | pub struct VisitOptions { 106 | pub visit_mixins: bool, 107 | } 108 | 109 | impl NamedType { 110 | pub fn as_mixin(&self) -> Option<&Mixin> { 111 | if let &NamedType::Mixin(ref m) = self { 112 | Some(m) 113 | } else { 114 | None 115 | } 116 | } 117 | pub fn as_interface(&self) -> Option<&Interface> { 118 | if let &NamedType::Interface(ref i) = self { 119 | Some(i) 120 | } else { 121 | None 122 | } 123 | } 124 | pub fn as_dictionary(&self) -> Option<&Dictionary> { 125 | if let &NamedType::Dictionary(ref d) = self { 126 | Some(d) 127 | } else { 128 | None 129 | } 130 | } 131 | pub fn as_enum(&self) -> Option<&Enum> { 132 | if let &NamedType::Enum(ref e) = self { 133 | Some(e) 134 | } else { 135 | None 136 | } 137 | } 138 | pub fn as_typedef(&self) -> Option<&Type> { 139 | if let &NamedType::Typedef(ref t) = self { 140 | Some(t) 141 | } else { 142 | None 143 | } 144 | } 145 | pub fn as_mixin_mut(&mut self) -> Option<&mut Mixin> { 146 | if let &mut NamedType::Mixin(ref mut m) = self { 147 | Some(m) 148 | } else { 149 | None 150 | } 151 | } 152 | pub fn as_interface_mut(&mut self) -> Option<&mut Interface> { 153 | if let &mut NamedType::Interface(ref mut i) = self { 154 | Some(i) 155 | } else { 156 | None 157 | } 158 | } 159 | pub fn as_dictionary_mut(&mut self) -> Option<&mut Dictionary> { 160 | if let &mut NamedType::Dictionary(ref mut d) = self { 161 | Some(d) 162 | } else { 163 | None 164 | } 165 | } 166 | pub fn as_enum_mut(&mut self) -> Option<&mut Enum> { 167 | if let &mut NamedType::Enum(ref mut e) = self { 168 | Some(e) 169 | } else { 170 | None 171 | } 172 | } 173 | pub fn as_typedef_mut(&mut self) -> Option<&mut Type> { 174 | if let &mut NamedType::Typedef(ref mut t) = self { 175 | Some(t) 176 | } else { 177 | None 178 | } 179 | } 180 | } 181 | 182 | impl PartialEq for Argument { 183 | fn eq(&self, other: &Self) -> bool { 184 | self.type_ == other.type_ 185 | } 186 | } 187 | 188 | impl Default for VisitOptions { 189 | fn default() -> Self { 190 | VisitOptions { visit_mixins: true } 191 | } 192 | } 193 | 194 | impl Dictionary { 195 | pub fn collect_fields<'a>(&'a self, registry: &'a Registry) -> BTreeMap<&'a str, &'a Field> { 196 | let mut fields = BTreeMap::new(); 197 | 198 | // Inherits 199 | if let Some(inherit_name) = self.inherits.as_ref() { 200 | let inherit = registry 201 | .types 202 | .get(inherit_name) 203 | .and_then(NamedType::as_dictionary) 204 | .expect(inherit_name); 205 | fields.append(&mut inherit.collect_fields(registry)); 206 | } 207 | 208 | // Fields 209 | for (name, field) in &self.fields { 210 | fields.insert(name, field); 211 | } 212 | 213 | fields 214 | } 215 | } 216 | 217 | impl Interface { 218 | pub fn collect_members<'a>( 219 | &'a self, 220 | registry: &'a Registry, 221 | options: &VisitOptions, 222 | ) -> BTreeMap<&'a str, Vec<&'a Member>> { 223 | let mut members = BTreeMap::new(); 224 | 225 | // Mixins 226 | for mixin_name in &self.mixins { 227 | let mixin = registry 228 | .types 229 | .get(mixin_name) 230 | .and_then(NamedType::as_mixin) 231 | .expect(mixin_name); 232 | if options.visit_mixins { 233 | multimap_append(&mut members, mixin.collect_members(registry, options)); 234 | } 235 | } 236 | 237 | // Members 238 | for (name, ms) in &self.members { 239 | for member in ms { 240 | multimap_insert(&mut members, &**name, member); 241 | } 242 | } 243 | 244 | members 245 | } 246 | } 247 | 248 | impl Mixin { 249 | pub fn collect_members<'a>( 250 | &'a self, 251 | _registry: &'a Registry, 252 | _options: &VisitOptions, 253 | ) -> BTreeMap<&'a str, Vec<&'a Member>> { 254 | let mut members = BTreeMap::new(); 255 | 256 | // Members 257 | for (name, ms) in &self.members { 258 | for member in ms { 259 | multimap_insert(&mut members, &**name, member); 260 | } 261 | } 262 | 263 | members 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /webgl_generator/webgl_registry/registry.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::collections::btree_map::{self, Entry}; 16 | use std::collections::{BTreeMap, BTreeSet}; 17 | use std::io; 18 | 19 | use webidl::ast; 20 | 21 | use utils::{multimap_insert, parse_defs}; 22 | use webgl_generators::Generator; 23 | 24 | use super::named::{ 25 | Argument, Attribute, Callback, Const, Dictionary, Enum, Field, Interface, Member, Mixin, 26 | NamedType, Operation, 27 | }; 28 | use super::types::{Primitive, Type, TypeKind}; 29 | use super::{Api, Exts, HIDDEN_NAMES, RENDERING_CONTEXTS}; 30 | 31 | #[derive(Debug, Default)] 32 | pub struct Registry { 33 | pub types: BTreeMap, 34 | pub extensions: BTreeSet, 35 | } 36 | 37 | /// Helper for iterating over specific kinds of named type 38 | pub struct TypeIter<'a, T: 'a, F: FnMut(&'a NamedType) -> Option<&'a T>> { 39 | inner: btree_map::Iter<'a, String, NamedType>, 40 | f: F, 41 | } 42 | 43 | impl<'a, T: 'a, F: FnMut(&'a NamedType) -> Option<&'a T>> Iterator for TypeIter<'a, T, F> { 44 | type Item = (&'a String, &'a T); 45 | fn next(&mut self) -> Option { 46 | // Implement a variation of `flat_map` 47 | while let Some((k, v)) = self.inner.next() { 48 | if let Some(t) = (self.f)(v) { 49 | return Some((k, t)); 50 | } 51 | } 52 | None 53 | } 54 | } 55 | 56 | impl Registry { 57 | /// Construct a new registry given a maximum API version 58 | /// and a set of extensions to support. 59 | pub fn new(api: Api, exts: Exts) -> Registry { 60 | let mut result = Registry::default(); 61 | 62 | // First load definitions from all API versions 63 | // up to the one requested. 64 | for idl_const in api.idl_consts() { 65 | for def in parse_defs(idl_const) { 66 | result.load_definition(def); 67 | } 68 | } 69 | 70 | // Next find all requested extensions 71 | for ext in exts.enumerate() { 72 | if api < ext.min_api { 73 | continue; 74 | } 75 | 76 | // Make a note that we included this extension 77 | result.extensions.insert(ext.name.clone()); 78 | 79 | // Load the definitions 80 | for def in parse_defs(ext.idl.as_bytes()) { 81 | result.load_definition(def); 82 | } 83 | 84 | // Attach overview doc comment 85 | let ext_iface = result 86 | .types 87 | .get_mut(&ext.name) 88 | .and_then(NamedType::as_interface_mut) 89 | .expect(&ext.name); 90 | ext_iface.doc_comment = ext.overview; 91 | 92 | // Attach individual function doc comments 93 | for (name, new_fun) in ext.new_funs { 94 | let members = ext_iface.members.get_mut(&name).unwrap(); 95 | for member in members { 96 | if let Member::Operation(ref mut op) = *member { 97 | op.doc_comment = new_fun.clone(); 98 | } 99 | } 100 | } 101 | } 102 | 103 | // Find the latest version of the rendering context, and generate a 104 | // version-independent rendering context helper type called "GLContext". 105 | for name in RENDERING_CONTEXTS.into_iter().rev() { 106 | if let Some(NamedType::Interface(mut iface)) = result.types.get(name.1).cloned() { 107 | iface.rendering_context = None; 108 | result 109 | .types 110 | .insert("GLContext".into(), NamedType::Interface(iface)); 111 | break; 112 | } 113 | } 114 | 115 | // Hide types that are listed in our "hidden names" array 116 | for &hidden_name in HIDDEN_NAMES { 117 | if let Some(interface) = result 118 | .types 119 | .get_mut(hidden_name) 120 | .and_then(NamedType::as_interface_mut) 121 | { 122 | interface.is_hidden = true; 123 | } 124 | if let Some(dictionary) = result 125 | .types 126 | .get_mut(hidden_name) 127 | .and_then(NamedType::as_dictionary_mut) 128 | { 129 | dictionary.is_hidden = true; 130 | } 131 | } 132 | 133 | // Done! 134 | result 135 | } 136 | 137 | /// Iterator over types matched by a filtering function 138 | pub fn iter_types<'a, T, F: FnMut(&'a NamedType) -> Option<&'a T>>( 139 | &'a self, 140 | f: F, 141 | ) -> TypeIter<'a, T, F> { 142 | TypeIter { 143 | inner: self.types.iter(), 144 | f, 145 | } 146 | } 147 | 148 | /// Resolves a named type 149 | pub fn resolve_type(&self, name: &str) -> &NamedType { 150 | self.types.get(name).expect(name) 151 | } 152 | 153 | /// Use the specified generator to generate bindings from this registry 154 | /// and write them to a stream. 155 | pub fn write_bindings(&self, generator: G, output: &mut W) -> io::Result<()> 156 | where 157 | G: Generator, 158 | W: io::Write, 159 | { 160 | generator.write(&self, output) 161 | } 162 | 163 | fn load_const(&mut self, const_: ast::Const) -> Option<(String, Member)> { 164 | use self::ast::{ConstType, ConstValue}; 165 | 166 | let type_ = ast::Type { 167 | extended_attributes: Vec::new(), 168 | kind: match const_.type_ { 169 | ConstType::Boolean => ast::TypeKind::Boolean, 170 | ConstType::Byte => ast::TypeKind::Byte, 171 | ConstType::Octet => ast::TypeKind::Octet, 172 | ConstType::RestrictedDouble => ast::TypeKind::RestrictedDouble, 173 | ConstType::UnrestrictedDouble => ast::TypeKind::UnrestrictedDouble, 174 | ConstType::RestrictedFloat => ast::TypeKind::RestrictedFloat, 175 | ConstType::UnrestrictedFloat => ast::TypeKind::UnrestrictedFloat, 176 | ConstType::SignedLong => ast::TypeKind::SignedLong, 177 | ConstType::UnsignedLong => ast::TypeKind::UnsignedLong, 178 | ConstType::SignedLongLong => ast::TypeKind::SignedLongLong, 179 | ConstType::UnsignedLongLong => ast::TypeKind::UnsignedLongLong, 180 | ConstType::SignedShort => ast::TypeKind::SignedShort, 181 | ConstType::UnsignedShort => ast::TypeKind::UnsignedShort, 182 | ConstType::Identifier(s) => ast::TypeKind::Identifier(s), 183 | }, 184 | nullable: const_.nullable, 185 | }; 186 | 187 | Some(( 188 | const_.name, 189 | Member::Const(Const { 190 | type_: self.load_type(type_), 191 | value: match const_.value { 192 | ConstValue::BooleanLiteral(b) => format!("{:?}", b), 193 | ConstValue::FloatLiteral(v) => format!("{:?}", v), 194 | ConstValue::SignedIntegerLiteral(v) => format!("{:?}", v), 195 | ConstValue::UnsignedIntegerLiteral(v) => format!("{:?}", v), 196 | ConstValue::Null => "None".into(), 197 | }, 198 | }), 199 | )) 200 | } 201 | 202 | fn load_attribute(&mut self, attribute: ast::Attribute) -> Option<(String, Member)> { 203 | use self::ast::Attribute::*; 204 | match attribute { 205 | Regular(a) => { 206 | let type_ = self.load_type(a.type_); 207 | Some(( 208 | a.name, 209 | Member::Attribute(Attribute { 210 | type_, 211 | setter: !a.read_only, 212 | getter: !a.inherits, 213 | }), 214 | )) 215 | }, 216 | _ => None, 217 | } 218 | } 219 | 220 | fn load_argument(&mut self, argument: ast::Argument) -> Argument { 221 | let type_ = self.load_type(argument.type_); 222 | Argument { 223 | name: argument.name, 224 | optional: argument.optional, 225 | type_, 226 | variadic: argument.variadic, 227 | } 228 | } 229 | 230 | fn load_operation(&mut self, operation: ast::Operation) -> Option<(String, Member)> { 231 | use self::ast::Operation::*; 232 | use self::ast::ReturnType; 233 | match operation { 234 | Regular(o) => { 235 | if let Some(name) = o.name { 236 | Some(( 237 | name, 238 | Member::Operation(Operation { 239 | args: o 240 | .arguments 241 | .into_iter() 242 | .map(|a| self.load_argument(a)) 243 | .collect(), 244 | return_type: match o.return_type { 245 | ReturnType::NonVoid(t) => Some(self.load_type(t)), 246 | ReturnType::Void => None, 247 | }, 248 | doc_comment: String::new(), 249 | }), 250 | )) 251 | } else { 252 | None 253 | } 254 | }, 255 | _ => None, 256 | } 257 | } 258 | 259 | fn load_mixin_member(&mut self, member: ast::MixinMember) -> Option<(String, Member)> { 260 | use self::ast::MixinMember::*; 261 | match member { 262 | Const(c) => self.load_const(c), 263 | Attribute(a) => self.load_attribute(a), 264 | Operation(o) => self.load_operation(o), 265 | } 266 | } 267 | 268 | fn load_mixin(&mut self, mixin: ast::NonPartialMixin) { 269 | let mut members = BTreeMap::new(); 270 | for (name, member) in mixin 271 | .members 272 | .into_iter() 273 | .flat_map(|m| self.load_mixin_member(m)) 274 | { 275 | multimap_insert(&mut members, name, member); 276 | } 277 | 278 | self.load_named_type(&mixin.name, NamedType::Mixin(Mixin { members })); 279 | } 280 | 281 | fn load_interface_member(&mut self, member: ast::InterfaceMember) -> Option<(String, Member)> { 282 | use self::ast::InterfaceMember::*; 283 | match member { 284 | Const(c) => self.load_const(c), 285 | Attribute(a) => self.load_attribute(a), 286 | Operation(o) => self.load_operation(o), 287 | _ => None, 288 | } 289 | } 290 | 291 | fn load_interface(&mut self, interface: ast::NonPartialInterface) { 292 | fn has_attr(attrs: &Vec, name: &str) -> bool { 293 | use self::ast::ExtendedAttribute::*; 294 | for attr in attrs { 295 | if let NoArguments(ref other) = *attr { 296 | if let &ast::Other::Identifier(ref n) = other { 297 | return n == name; 298 | } 299 | } 300 | } 301 | false 302 | } 303 | 304 | let mut members = BTreeMap::new(); 305 | for (name, member) in interface 306 | .members 307 | .into_iter() 308 | .flat_map(|m| self.load_interface_member(m)) 309 | { 310 | multimap_insert(&mut members, name, member); 311 | } 312 | 313 | let mut result = Interface { 314 | inherits: interface.inherits, 315 | mixins: BTreeSet::new(), 316 | members, 317 | is_hidden: false, 318 | has_class: !has_attr(&interface.extended_attributes, "NoInterfaceObject"), 319 | rendering_context: None, 320 | doc_comment: String::new(), 321 | }; 322 | 323 | for &(context_id, context_interface) in RENDERING_CONTEXTS { 324 | if context_interface == interface.name { 325 | result.rendering_context = Some(context_id); 326 | break; 327 | } 328 | } 329 | 330 | match self.types.entry(interface.name) { 331 | Entry::Vacant(v) => { 332 | v.insert(NamedType::Interface(result)); 333 | }, 334 | Entry::Occupied(o) => { 335 | assert!( 336 | result.members.is_empty(), 337 | "Duplicate interface: {}", 338 | o.key() 339 | ); 340 | }, 341 | } 342 | } 343 | 344 | fn load_includes(&mut self, includes: ast::Includes) { 345 | if let Some(interface) = self 346 | .types 347 | .get_mut(&includes.includer) 348 | .and_then(NamedType::as_interface_mut) 349 | { 350 | interface.mixins.insert(includes.includee); 351 | } 352 | } 353 | 354 | // Load a type kind into the registry under a given name, and return 355 | // a reference to it. 356 | fn load_named_type(&mut self, name: &str, named_type: NamedType) -> Type { 357 | if !self.types.contains_key(name) { 358 | self.types.insert(name.into(), named_type); 359 | } 360 | name.into() 361 | } 362 | 363 | // Convert an AST type kind into a type kind the generator can understand 364 | fn load_type_kind(&mut self, kind: ast::TypeKind) -> TypeKind { 365 | use self::ast::TypeKind::*; 366 | 367 | match kind { 368 | // Primitives 369 | Boolean => TypeKind::Primitive(Primitive::Bool), 370 | Byte => TypeKind::Primitive(Primitive::I8), 371 | Octet => TypeKind::Primitive(Primitive::U8), 372 | SignedShort => TypeKind::Primitive(Primitive::I16), 373 | UnsignedShort => TypeKind::Primitive(Primitive::U16), 374 | SignedLong => TypeKind::Primitive(Primitive::I32), 375 | UnsignedLong => TypeKind::Primitive(Primitive::U32), 376 | SignedLongLong => TypeKind::Primitive(Primitive::I64), 377 | UnsignedLongLong => TypeKind::Primitive(Primitive::U64), 378 | RestrictedFloat | UnrestrictedFloat => TypeKind::Primitive(Primitive::F32), 379 | RestrictedDouble | UnrestrictedDouble => TypeKind::Primitive(Primitive::F64), 380 | 381 | // Strings 382 | DOMString | USVString => TypeKind::String, 383 | ByteString => unimplemented!(), 384 | 385 | // TypedArrays 386 | Int8Array => TypeKind::TypedArray(Primitive::I8), 387 | Uint8Array => TypeKind::TypedArray(Primitive::U8), 388 | Int16Array => TypeKind::TypedArray(Primitive::I16), 389 | Uint16Array => TypeKind::TypedArray(Primitive::U16), 390 | Int32Array => TypeKind::TypedArray(Primitive::I32), 391 | Uint32Array => TypeKind::TypedArray(Primitive::U32), 392 | Float32Array => TypeKind::TypedArray(Primitive::F32), 393 | Float64Array => TypeKind::TypedArray(Primitive::F64), 394 | 395 | // Sequence 396 | Sequence(inner) => TypeKind::Sequence(Box::new(self.load_type(*inner))), 397 | 398 | // Identifier 399 | Identifier(s) => match &*s { 400 | "BufferSource" => TypeKind::BufferSource, 401 | "HTMLCanvasElement" => TypeKind::CanvasElement, 402 | "ArrayBufferView" => TypeKind::ArrayBufferView, 403 | other => TypeKind::Named(other.into()), 404 | }, 405 | 406 | // Composite 407 | Union(inners) => { 408 | if inners.len() <= 2 { 409 | TypeKind::Union( 410 | inners 411 | .into_iter() 412 | .map(|inner| self.load_type(inner)) 413 | .collect(), 414 | ) 415 | } else { 416 | TypeKind::Any 417 | } 418 | }, 419 | 420 | // Misc 421 | ArrayBuffer => TypeKind::ArrayBuffer, 422 | Object => TypeKind::Object, 423 | _ => TypeKind::Any, 424 | } 425 | } 426 | 427 | // Convert an AST type into a type the generator can understand 428 | fn load_type(&mut self, t: ast::Type) -> Type { 429 | Type { 430 | kind: self.load_type_kind(t.kind), 431 | optional: t.nullable, 432 | } 433 | } 434 | 435 | fn load_typedef(&mut self, typedef: ast::Typedef) { 436 | let type_ = self.load_type(typedef.type_); 437 | self.load_named_type(&typedef.name, NamedType::Typedef(type_)); 438 | } 439 | 440 | fn load_field(&mut self, field: ast::DictionaryMember) -> (String, Field) { 441 | let type_ = self.load_type(field.type_); 442 | 443 | (field.name, Field { type_ }) 444 | } 445 | 446 | fn load_dictionary(&mut self, dictionary: ast::NonPartialDictionary) { 447 | let fields = dictionary 448 | .members 449 | .into_iter() 450 | .map(|m| self.load_field(m)) 451 | .collect(); 452 | 453 | match self.types.entry(dictionary.name) { 454 | Entry::Vacant(v) => { 455 | v.insert(NamedType::Dictionary(Dictionary { 456 | inherits: dictionary.inherits, 457 | fields, 458 | is_hidden: false, 459 | })); 460 | }, 461 | Entry::Occupied(mut o) => { 462 | let key = o.key().clone(); 463 | let d = o.get_mut().as_dictionary_mut().unwrap(); 464 | // Dictionary is being extended, so make these fields all optional 465 | for (k, mut field) in fields { 466 | field.type_.optional = true; 467 | if d.fields.insert(k.clone(), field).is_some() { 468 | panic!("Duplicate field: {}.{}", key, k); 469 | } 470 | } 471 | }, 472 | } 473 | } 474 | 475 | fn load_enum(&mut self, enum_: ast::Enum) { 476 | let variants = enum_.variants.into_iter().collect(); 477 | self.load_named_type(&enum_.name, NamedType::Enum(Enum { variants })); 478 | } 479 | 480 | fn load_callback(&mut self, callback: ast::Callback) { 481 | use self::ast::ReturnType; 482 | let args = callback 483 | .arguments 484 | .into_iter() 485 | .map(|a| self.load_argument(a)) 486 | .collect(); 487 | let return_type = match callback.return_type { 488 | ReturnType::NonVoid(t) => Some(self.load_type(t)), 489 | ReturnType::Void => None, 490 | }; 491 | self.load_named_type( 492 | &callback.name, 493 | NamedType::Callback(Callback { args, return_type }), 494 | ); 495 | } 496 | 497 | fn load_definition(&mut self, def: ast::Definition) { 498 | use self::ast::Definition::*; 499 | match def { 500 | Mixin(ast::Mixin::NonPartial(m)) => self.load_mixin(m), 501 | Interface(ast::Interface::NonPartial(i)) => self.load_interface(i), 502 | Includes(i) => self.load_includes(i), 503 | Typedef(t) => self.load_typedef(t), 504 | Dictionary(ast::Dictionary::NonPartial(d)) => self.load_dictionary(d), 505 | Enum(e) => self.load_enum(e), 506 | Callback(c) => self.load_callback(c), 507 | _ => {}, 508 | } 509 | } 510 | } 511 | -------------------------------------------------------------------------------- /webgl_generator/webgl_registry/types.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use super::{NamedType, Registry}; 16 | 17 | #[derive(Debug, Clone, PartialEq, Eq)] 18 | pub struct Type { 19 | pub kind: TypeKind, 20 | /// Optional types are the default in WebIDL, so we give this a special 21 | /// place in the `Type` reference. It's also convenient to be able to 22 | /// "squash" optional flags to avoid `Option>`. 23 | pub optional: bool, 24 | } 25 | 26 | /// The different kinds of primitive types supported by WebIDL 27 | /// These are named according to their equivalents in rust. 28 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 29 | pub enum Primitive { 30 | Bool, 31 | I8, 32 | U8, 33 | I16, 34 | U16, 35 | I32, 36 | U32, 37 | I64, 38 | U64, 39 | F32, 40 | F64, 41 | } 42 | 43 | /// The definition of a type 44 | #[derive(Debug, Clone, PartialEq, Eq)] 45 | pub enum TypeKind { 46 | // Primitive types 47 | Primitive(Primitive), 48 | 49 | // "Known" types, that may deserve special handling 50 | String, 51 | ArrayBuffer, 52 | ArrayBufferView, 53 | BufferSource, 54 | CanvasElement, 55 | 56 | // Collection types 57 | TypedArray(Primitive), 58 | Sequence(Box), 59 | Union(Vec), 60 | 61 | // Named types 62 | Named(String), 63 | 64 | // Misc. types 65 | Any, 66 | Object, 67 | } 68 | 69 | impl Type { 70 | /// Return an optional version of this type reference. 71 | /// Returns an identical copy if the type is already optional. 72 | pub fn optional(&self) -> Self { 73 | Type { 74 | kind: self.kind.clone(), 75 | optional: true, 76 | } 77 | } 78 | } 79 | 80 | impl<'a> From<&'a str> for Type { 81 | /// Construct a type reference from a name 82 | fn from(s: &'a str) -> Type { 83 | Type { 84 | kind: TypeKind::Named(s.into()), 85 | optional: false, 86 | } 87 | } 88 | } 89 | 90 | impl Primitive { 91 | /// Get the rust name for a primitive type 92 | pub fn name(self) -> &'static str { 93 | use self::Primitive::*; 94 | match self { 95 | Bool => "bool", 96 | I8 => "i8", 97 | U8 => "u8", 98 | I16 => "i16", 99 | U16 => "u16", 100 | I32 => "i32", 101 | U32 => "u32", 102 | I64 => "i64", 103 | U64 => "u64", 104 | F32 => "f32", 105 | F64 => "f64", 106 | } 107 | } 108 | } 109 | 110 | impl TypeKind { 111 | /// Look through type aliases to find the "real" definition of a type. 112 | /// Also returns the "original name" if applicable. 113 | pub fn flatten<'a>(&'a self, registry: &'a Registry) -> (Option<&'a str>, &'a TypeKind) { 114 | match self { 115 | &TypeKind::Primitive(ref p) => (Some(p.name()), self), 116 | &TypeKind::Named(ref s) => { 117 | if let &NamedType::Typedef(ref t) = registry.resolve_type(s) { 118 | if !t.optional { 119 | return (Some(s.as_str()), t.kind.flatten(registry).1); 120 | } 121 | } 122 | (Some(s.as_str()), self) 123 | }, 124 | _ => (None, self), 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /webgl_stdweb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webgl_stdweb" 3 | version = "0.3.0" 4 | authors = [ 5 | "Diggory Blake", 6 | ] 7 | description = "WebGL bindings (stdweb)" 8 | license = "Apache-2.0" 9 | build = "build.rs" 10 | documentation = "https://docs.rs/webgl_stdweb" 11 | homepage = "https://github.com/brendanzab/gl-rs/" 12 | repository = "https://github.com/brendanzab/gl-rs/" 13 | readme = "README.md" 14 | categories = ["api-bindings", "rendering::graphics-api"] 15 | keywords = ["webgl", "stdweb"] 16 | 17 | [build-dependencies] 18 | webgl_generator = { version = "0.2.0", path = "../webgl_generator" } 19 | 20 | [dependencies] 21 | stdweb-derive = "0.5" 22 | stdweb = "0.4" 23 | serde = "1.0" 24 | serde_derive = "1.0" 25 | -------------------------------------------------------------------------------- /webgl_stdweb/README.md: -------------------------------------------------------------------------------- 1 | # webgl-stdweb 2 | 3 | [![Version](https://img.shields.io/crates/v/webgl_stdweb.svg)](https://crates.io/crates/webgl_stdweb) 4 | [![License](https://img.shields.io/crates/l/webgl_stdweb.svg)](https://github.com/brendanzab/gl-rs/blob/master/LICENSE) 5 | [![Downloads](https://img.shields.io/crates/d/webgl_stdweb.svg)](https://crates.io/crates/webgl_stdweb) 6 | 7 | 8 | WebGL bindings using stdweb 9 | 10 | ```toml 11 | [build-dependencies] 12 | webgl_stdweb = "0.3.0" 13 | ``` 14 | -------------------------------------------------------------------------------- /webgl_stdweb/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | extern crate webgl_generator; 16 | 17 | use std::env; 18 | use std::fs::File; 19 | use std::path::*; 20 | use webgl_generator::*; 21 | 22 | fn main() { 23 | let dest = env::var("OUT_DIR").unwrap(); 24 | let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap(); 25 | 26 | Registry::new(Api::WebGl2, Exts::ALL) 27 | .write_bindings(StdwebGenerator, &mut file) 28 | .unwrap(); 29 | } 30 | -------------------------------------------------------------------------------- /webgl_stdweb/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Brendan Zabarauskas and the gl-rs developers 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #![allow(unused_parens, non_camel_case_types)] 16 | #![crate_name = "webgl_stdweb"] 17 | #![crate_type = "lib"] 18 | 19 | #[macro_use] 20 | extern crate serde_derive as _serde_derive; 21 | #[macro_use] 22 | extern crate stdweb as _stdweb; 23 | #[macro_use] 24 | extern crate stdweb_derive as _stdweb_derive; 25 | 26 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 27 | --------------------------------------------------------------------------------