├── .gitignore
├── examples
└── hello
│ ├── Cargo.toml
│ ├── README.md
│ ├── index.html
│ └── src
│ └── main.rs
├── README.md
├── LICENSE-MIT
├── Cargo.toml
├── LICENSE-APACHE
└── src
├── native.rs
└── web.rs
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | /target
3 | **/*.rs.bk
4 | Cargo.lock
5 | generated
6 |
--------------------------------------------------------------------------------
/examples/hello/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "hello"
3 | version = "0.1.0"
4 | edition = "2018"
5 |
6 | [dependencies]
7 | glow = { path = "../../" }
8 |
9 | [target.'cfg(not(any(target_arch = "wasm32")))'.dependencies]
10 | glutin = "0.19"
11 |
12 | [target.wasm32-unknown-unknown.dependencies]
13 | web-sys = { version = "0.3", features=["console"] }
14 | wasm-bindgen = "0.2"
15 |
--------------------------------------------------------------------------------
/examples/hello/README.md:
--------------------------------------------------------------------------------
1 | # How to Build
2 |
3 | ## Native
4 |
5 | ```shell
6 | cargo run
7 | ```
8 |
9 | ## Web
10 |
11 | `cd` to `examples/hello` directory
12 |
13 | ```shell
14 | cargo +nightly build --target wasm32-unknown-unknown
15 | mkdir -p generated
16 | wasm-bindgen ../../target/wasm32-unknown-unknown/debug/hello.wasm --out-dir generated --no-modules
17 | cp index.html generated
18 | ```
19 |
--------------------------------------------------------------------------------
/examples/hello/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # glow
2 |
3 | GL on Whatever: a set of bindings to run GL anywhere (Open GL, OpenGL ES, and WebGL) and avoid target-specific code.
4 |
5 | This is heavily work-in-progress and should be considered experimental.
6 |
7 | ## License
8 |
9 | This project is licensed under either of [Apache License, Version
10 | 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT), at your option.
11 |
12 | ## Contribution
13 |
14 | Unless you explicitly state otherwise, any contribution intentionally submitted
15 | for inclusion in this project by you, as defined in the Apache 2.0 license,
16 | shall be dual licensed as above, without any additional terms or conditions.
17 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Permission is hereby granted, free of charge, to any
2 | person obtaining a copy of this software and associated
3 | documentation files (the "Software"), to deal in the
4 | Software without restriction, including without
5 | limitation the rights to use, copy, modify, merge,
6 | publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software
8 | is furnished to do so, subject to the following
9 | conditions:
10 |
11 | The above copyright notice and this permission notice
12 | shall be included in all copies or substantial portions
13 | of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "glow"
3 | version = "0.1.0"
4 | description = "GL on Whatever: a set of bindings to run GL anywhere (Open GL, OpenGL ES, and WebGL) and avoid target-specific code."
5 | authors = ["Joshua Groves "]
6 | homepage = "https://github.com/grovesNL/glow.git"
7 | license = "MIT OR Apache-2.0"
8 | build = "build.rs"
9 | edition = "2018"
10 |
11 | [lib]
12 | name = "glow"
13 | path = "src/lib.rs"
14 |
15 | [target.'cfg(not(any(target_arch = "wasm32")))'.dependencies]
16 | glutin = "0.19"
17 |
18 | [target.wasm32-unknown-unknown.dependencies]
19 | js-sys = "0.3"
20 | wasm-bindgen = "0.2"
21 | slotmap = "0.3"
22 |
23 | [target.wasm32-unknown-unknown.dependencies.web-sys]
24 | version = "0.3"
25 | features = [
26 | "Document",
27 | "Element",
28 | "HtmlCanvasElement",
29 | "WebGlBuffer",
30 | "WebGlFramebuffer",
31 | "WebGlProgram",
32 | "WebGlRenderbuffer",
33 | "WebGlRenderingContext",
34 | "WebGl2RenderingContext",
35 | "WebGlSampler",
36 | "WebGlShader",
37 | "WebGlSync",
38 | "WebGlTexture",
39 | "WebGlUniformLocation",
40 | "WebGlVertexArrayObject",
41 | "Window",
42 | ]
43 |
44 | [build-dependencies]
45 | gl_generator = "0.9"
46 |
47 | [workspace]
48 | members = [
49 | "examples/hello",
50 | ]
51 |
--------------------------------------------------------------------------------
/examples/hello/src/main.rs:
--------------------------------------------------------------------------------
1 | use glow::{self, Context, RenderLoop};
2 |
3 | #[cfg(target_arch = "wasm32")]
4 | use wasm_bindgen::prelude::*;
5 |
6 | #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
7 | pub fn wasm_main() {
8 | main();
9 | }
10 |
11 | fn main() {
12 | unsafe {
13 | // Create a context from a WebGL2 context on wasm32 targets
14 | #[cfg(target_arch = "wasm32")]
15 | let (_window, gl, _events_loop, render_loop, shader_version) = {
16 | use wasm_bindgen::JsCast;
17 | let canvas = web_sys::window()
18 | .unwrap()
19 | .document()
20 | .unwrap()
21 | .get_element_by_id("canvas")
22 | .unwrap()
23 | .dyn_into::()
24 | .unwrap();
25 | let webgl2_context = canvas
26 | .get_context("webgl2")
27 | .unwrap()
28 | .unwrap()
29 | .dyn_into::()
30 | .unwrap();
31 | (
32 | (),
33 | glow::web::Context::from_webgl2_context(webgl2_context),
34 | (),
35 | glow::web::RenderLoop::from_request_animation_frame(),
36 | "#version 300 es",
37 | )
38 | };
39 |
40 | // Create a context from a glutin window on non-wasm32 targets
41 | #[cfg(not(target_arch = "wasm32"))]
42 | let (window, gl, mut events_loop, render_loop, shader_version) = {
43 | use glutin::GlContext;
44 | let events_loop = glutin::EventsLoop::new();
45 | let window_builder = glutin::WindowBuilder::new()
46 | .with_title("Hello triangle!")
47 | .with_dimensions(glutin::dpi::LogicalSize::new(1024.0, 768.0));
48 | let context_builder = glutin::ContextBuilder::new().with_vsync(true);
49 | let window =
50 | glutin::GlWindow::new(window_builder, context_builder, &events_loop).unwrap();
51 | let context = glow::native::Context::from_loader_function(|s| {
52 | window.get_proc_address(s) as *const _
53 | });
54 | window.make_current().unwrap();
55 | let render_loop = glow::native::RenderLoop::from_window();
56 | (window, context, events_loop, render_loop, "#version 410")
57 | };
58 |
59 | let vertex_array = gl
60 | .create_vertex_array()
61 | .expect("Cannot create vertex array");
62 | gl.bind_vertex_array(Some(vertex_array));
63 |
64 | let program = gl.create_program().expect("Cannot create program");
65 |
66 | let (vertex_shader_source, fragment_shader_source) = (
67 | r#"const vec2 verts[3] = vec2[3](
68 | vec2(0.5f, 1.0f),
69 | vec2(0.0f, 0.0f),
70 | vec2(1.0f, 0.0f)
71 | );
72 | out vec2 vert;
73 | void main() {
74 | vert = verts[gl_VertexID];
75 | gl_Position = vec4(vert - 0.5, 0.0, 1.0);
76 | }"#,
77 | r#"precision mediump float;
78 | in vec2 vert;
79 | out vec4 color;
80 | void main() {
81 | color = vec4(vert, 0.5, 1.0);
82 | }"#,
83 | );
84 |
85 | let shader_sources = [
86 | (glow::VERTEX_SHADER, vertex_shader_source),
87 | (glow::FRAGMENT_SHADER, fragment_shader_source),
88 | ];
89 |
90 | let mut shaders = Vec::with_capacity(shader_sources.len());
91 |
92 | for (shader_type, shader_source) in shader_sources.iter() {
93 | let shader = gl
94 | .create_shader(*shader_type)
95 | .expect("Cannot create shader");
96 | gl.shader_source(shader, &format!("{}\n{}", shader_version, shader_source));
97 | gl.compile_shader(shader);
98 | if !gl.get_shader_compile_status(shader) {
99 | panic!(gl.get_shader_info_log(shader));
100 | }
101 | gl.attach_shader(program, shader);
102 | shaders.push(shader);
103 | }
104 |
105 | gl.link_program(program);
106 | if !gl.get_program_link_status(program) {
107 | panic!(gl.get_program_info_log(program));
108 | }
109 |
110 | for shader in shaders {
111 | gl.detach_shader(program, shader);
112 | gl.delete_shader(shader);
113 | }
114 |
115 | gl.use_program(Some(program));
116 | gl.clear_color(0.1, 0.2, 0.3, 1.0);
117 |
118 | render_loop.run(move |running: &mut bool| {
119 | // Handle events differently between targets
120 | #[cfg(not(target_arch = "wasm32"))]
121 | {
122 | events_loop.poll_events(|event| match event {
123 | glutin::Event::WindowEvent { event, .. } => match event {
124 | glutin::WindowEvent::CloseRequested => *running = false,
125 | _ => (),
126 | },
127 | _ => (),
128 | });
129 | window.swap_buffers().unwrap();
130 | }
131 |
132 | gl.clear(glow::COLOR_BUFFER_BIT);
133 | gl.draw_arrays(glow::TRIANGLES, 0, 3);
134 |
135 | if !*running {
136 | gl.delete_program(program);
137 | gl.delete_vertex_array(vertex_array);
138 | }
139 | });
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/src/native.rs:
--------------------------------------------------------------------------------
1 | use super::*;
2 |
3 | use std::ffi::CString;
4 | use std::sync::Arc;
5 |
6 | mod native_gl {
7 | include!(concat!(env!("OUT_DIR"), "/opengl_bindings.rs"));
8 | }
9 |
10 | pub struct Context {
11 | raw: native_gl::Gl,
12 | }
13 |
14 | impl Context {
15 | pub fn from_loader_function(loader_function: F) -> Self
16 | where
17 | F: FnMut(&str) -> *const std::os::raw::c_void,
18 | {
19 | let raw = native_gl::Gl::load_with(loader_function);
20 | Context { raw }
21 | }
22 | }
23 |
24 | impl std::fmt::Debug for Context {
25 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
26 | // TODO
27 | write!(f, "TODO")
28 | }
29 | }
30 |
31 | impl super::Context for Context {
32 | type Shader = native_gl::types::GLuint;
33 | type Program = native_gl::types::GLuint;
34 | type Buffer = native_gl::types::GLuint;
35 | type VertexArray = native_gl::types::GLuint;
36 | type Texture = native_gl::types::GLuint;
37 | type Sampler = native_gl::types::GLuint;
38 | type Fence = native_gl::types::GLsync;
39 | type Framebuffer = native_gl::types::GLuint;
40 | type Renderbuffer = native_gl::types::GLuint;
41 | type UniformLocation = native_gl::types::GLuint;
42 |
43 | unsafe fn create_framebuffer(&self) -> Result {
44 | let gl = &self.raw;
45 | let mut name = 0;
46 | gl.GenFramebuffers(1, &mut name);
47 | Ok(name)
48 | }
49 |
50 | unsafe fn create_renderbuffer(&self) -> Result {
51 | let gl = &self.raw;
52 | let mut name = 0;
53 | gl.GenRenderbuffers(1, &mut name);
54 | Ok(name)
55 | }
56 |
57 | unsafe fn create_sampler(&self) -> Result {
58 | let gl = &self.raw;
59 | let mut name = 0;
60 | gl.GenSamplers(1, &mut name);
61 | Ok(name)
62 | }
63 |
64 | unsafe fn create_shader(&self, shader_type: u32) -> Result {
65 | let gl = &self.raw;
66 | Ok(gl.CreateShader(shader_type as u32))
67 | }
68 |
69 | unsafe fn create_texture(&self) -> Result {
70 | let gl = &self.raw;
71 | let mut name = 0;
72 | gl.GenTextures(1, &mut name);
73 | Ok(name)
74 | }
75 |
76 | unsafe fn delete_shader(&self, shader: Self::Shader) {
77 | let gl = &self.raw;
78 | gl.DeleteShader(shader);
79 | }
80 |
81 | unsafe fn shader_source(&self, shader: Self::Shader, source: &str) {
82 | let gl = &self.raw;
83 | gl.ShaderSource(
84 | shader,
85 | 1,
86 | &(source.as_ptr() as *const native_gl::types::GLchar),
87 | &(source.len() as native_gl::types::GLint),
88 | );
89 | }
90 |
91 | unsafe fn compile_shader(&self, shader: Self::Shader) {
92 | let gl = &self.raw;
93 | gl.CompileShader(shader);
94 | }
95 |
96 | unsafe fn get_shader_compile_status(&self, shader: Self::Shader) -> bool {
97 | let gl = &self.raw;
98 | let mut status = 0;
99 | gl.GetShaderiv(shader, COMPILE_STATUS, &mut status);
100 | 1 == status
101 | }
102 |
103 | unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String {
104 | let gl = &self.raw;
105 | let mut length = 0;
106 | gl.GetShaderiv(shader, INFO_LOG_LENGTH, &mut length);
107 | if length > 0 {
108 | let mut log = String::with_capacity(length as usize);
109 | log.extend(std::iter::repeat('\0').take(length as usize));
110 | gl.GetShaderInfoLog(
111 | shader,
112 | length,
113 | &mut length,
114 | (&log[..]).as_ptr() as *mut native_gl::types::GLchar,
115 | );
116 | log.truncate(length as usize);
117 | log
118 | } else {
119 | String::from("")
120 | }
121 | }
122 |
123 | unsafe fn get_tex_image(
124 | &self,
125 | target: u32,
126 | level: i32,
127 | format: u32,
128 | ty: u32,
129 | pixels: Option<&[u8]>,
130 | ) {
131 | let gl = &self.raw;
132 | gl.GetTexImage(
133 | target,
134 | level,
135 | format,
136 | ty,
137 | pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *mut std::ffi::c_void,
138 | );
139 | }
140 |
141 | unsafe fn create_program(&self) -> Result {
142 | let gl = &self.raw;
143 | Ok(gl.CreateProgram())
144 | }
145 |
146 | unsafe fn delete_program(&self, program: Self::Program) {
147 | let gl = &self.raw;
148 | gl.DeleteProgram(program);
149 | }
150 |
151 | unsafe fn attach_shader(&self, program: Self::Program, shader: Self::Shader) {
152 | let gl = &self.raw;
153 | gl.AttachShader(program, shader);
154 | }
155 |
156 | unsafe fn detach_shader(&self, program: Self::Program, shader: Self::Shader) {
157 | let gl = &self.raw;
158 | gl.DetachShader(program, shader);
159 | }
160 |
161 | unsafe fn link_program(&self, program: Self::Program) {
162 | let gl = &self.raw;
163 | gl.LinkProgram(program);
164 | }
165 |
166 | unsafe fn get_program_link_status(&self, program: Self::Program) -> bool {
167 | let gl = &self.raw;
168 | let mut status = 0;
169 | gl.GetProgramiv(program, LINK_STATUS, &mut status);
170 | 1 == status
171 | }
172 |
173 | unsafe fn get_program_info_log(&self, program: Self::Program) -> String {
174 | let gl = &self.raw;
175 | let mut length = 0;
176 | gl.GetProgramiv(program, INFO_LOG_LENGTH, &mut length);
177 | if length > 0 {
178 | let mut log = String::with_capacity(length as usize);
179 | log.extend(std::iter::repeat('\0').take(length as usize));
180 | gl.GetProgramInfoLog(
181 | program,
182 | length,
183 | &mut length,
184 | (&log[..]).as_ptr() as *mut native_gl::types::GLchar,
185 | );
186 | log.truncate(length as usize);
187 | log
188 | } else {
189 | String::from("")
190 | }
191 | }
192 |
193 | unsafe fn use_program(&self, program: Option) {
194 | let gl = &self.raw;
195 | gl.UseProgram(program.unwrap_or(0));
196 | }
197 |
198 | unsafe fn create_buffer(&self) -> Result {
199 | let gl = &self.raw;
200 | let mut buffer = 0;
201 | gl.GenBuffers(1, &mut buffer);
202 | Ok(buffer)
203 | }
204 |
205 | unsafe fn bind_buffer(&self, target: u32, buffer: Option) {
206 | let gl = &self.raw;
207 | gl.BindBuffer(target, buffer.unwrap_or(0));
208 | }
209 |
210 | unsafe fn bind_buffer_range(
211 | &self,
212 | target: u32,
213 | index: u32,
214 | buffer: Option,
215 | offset: i32,
216 | size: i32,
217 | ) {
218 | let gl = &self.raw;
219 | gl.BindBufferRange(
220 | target,
221 | index,
222 | buffer.unwrap_or(0),
223 | offset as isize,
224 | size as isize,
225 | );
226 | }
227 |
228 | unsafe fn bind_framebuffer(&self, target: u32, framebuffer: Option) {
229 | let gl = &self.raw;
230 | gl.BindFramebuffer(target, framebuffer.unwrap_or(0));
231 | }
232 |
233 | unsafe fn bind_renderbuffer(&self, target: u32, renderbuffer: Option) {
234 | let gl = &self.raw;
235 | gl.BindRenderbuffer(target, renderbuffer.unwrap_or(0));
236 | }
237 |
238 | unsafe fn create_vertex_array(&self) -> Result {
239 | let gl = &self.raw;
240 | let mut vertex_array = 0;
241 | gl.GenVertexArrays(1, &mut vertex_array);
242 | Ok(vertex_array)
243 | }
244 |
245 | unsafe fn delete_vertex_array(&self, vertex_array: Self::VertexArray) {
246 | let gl = &self.raw;
247 | gl.DeleteVertexArrays(1, &vertex_array);
248 | }
249 |
250 | unsafe fn bind_vertex_array(&self, vertex_array: Option) {
251 | let gl = &self.raw;
252 | gl.BindVertexArray(vertex_array.unwrap_or(0));
253 | }
254 |
255 | unsafe fn clear_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
256 | let gl = &self.raw;
257 | gl.ClearColor(red, green, blue, alpha);
258 | }
259 |
260 | unsafe fn supports_f64_precision() -> bool {
261 | // TODO: Handle OpenGL ES
262 | true
263 | }
264 |
265 | unsafe fn clear_depth_f64(&self, depth: f64) {
266 | let gl = &self.raw;
267 | gl.ClearDepth(depth);
268 | }
269 |
270 | unsafe fn clear_depth_f32(&self, depth: f32) {
271 | let gl = &self.raw;
272 | gl.ClearDepthf(depth);
273 | }
274 |
275 | unsafe fn clear_stencil(&self, stencil: i32) {
276 | let gl = &self.raw;
277 | gl.ClearStencil(stencil);
278 | }
279 |
280 | unsafe fn clear(&self, mask: u32) {
281 | let gl = &self.raw;
282 | gl.Clear(mask);
283 | }
284 |
285 | unsafe fn patch_parameter_i32(&self, parameter: u32, value: i32) {
286 | let gl = &self.raw;
287 | gl.PatchParameteri(parameter, value);
288 | }
289 |
290 | unsafe fn pixel_store_i32(&self, parameter: u32, value: i32) {
291 | let gl = &self.raw;
292 | gl.PixelStorei(parameter, value);
293 | }
294 |
295 | unsafe fn pixel_store_bool(&self, parameter: u32, value: bool) {
296 | let gl = &self.raw;
297 | gl.PixelStorei(parameter, value as i32);
298 | }
299 |
300 | unsafe fn bind_frag_data_location(
301 | &self,
302 | program: Self::Program,
303 | color_number: u32,
304 | name: &str,
305 | ) {
306 | let gl = &self.raw;
307 | gl.BindFragDataLocation(program, color_number, name.as_ptr() as *const i8);
308 | }
309 |
310 | unsafe fn buffer_data_size(&self, target: u32, size: i32, usage: u32) {
311 | let gl = &self.raw;
312 | gl.BufferData(target, size as isize, std::ptr::null(), usage);
313 | }
314 |
315 | unsafe fn buffer_data_u8_slice(&self, target: u32, data: &[u8], usage: u32) {
316 | let gl = &self.raw;
317 | gl.BufferData(
318 | target,
319 | data.len() as isize,
320 | data.as_ptr() as *const std::ffi::c_void,
321 | usage,
322 | );
323 | }
324 |
325 | unsafe fn buffer_storage(&self, target: u32, size: i32, data: Option<&mut [u8]>, flags: u32) {
326 | let gl = &self.raw;
327 | gl.BufferStorage(
328 | target,
329 | size as isize,
330 | data.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
331 | flags,
332 | );
333 | }
334 |
335 | unsafe fn check_framebuffer_status(&self, target: u32) -> u32 {
336 | let gl = &self.raw;
337 | gl.CheckFramebufferStatus(target)
338 | }
339 |
340 | unsafe fn clear_buffer_i32_slice(&self, target: u32, draw_buffer: u32, values: &mut [i32]) {
341 | let gl = &self.raw;
342 | gl.ClearBufferiv(target, draw_buffer as i32, values.as_ptr());
343 | }
344 |
345 | unsafe fn clear_buffer_u32_slice(&self, target: u32, draw_buffer: u32, values: &mut [u32]) {
346 | let gl = &self.raw;
347 | gl.ClearBufferuiv(target, draw_buffer as i32, values.as_ptr());
348 | }
349 |
350 | unsafe fn clear_buffer_f32_slice(&self, target: u32, draw_buffer: u32, values: &mut [f32]) {
351 | let gl = &self.raw;
352 | gl.ClearBufferfv(target, draw_buffer as i32, values.as_ptr());
353 | }
354 |
355 | unsafe fn clear_buffer_depth_stencil(
356 | &self,
357 | target: u32,
358 | draw_buffer: u32,
359 | depth: f32,
360 | stencil: i32,
361 | ) {
362 | let gl = &self.raw;
363 | gl.ClearBufferfi(target, draw_buffer as i32, depth, stencil);
364 | }
365 |
366 | unsafe fn client_wait_sync(&self, fence: Self::Fence, flags: u32, timeout: i32) -> u32 {
367 | let gl = &self.raw;
368 | gl.ClientWaitSync(fence, flags, timeout as u64)
369 | }
370 |
371 | unsafe fn copy_buffer_sub_data(
372 | &self,
373 | src_target: u32,
374 | dst_target: u32,
375 | src_offset: i32,
376 | dst_offset: i32,
377 | size: i32,
378 | ) {
379 | let gl = &self.raw;
380 | gl.CopyBufferSubData(
381 | src_target,
382 | dst_target,
383 | src_offset as isize,
384 | dst_offset as isize,
385 | size as isize,
386 | );
387 | }
388 |
389 | unsafe fn delete_buffer(&self, buffer: Self::Buffer) {
390 | let gl = &self.raw;
391 | gl.DeleteBuffers(1, &buffer);
392 | }
393 |
394 | unsafe fn delete_framebuffer(&self, framebuffer: Self::Framebuffer) {
395 | let gl = &self.raw;
396 | gl.DeleteFramebuffers(1, &framebuffer);
397 | }
398 |
399 | unsafe fn delete_renderbuffer(&self, renderbuffer: Self::Renderbuffer) {
400 | let gl = &self.raw;
401 | gl.DeleteRenderbuffers(1, &renderbuffer);
402 | }
403 |
404 | unsafe fn delete_sampler(&self, sampler: Self::Sampler) {
405 | let gl = &self.raw;
406 | gl.DeleteSamplers(1, &sampler);
407 | }
408 |
409 | unsafe fn delete_sync(&self, fence: Self::Fence) {
410 | let gl = &self.raw;
411 | gl.DeleteSync(fence);
412 | }
413 |
414 | unsafe fn delete_texture(&self, texture: Self::Texture) {
415 | let gl = &self.raw;
416 | gl.DeleteTextures(1, &texture);
417 | }
418 |
419 | unsafe fn disable(&self, parameter: u32) {
420 | let gl = &self.raw;
421 | gl.Disable(parameter);
422 | }
423 |
424 | unsafe fn disable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
425 | let gl = &self.raw;
426 | gl.Disablei(draw_buffer, parameter);
427 | }
428 |
429 | unsafe fn disable_vertex_attrib_array(&self, index: u32) {
430 | let gl = &self.raw;
431 | gl.DisableVertexAttribArray(index);
432 | }
433 |
434 | unsafe fn dispatch_compute(&self, groups_x: u32, groups_y: u32, groups_z: u32) {
435 | let gl = &self.raw;
436 | gl.DispatchCompute(groups_x, groups_y, groups_z);
437 | }
438 |
439 | unsafe fn dispatch_compute_indirect(&self, offset: i32) {
440 | let gl = &self.raw;
441 | gl.DispatchComputeIndirect(offset as isize);
442 | }
443 |
444 | unsafe fn draw_arrays(&self, mode: u32, first: i32, count: i32) {
445 | let gl = &self.raw;
446 | gl.DrawArrays(mode as u32, first, count);
447 | }
448 |
449 | unsafe fn draw_arrays_instanced(&self, mode: u32, first: i32, count: i32, instance_count: i32) {
450 | let gl = &self.raw;
451 | gl.DrawArraysInstanced(mode as u32, first, count, instance_count);
452 | }
453 |
454 | unsafe fn draw_arrays_instanced_base_instance(
455 | &self,
456 | mode: u32,
457 | first: i32,
458 | count: i32,
459 | instance_count: i32,
460 | base_instance: u32,
461 | ) {
462 | let gl = &self.raw;
463 | gl.DrawArraysInstancedBaseInstance(
464 | mode as u32,
465 | first,
466 | count,
467 | instance_count,
468 | base_instance,
469 | );
470 | }
471 |
472 | unsafe fn draw_buffer(&self, draw_buffer: u32) {
473 | let gl = &self.raw;
474 | gl.DrawBuffer(draw_buffer);
475 | }
476 |
477 | unsafe fn draw_buffers(&self, buffers: &[u32]) {
478 | let gl = &self.raw;
479 | gl.DrawBuffers(buffers.len() as i32, buffers.as_ptr());
480 | }
481 |
482 | unsafe fn draw_elements(&self, mode: u32, count: i32, element_type: u32, offset: i32) {
483 | let gl = &self.raw;
484 | gl.DrawElements(
485 | mode as u32,
486 | count,
487 | element_type as u32,
488 | offset as *const std::ffi::c_void,
489 | );
490 | }
491 |
492 | unsafe fn draw_elements_base_vertex(
493 | &self,
494 | mode: u32,
495 | count: i32,
496 | element_type: u32,
497 | offset: i32,
498 | base_vertex: i32,
499 | ) {
500 | let gl = &self.raw;
501 | gl.DrawElementsBaseVertex(
502 | mode as u32,
503 | count,
504 | element_type as u32,
505 | offset as *const std::ffi::c_void,
506 | base_vertex,
507 | );
508 | }
509 |
510 | unsafe fn draw_elements_instanced(
511 | &self,
512 | mode: u32,
513 | count: i32,
514 | element_type: u32,
515 | offset: i32,
516 | instance_count: i32,
517 | ) {
518 | let gl = &self.raw;
519 | gl.DrawElementsInstanced(
520 | mode as u32,
521 | count,
522 | element_type as u32,
523 | offset as *const std::ffi::c_void,
524 | instance_count,
525 | );
526 | }
527 |
528 | unsafe fn draw_elements_instanced_base_vertex(
529 | &self,
530 | mode: u32,
531 | count: i32,
532 | element_type: u32,
533 | offset: i32,
534 | instance_count: i32,
535 | base_vertex: i32,
536 | ) {
537 | let gl = &self.raw;
538 | gl.DrawElementsInstancedBaseVertex(
539 | mode as u32,
540 | count,
541 | element_type as u32,
542 | offset as *const std::ffi::c_void,
543 | instance_count,
544 | base_vertex,
545 | );
546 | }
547 |
548 | unsafe fn draw_elements_instanced_base_vertex_base_instance(
549 | &self,
550 | mode: u32,
551 | count: i32,
552 | element_type: u32,
553 | offset: i32,
554 | instance_count: i32,
555 | base_vertex: i32,
556 | base_instance: u32,
557 | ) {
558 | let gl = &self.raw;
559 | gl.DrawElementsInstancedBaseVertexBaseInstance(
560 | mode as u32,
561 | count,
562 | element_type as u32,
563 | offset as *const std::ffi::c_void,
564 | instance_count,
565 | base_vertex,
566 | base_instance,
567 | );
568 | }
569 |
570 | unsafe fn enable(&self, parameter: u32) {
571 | let gl = &self.raw;
572 | gl.Enable(parameter);
573 | }
574 |
575 | unsafe fn enable_draw_buffer(&self, parameter: u32, draw_buffer: u32) {
576 | let gl = &self.raw;
577 | gl.Enablei(parameter, draw_buffer);
578 | }
579 |
580 | unsafe fn enable_vertex_attrib_array(&self, index: u32) {
581 | let gl = &self.raw;
582 | gl.EnableVertexAttribArray(index);
583 | }
584 |
585 | unsafe fn flush(&self) {
586 | let gl = &self.raw;
587 | gl.Flush();
588 | }
589 |
590 | unsafe fn framebuffer_renderbuffer(
591 | &self,
592 | target: u32,
593 | attachment: u32,
594 | renderbuffer_target: u32,
595 | renderbuffer: Option,
596 | ) {
597 | let gl = &self.raw;
598 | gl.FramebufferRenderbuffer(
599 | target,
600 | attachment,
601 | renderbuffer_target,
602 | renderbuffer.unwrap_or(0),
603 | );
604 | }
605 |
606 | unsafe fn framebuffer_texture(
607 | &self,
608 | target: u32,
609 | attachment: u32,
610 | texture: Option,
611 | level: i32,
612 | ) {
613 | let gl = &self.raw;
614 | gl.FramebufferTexture(target, attachment, texture.unwrap_or(0), level);
615 | }
616 |
617 | unsafe fn framebuffer_texture_2d(
618 | &self,
619 | target: u32,
620 | attachment: u32,
621 | texture_target: u32,
622 | texture: Option,
623 | level: i32,
624 | ) {
625 | let gl = &self.raw;
626 | gl.FramebufferTexture2D(
627 | target,
628 | attachment,
629 | texture_target,
630 | texture.unwrap_or(0),
631 | level,
632 | );
633 | }
634 |
635 | unsafe fn framebuffer_texture_3d(
636 | &self,
637 | target: u32,
638 | attachment: u32,
639 | texture_target: u32,
640 | texture: Option,
641 | level: i32,
642 | layer: i32,
643 | ) {
644 | let gl = &self.raw;
645 | gl.FramebufferTexture3D(
646 | target,
647 | attachment,
648 | texture_target,
649 | texture.unwrap_or(0),
650 | level,
651 | layer,
652 | );
653 | }
654 |
655 | unsafe fn framebuffer_texture_layer(
656 | &self,
657 | target: u32,
658 | attachment: u32,
659 | texture: Option,
660 | level: i32,
661 | layer: i32,
662 | ) {
663 | let gl = &self.raw;
664 | gl.FramebufferTextureLayer(target, attachment, texture.unwrap_or(0), level, layer);
665 | }
666 |
667 | unsafe fn front_face(&self, value: u32) {
668 | let gl = &self.raw;
669 | gl.FrontFace(value as u32);
670 | }
671 |
672 | unsafe fn get_error(&self) -> u32 {
673 | let gl = &self.raw;
674 | gl.GetError()
675 | }
676 |
677 | unsafe fn get_parameter_i32(&self, parameter: u32) -> i32 {
678 | let gl = &self.raw;
679 | let mut value = 0;
680 | gl.GetIntegerv(parameter, &mut value);
681 | value
682 | }
683 |
684 | unsafe fn get_parameter_indexed_i32(&self, parameter: u32, index: u32) -> i32 {
685 | let gl = &self.raw;
686 | let mut value = 0;
687 | gl.GetIntegeri_v(parameter, index, &mut value);
688 | value
689 | }
690 |
691 | unsafe fn get_parameter_indexed_string(&self, parameter: u32, index: u32) -> String {
692 | let gl = &self.raw;
693 | let raw_ptr = gl.GetStringi(parameter, index);
694 | std::ffi::CStr::from_ptr(raw_ptr as *const i8)
695 | .to_str()
696 | .unwrap()
697 | .to_owned()
698 | }
699 |
700 | unsafe fn get_parameter_string(&self, parameter: u32) -> String {
701 | let gl = &self.raw;
702 | let raw_ptr = gl.GetString(parameter);
703 | std::ffi::CStr::from_ptr(raw_ptr as *const i8)
704 | .to_str()
705 | .unwrap()
706 | .to_owned()
707 | }
708 |
709 | unsafe fn get_uniform_location(
710 | &self,
711 | program: Self::Program,
712 | name: &str,
713 | ) -> Option {
714 | let gl = &self.raw;
715 | let name = CString::new(name).unwrap();
716 | Some(gl.GetUniformLocation(program, name.as_ptr() as *const i8) as u32)
717 | }
718 |
719 | unsafe fn get_attrib_location(
720 | &self,
721 | program: Self::Program,
722 | name: &str
723 | ) -> i32 {
724 | let gl = &self.raw;
725 | let name = CString::new(name).unwrap();
726 | gl.GetAttribLocation(program, name.as_ptr() as *const i8) as i32
727 | }
728 |
729 | unsafe fn is_sync(&self, fence: Self::Fence) -> bool {
730 | let gl = &self.raw;
731 | 1 == gl.IsSync(fence)
732 | }
733 |
734 | unsafe fn renderbuffer_storage(
735 | &self,
736 | target: u32,
737 | internal_format: u32,
738 | width: i32,
739 | height: i32,
740 | ) {
741 | let gl = &self.raw;
742 | gl.RenderbufferStorage(target, internal_format, width, height);
743 | }
744 |
745 | unsafe fn sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32, value: f32) {
746 | let gl = &self.raw;
747 | gl.SamplerParameterf(sampler, name, value);
748 | }
749 |
750 | unsafe fn sampler_parameter_f32_slice(
751 | &self,
752 | sampler: Self::Sampler,
753 | name: u32,
754 | value: &mut [f32],
755 | ) {
756 | let gl = &self.raw;
757 | gl.SamplerParameterfv(sampler, name, value.as_ptr());
758 | }
759 |
760 | unsafe fn sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32, value: i32) {
761 | let gl = &self.raw;
762 | gl.SamplerParameteri(sampler, name, value);
763 | }
764 |
765 | unsafe fn tex_image_2d(
766 | &self,
767 | target: u32,
768 | level: i32,
769 | internal_format: i32,
770 | width: i32,
771 | height: i32,
772 | border: i32,
773 | format: u32,
774 | ty: u32,
775 | pixels: Option<&[u8]>,
776 | ) {
777 | let gl = &self.raw;
778 | gl.TexImage2D(
779 | target,
780 | level,
781 | internal_format,
782 | width,
783 | height,
784 | border,
785 | format,
786 | ty,
787 | pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
788 | );
789 | }
790 |
791 | unsafe fn tex_storage_2d(
792 | &self,
793 | target: u32,
794 | levels: i32,
795 | internal_format: u32,
796 | width: i32,
797 | height: i32,
798 | ) {
799 | let gl = &self.raw;
800 | gl.TexStorage2D(target, levels, internal_format, width, height);
801 | }
802 |
803 | unsafe fn uniform_1_i32(&self, location: Option, x: i32) {
804 | let gl = &self.raw;
805 | gl.Uniform1i(location.unwrap_or(0) as i32, x);
806 | }
807 |
808 | unsafe fn uniform_2_i32(&self, location: Option, x: i32, y: i32) {
809 | let gl = &self.raw;
810 | gl.Uniform2i(location.unwrap_or(0) as i32, x, y);
811 | }
812 |
813 | unsafe fn uniform_3_i32(&self, location: Option, x: i32, y: i32, z: i32) {
814 | let gl = &self.raw;
815 | gl.Uniform3i(location.unwrap_or(0) as i32, x, y, z);
816 | }
817 |
818 | unsafe fn uniform_4_i32(&self, location: Option, x: i32, y: i32, z: i32, w: i32) {
819 | let gl = &self.raw;
820 | gl.Uniform4i(location.unwrap_or(0) as i32, x, y, z, w);
821 | }
822 |
823 | unsafe fn uniform_1_i32_slice(&self, location: Option, v: &mut [i32; 1]) {
824 | let gl = &self.raw;
825 | gl.Uniform1iv(location.unwrap_or(0) as i32, 1, v.as_ptr());
826 | }
827 |
828 | unsafe fn uniform_2_i32_slice(&self, location: Option, v: &mut [i32; 2]) {
829 | let gl = &self.raw;
830 | gl.Uniform2iv(location.unwrap_or(0) as i32, 1, v.as_ptr());
831 | }
832 |
833 | unsafe fn uniform_3_i32_slice(&self, location: Option, v: &mut [i32; 3]) {
834 | let gl = &self.raw;
835 | gl.Uniform3iv(location.unwrap_or(0) as i32, 1, v.as_ptr());
836 | }
837 |
838 | unsafe fn uniform_4_i32_slice(&self, location: Option, v: &mut [i32; 4]) {
839 | let gl = &self.raw;
840 | gl.Uniform4iv(location.unwrap_or(0) as i32, 1, v.as_ptr());
841 | }
842 |
843 | unsafe fn uniform_1_f32(&self, location: Option, x: f32) {
844 | let gl = &self.raw;
845 | gl.Uniform1f(location.unwrap_or(0) as i32, x);
846 | }
847 |
848 | unsafe fn uniform_2_f32(&self, location: Option, x: f32, y: f32) {
849 | let gl = &self.raw;
850 | gl.Uniform2f(location.unwrap_or(0) as i32, x, y);
851 | }
852 |
853 | unsafe fn uniform_3_f32(&self, location: Option, x: f32, y: f32, z: f32) {
854 | let gl = &self.raw;
855 | gl.Uniform3f(location.unwrap_or(0) as i32, x, y, z);
856 | }
857 |
858 | unsafe fn uniform_4_f32(&self, location: Option, x: f32, y: f32, z: f32, w: f32) {
859 | let gl = &self.raw;
860 | gl.Uniform4f(location.unwrap_or(0) as i32, x, y, z, w);
861 | }
862 |
863 | unsafe fn uniform_1_f32_slice(&self, location: Option, v: &[f32; 1]) {
864 | let gl = &self.raw;
865 | gl.Uniform1fv(location.unwrap_or(0) as i32, 1, v.as_ptr());
866 | }
867 |
868 | unsafe fn uniform_2_f32_slice(&self, location: Option, v: &[f32; 2]) {
869 | let gl = &self.raw;
870 | gl.Uniform2fv(location.unwrap_or(0) as i32, 1, v.as_ptr());
871 | }
872 |
873 | unsafe fn uniform_3_f32_slice(&self, location: Option, v: &[f32; 3]) {
874 | let gl = &self.raw;
875 | gl.Uniform3fv(location.unwrap_or(0) as i32, 1, v.as_ptr());
876 | }
877 |
878 | unsafe fn uniform_4_f32_slice(&self, location: Option, v: &[f32; 4]) {
879 | let gl = &self.raw;
880 | gl.Uniform4fv(location.unwrap_or(0) as i32, 1, v.as_ptr());
881 | }
882 |
883 | unsafe fn uniform_matrix_2_f32_slice(&self, location: Option, transpose: bool, v: &[f32; 4]) {
884 | let gl = &self.raw;
885 | gl.UniformMatrix2fv(location.unwrap_or(0) as i32, 1, transpose as u8, v.as_ptr());
886 | }
887 |
888 | unsafe fn uniform_matrix_3_f32_slice(&self, location: Option, transpose: bool, v: &[f32; 9]) {
889 | let gl = &self.raw;
890 | gl.UniformMatrix3fv(location.unwrap_or(0) as i32, 1, transpose as u8, v.as_ptr());
891 | }
892 |
893 | unsafe fn uniform_matrix_4_f32_slice(&self, location: Option, transpose: bool, v: &[f32; 16]) {
894 | let gl = &self.raw;
895 | gl.UniformMatrix4fv(location.unwrap_or(0) as i32, 1, transpose as u8, v.as_ptr());
896 | }
897 |
898 | unsafe fn unmap_buffer(&self, target: u32) {
899 | let gl = &self.raw;
900 | gl.UnmapBuffer(target);
901 | }
902 |
903 | unsafe fn cull_face(&self, value: u32) {
904 | let gl = &self.raw;
905 | gl.CullFace(value as u32);
906 | }
907 |
908 | unsafe fn color_mask(&self, red: bool, green: bool, blue: bool, alpha: bool) {
909 | let gl = &self.raw;
910 | gl.ColorMask(red as u8, green as u8, blue as u8, alpha as u8);
911 | }
912 |
913 | unsafe fn color_mask_draw_buffer(
914 | &self,
915 | draw_buffer: u32,
916 | red: bool,
917 | green: bool,
918 | blue: bool,
919 | alpha: bool,
920 | ) {
921 | let gl = &self.raw;
922 | gl.ColorMaski(draw_buffer, red as u8, green as u8, blue as u8, alpha as u8);
923 | }
924 |
925 | unsafe fn depth_mask(&self, value: bool) {
926 | let gl = &self.raw;
927 | gl.DepthMask(value as u8);
928 | }
929 |
930 | unsafe fn blend_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
931 | let gl = &self.raw;
932 | gl.BlendColor(red, green, blue, alpha);
933 | }
934 |
935 | unsafe fn line_width(&self, width: f32) {
936 | let gl = &self.raw;
937 | gl.LineWidth(width);
938 | }
939 |
940 | unsafe fn map_buffer_range(
941 | &self,
942 | target: u32,
943 | offset: i32,
944 | length: i32,
945 | access: u32,
946 | ) -> *mut u8 {
947 | let gl = &self.raw;
948 | gl.MapBufferRange(target, offset as isize, length as isize, access) as *mut u8
949 | }
950 |
951 | unsafe fn polygon_offset(&self, factor: f32, units: f32) {
952 | let gl = &self.raw;
953 | gl.PolygonOffset(factor, units);
954 | }
955 |
956 | unsafe fn polygon_mode(&self, face: u32, mode: u32) {
957 | let gl = &self.raw;
958 | gl.PolygonMode(face as u32, mode as u32);
959 | }
960 |
961 | unsafe fn finish(&self) {
962 | let gl = &self.raw;
963 | gl.Finish();
964 | }
965 |
966 | unsafe fn bind_texture(&self, target: u32, texture: Option) {
967 | let gl = &self.raw;
968 | gl.BindTexture(target, texture.unwrap_or(0));
969 | }
970 |
971 | unsafe fn bind_sampler(&self, unit: u32, sampler: Option) {
972 | let gl = &self.raw;
973 | gl.BindSampler(unit, sampler.unwrap_or(0));
974 | }
975 |
976 | unsafe fn active_texture(&self, unit: u32) {
977 | let gl = &self.raw;
978 | gl.ActiveTexture(unit);
979 | }
980 |
981 | unsafe fn fence_sync(&self, condition: u32, flags: u32) -> Result {
982 | let gl = &self.raw;
983 | Ok(gl.FenceSync(condition as u32, flags))
984 | }
985 |
986 | unsafe fn tex_parameter_f32(&self, target: u32, parameter: u32, value: f32) {
987 | let gl = &self.raw;
988 | gl.TexParameterf(target, parameter, value);
989 | }
990 |
991 | unsafe fn tex_parameter_i32(&self, target: u32, parameter: u32, value: i32) {
992 | let gl = &self.raw;
993 | gl.TexParameteri(target, parameter, value);
994 | }
995 |
996 | unsafe fn tex_parameter_f32_slice(&self, target: u32, parameter: u32, values: &[f32]) {
997 | let gl = &self.raw;
998 | gl.TexParameterfv(target, parameter, values.as_ptr());
999 | }
1000 |
1001 | unsafe fn tex_parameter_i32_slice(&self, target: u32, parameter: u32, values: &[i32]) {
1002 | let gl = &self.raw;
1003 | gl.TexParameteriv(target, parameter, values.as_ptr());
1004 | }
1005 |
1006 | unsafe fn tex_sub_image_2d_u8_slice(
1007 | &self,
1008 | target: u32,
1009 | level: i32,
1010 | x_offset: i32,
1011 | y_offset: i32,
1012 | width: i32,
1013 | height: i32,
1014 | format: u32,
1015 | ty: u32,
1016 | pixels: Option<&[u8]>,
1017 | ) {
1018 | let gl = &self.raw;
1019 | gl.TexSubImage2D(
1020 | target,
1021 | level,
1022 | x_offset,
1023 | y_offset,
1024 | width,
1025 | height,
1026 | format,
1027 | ty,
1028 | pixels.map(|p| p.as_ptr()).unwrap_or(std::ptr::null()) as *const std::ffi::c_void,
1029 | );
1030 | }
1031 |
1032 | unsafe fn tex_sub_image_2d_pixel_buffer_offset(
1033 | &self,
1034 | target: u32,
1035 | level: i32,
1036 | x_offset: i32,
1037 | y_offset: i32,
1038 | width: i32,
1039 | height: i32,
1040 | format: u32,
1041 | ty: u32,
1042 | pixel_buffer_offset: i32,
1043 | ) {
1044 | let gl = &self.raw;
1045 | gl.TexSubImage2D(
1046 | target,
1047 | level,
1048 | x_offset,
1049 | y_offset,
1050 | width,
1051 | height,
1052 | format,
1053 | ty,
1054 | pixel_buffer_offset as *const std::ffi::c_void,
1055 | );
1056 | }
1057 |
1058 | unsafe fn depth_func(&self, func: u32) {
1059 | let gl = &self.raw;
1060 | gl.DepthFunc(func as u32);
1061 | }
1062 |
1063 | unsafe fn depth_range_f32(&self, near: f32, far: f32) {
1064 | let gl = &self.raw;
1065 | gl.DepthRangef(near, far);
1066 | }
1067 |
1068 | unsafe fn depth_range_f64(&self, near: f64, far: f64) {
1069 | let gl = &self.raw;
1070 | gl.DepthRange(near, far);
1071 | }
1072 |
1073 | unsafe fn depth_range_f64_slice(&self, first: u32, count: i32, values: &[[f64; 2]]) {
1074 | let gl = &self.raw;
1075 | gl.DepthRangeArrayv(first, count, values.as_ptr() as *const f64);
1076 | }
1077 |
1078 | unsafe fn scissor(&self, x: i32, y: i32, width: i32, height: i32) {
1079 | let gl = &self.raw;
1080 | gl.Scissor(x, y, width, height);
1081 | }
1082 |
1083 | unsafe fn scissor_slice(&self, first: u32, count: i32, scissors: &[[i32; 4]]) {
1084 | let gl = &self.raw;
1085 | gl.ScissorArrayv(first, count, scissors.as_ptr() as *const i32);
1086 | }
1087 |
1088 | unsafe fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
1089 | let gl = &self.raw;
1090 | gl.VertexAttribDivisor(index, divisor);
1091 | }
1092 |
1093 | unsafe fn vertex_attrib_pointer_f32(
1094 | &self,
1095 | index: u32,
1096 | size: i32,
1097 | data_type: u32,
1098 | normalized: bool,
1099 | stride: i32,
1100 | offset: i32,
1101 | ) {
1102 | let gl = &self.raw;
1103 | gl.VertexAttribPointer(
1104 | index,
1105 | size,
1106 | data_type,
1107 | normalized as u8,
1108 | stride,
1109 | offset as *const std::ffi::c_void,
1110 | );
1111 | }
1112 |
1113 | unsafe fn vertex_attrib_pointer_i32(
1114 | &self,
1115 | index: u32,
1116 | size: i32,
1117 | data_type: u32,
1118 | stride: i32,
1119 | offset: i32,
1120 | ) {
1121 | let gl = &self.raw;
1122 | gl.VertexAttribIPointer(
1123 | index,
1124 | size,
1125 | data_type,
1126 | stride,
1127 | offset as *const std::ffi::c_void,
1128 | );
1129 | }
1130 |
1131 | unsafe fn vertex_attrib_pointer_f64(
1132 | &self,
1133 | index: u32,
1134 | size: i32,
1135 | data_type: u32,
1136 | stride: i32,
1137 | offset: i32,
1138 | ) {
1139 | let gl = &self.raw;
1140 | gl.VertexAttribLPointer(
1141 | index,
1142 | size,
1143 | data_type,
1144 | stride,
1145 | offset as *const std::ffi::c_void,
1146 | );
1147 | }
1148 |
1149 | unsafe fn viewport(&self, x: i32, y: i32, width: i32, height: i32) {
1150 | let gl = &self.raw;
1151 | gl.Viewport(x, y, width, height);
1152 | }
1153 |
1154 | unsafe fn viewport_f32_slice(&self, first: u32, count: i32, values: &[[f32; 4]]) {
1155 | let gl = &self.raw;
1156 | gl.ViewportArrayv(first, count, values.as_ptr() as *const f32);
1157 | }
1158 |
1159 | unsafe fn blend_equation(&self, mode: u32) {
1160 | let gl = &self.raw;
1161 | gl.BlendEquation(mode as u32);
1162 | }
1163 |
1164 | unsafe fn blend_equation_draw_buffer(&self, draw_buffer: u32, mode: u32) {
1165 | let gl = &self.raw;
1166 | gl.BlendEquationi(draw_buffer, mode as u32);
1167 | }
1168 |
1169 | unsafe fn blend_equation_separate(&self, mode_rgb: u32, mode_alpha: u32) {
1170 | let gl = &self.raw;
1171 | gl.BlendEquationSeparate(mode_rgb as u32, mode_alpha as u32);
1172 | }
1173 |
1174 | unsafe fn blend_equation_separate_draw_buffer(
1175 | &self,
1176 | draw_buffer: u32,
1177 | mode_rgb: u32,
1178 | mode_alpha: u32,
1179 | ) {
1180 | let gl = &self.raw;
1181 | gl.BlendEquationSeparatei(draw_buffer, mode_rgb as u32, mode_alpha as u32);
1182 | }
1183 |
1184 | unsafe fn blend_func(&self, src: u32, dst: u32) {
1185 | let gl = &self.raw;
1186 | gl.BlendFunc(src as u32, dst as u32);
1187 | }
1188 |
1189 | unsafe fn blend_func_draw_buffer(&self, draw_buffer: u32, src: u32, dst: u32) {
1190 | let gl = &self.raw;
1191 | gl.BlendFunci(draw_buffer, src as u32, dst as u32);
1192 | }
1193 |
1194 | unsafe fn blend_func_separate(
1195 | &self,
1196 | src_rgb: u32,
1197 | dst_rgb: u32,
1198 | src_alpha: u32,
1199 | dst_alpha: u32,
1200 | ) {
1201 | let gl = &self.raw;
1202 | gl.BlendFuncSeparate(
1203 | src_rgb as u32,
1204 | dst_rgb as u32,
1205 | src_alpha as u32,
1206 | dst_alpha as u32,
1207 | );
1208 | }
1209 |
1210 | unsafe fn blend_func_separate_draw_buffer(
1211 | &self,
1212 | draw_buffer: u32,
1213 | src_rgb: u32,
1214 | dst_rgb: u32,
1215 | src_alpha: u32,
1216 | dst_alpha: u32,
1217 | ) {
1218 | let gl = &self.raw;
1219 | gl.BlendFuncSeparatei(
1220 | draw_buffer,
1221 | src_rgb as u32,
1222 | dst_rgb as u32,
1223 | src_alpha as u32,
1224 | dst_alpha as u32,
1225 | );
1226 | }
1227 |
1228 | unsafe fn stencil_func(&self, func: u32, reference: i32, mask: u32) {
1229 | let gl = &self.raw;
1230 | gl.StencilFunc(func as u32, reference, mask);
1231 | }
1232 |
1233 | unsafe fn stencil_func_separate(&self, face: u32, func: u32, reference: i32, mask: u32) {
1234 | let gl = &self.raw;
1235 | gl.StencilFuncSeparate(face as u32, func as u32, reference, mask);
1236 | }
1237 |
1238 | unsafe fn stencil_mask(&self, mask: u32) {
1239 | let gl = &self.raw;
1240 | gl.StencilMask(mask);
1241 | }
1242 |
1243 | unsafe fn stencil_mask_separate(&self, face: u32, mask: u32) {
1244 | let gl = &self.raw;
1245 | gl.StencilMaskSeparate(face as u32, mask);
1246 | }
1247 |
1248 | unsafe fn stencil_op(&self, stencil_fail: u32, depth_fail: u32, pass: u32) {
1249 | let gl = &self.raw;
1250 | gl.StencilOp(stencil_fail as u32, depth_fail as u32, pass as u32);
1251 | }
1252 |
1253 | unsafe fn stencil_op_separate(&self, face: u32, stencil_fail: u32, depth_fail: u32, pass: u32) {
1254 | let gl = &self.raw;
1255 | gl.StencilOpSeparate(
1256 | face as u32,
1257 | stencil_fail as u32,
1258 | depth_fail as u32,
1259 | pass as u32,
1260 | );
1261 | }
1262 | }
1263 |
1264 | pub struct RenderLoop;
1265 |
1266 | impl RenderLoop {
1267 | pub fn from_window() -> Self {
1268 | RenderLoop
1269 | }
1270 | }
1271 |
1272 | impl super::RenderLoop for RenderLoop {
1273 | type Window = Arc;
1274 |
1275 | fn run(&self, mut callback: F) {
1276 | let mut running = true;
1277 | while running {
1278 | callback(&mut running);
1279 | }
1280 | }
1281 | }
1282 |
--------------------------------------------------------------------------------
/src/web.rs:
--------------------------------------------------------------------------------
1 | use super::*;
2 |
3 | use slotmap::{new_key_type, SecondaryMap, SlotMap};
4 | use std::cell::RefCell;
5 | use wasm_bindgen::prelude::*;
6 | use web_sys::{
7 | WebGl2RenderingContext, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderbuffer,
8 | WebGlRenderingContext, WebGlSampler, WebGlShader, WebGlSync, WebGlTexture,
9 | WebGlUniformLocation, WebGlVertexArrayObject,
10 | };
11 |
12 | #[derive(Debug)]
13 | enum RawRenderingContext {
14 | WebGl1(WebGlRenderingContext),
15 | WebGl2(WebGl2RenderingContext),
16 | }
17 |
18 | // Workaround for stable Rust
19 | // See https://github.com/orlp/slotmap/blob/b5df4ac7ee8aa795668bf79ebf8929d2f39bec8e/src/lib.rs#L198
20 | type SlotMapWithoutCopy = (SlotMap, SecondaryMap);
21 |
22 | type TrackedResource = RefCell>;
23 |
24 | fn tracked_resource() -> TrackedResource {
25 | RefCell::new((SlotMap::with_key(), SecondaryMap::new()))
26 | }
27 |
28 | #[derive(Debug)]
29 | pub struct Context {
30 | raw: RawRenderingContext,
31 | shaders: TrackedResource,
32 | programs: TrackedResource,
33 | buffers: TrackedResource,
34 | vertex_arrays: TrackedResource,
35 | textures: TrackedResource,
36 | samplers: TrackedResource,
37 | fences: TrackedResource,
38 | framebuffers: TrackedResource,
39 | renderbuffers: TrackedResource,
40 | uniform_locations: TrackedResource,
41 | }
42 |
43 | impl Context {
44 | pub fn from_webgl1_context(context: WebGlRenderingContext) -> Self {
45 | Context {
46 | raw: RawRenderingContext::WebGl1(context),
47 | shaders: tracked_resource(),
48 | programs: tracked_resource(),
49 | buffers: tracked_resource(),
50 | vertex_arrays: tracked_resource(),
51 | textures: tracked_resource(),
52 | samplers: tracked_resource(),
53 | fences: tracked_resource(),
54 | framebuffers: tracked_resource(),
55 | renderbuffers: tracked_resource(),
56 | uniform_locations: tracked_resource(),
57 | }
58 | }
59 |
60 | pub fn from_webgl2_context(context: WebGl2RenderingContext) -> Self {
61 | Context {
62 | raw: RawRenderingContext::WebGl2(context),
63 | shaders: tracked_resource(),
64 | programs: tracked_resource(),
65 | buffers: tracked_resource(),
66 | vertex_arrays: tracked_resource(),
67 | textures: tracked_resource(),
68 | samplers: tracked_resource(),
69 | fences: tracked_resource(),
70 | framebuffers: tracked_resource(),
71 | renderbuffers: tracked_resource(),
72 | uniform_locations: tracked_resource(),
73 | }
74 | }
75 | }
76 |
77 | new_key_type! { pub struct WebShaderKey; }
78 | new_key_type! { pub struct WebProgramKey; }
79 | new_key_type! { pub struct WebBufferKey; }
80 | new_key_type! { pub struct WebVertexArrayKey; }
81 | new_key_type! { pub struct WebTextureKey; }
82 | new_key_type! { pub struct WebSamplerKey; }
83 | new_key_type! { pub struct WebFenceKey; }
84 | new_key_type! { pub struct WebFramebufferKey; }
85 | new_key_type! { pub struct WebRenderbufferKey; }
86 | new_key_type! { pub struct WebUniformLocationKey; }
87 |
88 | impl super::Context for Context {
89 | type Shader = WebShaderKey;
90 | type Program = WebProgramKey;
91 | type Buffer = WebBufferKey;
92 | type VertexArray = WebVertexArrayKey;
93 | type Texture = WebTextureKey;
94 | type Sampler = WebSamplerKey;
95 | type Fence = WebFenceKey;
96 | type Framebuffer = WebFramebufferKey;
97 | type Renderbuffer = WebRenderbufferKey;
98 | type UniformLocation = WebUniformLocationKey;
99 |
100 | unsafe fn create_framebuffer(&self) -> Result {
101 | let raw_framebuffer = match self.raw {
102 | RawRenderingContext::WebGl1(ref gl) => gl.create_framebuffer(),
103 | RawRenderingContext::WebGl2(ref gl) => gl.create_framebuffer(),
104 | };
105 |
106 | match raw_framebuffer {
107 | Some(s) => {
108 | let key = self.framebuffers.borrow_mut().0.insert(());
109 | self.framebuffers.borrow_mut().1.insert(key, s);
110 | Ok(key)
111 | }
112 | None => Err(String::from("Unable to create framebuffer object")),
113 | }
114 | }
115 |
116 | unsafe fn create_renderbuffer(&self) -> Result {
117 | let raw_renderbuffer = match self.raw {
118 | RawRenderingContext::WebGl1(ref gl) => gl.create_renderbuffer(),
119 | RawRenderingContext::WebGl2(ref gl) => gl.create_renderbuffer(),
120 | };
121 |
122 | match raw_renderbuffer {
123 | Some(s) => {
124 | let key = self.renderbuffers.borrow_mut().0.insert(());
125 | self.renderbuffers.borrow_mut().1.insert(key, s);
126 | Ok(key)
127 | }
128 | None => Err(String::from("Unable to create renderbuffer object")),
129 | }
130 | }
131 |
132 | unsafe fn create_sampler(&self) -> Result {
133 | let raw_sampler = match self.raw {
134 | RawRenderingContext::WebGl1(ref _gl) => panic!("Sampler objects are not supported"),
135 | RawRenderingContext::WebGl2(ref gl) => gl.create_sampler(),
136 | };
137 |
138 | match raw_sampler {
139 | Some(s) => {
140 | let key = self.samplers.borrow_mut().0.insert(());
141 | self.samplers.borrow_mut().1.insert(key, s);
142 | Ok(key)
143 | }
144 | None => Err(String::from("Unable to create sampler object")),
145 | }
146 | }
147 |
148 | unsafe fn create_shader(&self, shader_type: u32) -> Result {
149 | let raw_shader = match self.raw {
150 | RawRenderingContext::WebGl1(ref gl) => gl.create_shader(shader_type as u32),
151 | RawRenderingContext::WebGl2(ref gl) => gl.create_shader(shader_type as u32),
152 | };
153 |
154 | match raw_shader {
155 | Some(s) => {
156 | let key = self.shaders.borrow_mut().0.insert(());
157 | self.shaders.borrow_mut().1.insert(key, s);
158 | Ok(key)
159 | }
160 | None => Err(String::from("Unable to create shader object")),
161 | }
162 | }
163 |
164 | unsafe fn create_texture(&self) -> Result {
165 | let raw_texture = match self.raw {
166 | RawRenderingContext::WebGl1(ref gl) => gl.create_texture(),
167 | RawRenderingContext::WebGl2(ref gl) => gl.create_texture(),
168 | };
169 |
170 | match raw_texture {
171 | Some(t) => {
172 | let key = self.textures.borrow_mut().0.insert(());
173 | self.textures.borrow_mut().1.insert(key, t);
174 | Ok(key)
175 | }
176 | None => Err(String::from("Unable to create texture object")),
177 | }
178 | }
179 |
180 | unsafe fn delete_shader(&self, shader: Self::Shader) {
181 | let mut shaders = self.shaders.borrow_mut();
182 | match shaders.1.remove(shader) {
183 | Some(ref s) => match self.raw {
184 | RawRenderingContext::WebGl1(ref gl) => gl.delete_shader(Some(s)),
185 | RawRenderingContext::WebGl2(ref gl) => gl.delete_shader(Some(s)),
186 | },
187 | None => {}
188 | }
189 | }
190 |
191 | unsafe fn shader_source(&self, shader: Self::Shader, source: &str) {
192 | let shaders = self.shaders.borrow();
193 | let raw_shader = shaders.1.get_unchecked(shader);
194 | match self.raw {
195 | RawRenderingContext::WebGl1(ref gl) => gl.shader_source(raw_shader, source),
196 | RawRenderingContext::WebGl2(ref gl) => gl.shader_source(raw_shader, source),
197 | }
198 | }
199 |
200 | unsafe fn compile_shader(&self, shader: Self::Shader) {
201 | let shaders = self.shaders.borrow();
202 | let raw_shader = shaders.1.get_unchecked(shader);
203 | match self.raw {
204 | RawRenderingContext::WebGl1(ref gl) => gl.compile_shader(raw_shader),
205 | RawRenderingContext::WebGl2(ref gl) => gl.compile_shader(raw_shader),
206 | }
207 | }
208 |
209 | unsafe fn get_shader_compile_status(&self, shader: Self::Shader) -> bool {
210 | let shaders = self.shaders.borrow();
211 | let raw_shader = shaders.1.get_unchecked(shader);
212 | match self.raw {
213 | RawRenderingContext::WebGl1(ref gl) => {
214 | gl.get_shader_parameter(raw_shader, COMPILE_STATUS)
215 | }
216 | RawRenderingContext::WebGl2(ref gl) => {
217 | gl.get_shader_parameter(raw_shader, COMPILE_STATUS)
218 | }
219 | }
220 | .as_bool()
221 | .unwrap_or(false)
222 | }
223 |
224 | unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String {
225 | let shaders = self.shaders.borrow();
226 | let raw_shader = shaders.1.get_unchecked(shader);
227 | match self.raw {
228 | RawRenderingContext::WebGl1(ref gl) => gl.get_shader_info_log(raw_shader),
229 | RawRenderingContext::WebGl2(ref gl) => gl.get_shader_info_log(raw_shader),
230 | }
231 | .unwrap_or_else(|| String::from(""))
232 | }
233 |
234 | unsafe fn get_tex_image(
235 | &self,
236 | _target: u32,
237 | _level: i32,
238 | _format: u32,
239 | _ty: u32,
240 | _pixels: Option<&[u8]>,
241 | ) {
242 | panic!("Get tex image is not supported");
243 | }
244 |
245 | unsafe fn create_program(&self) -> Result {
246 | let raw_program = match self.raw {
247 | RawRenderingContext::WebGl1(ref gl) => gl.create_program(),
248 | RawRenderingContext::WebGl2(ref gl) => gl.create_program(),
249 | };
250 |
251 | match raw_program {
252 | Some(p) => {
253 | let key = self.programs.borrow_mut().0.insert(());
254 | self.programs.borrow_mut().1.insert(key, p);
255 | Ok(key)
256 | }
257 | None => Err(String::from("Unable to create program object")),
258 | }
259 | }
260 |
261 | unsafe fn delete_program(&self, program: Self::Program) {
262 | let mut programs = self.programs.borrow_mut();
263 | match programs.1.remove(program) {
264 | Some(ref p) => match self.raw {
265 | RawRenderingContext::WebGl1(ref gl) => gl.delete_program(Some(p)),
266 | RawRenderingContext::WebGl2(ref gl) => gl.delete_program(Some(p)),
267 | },
268 | None => {}
269 | }
270 | }
271 |
272 | unsafe fn attach_shader(&self, program: Self::Program, shader: Self::Shader) {
273 | let programs = self.programs.borrow();
274 | let shaders = self.shaders.borrow();
275 | let raw_program = programs.1.get_unchecked(program);
276 | let raw_shader = shaders.1.get_unchecked(shader);
277 | match self.raw {
278 | RawRenderingContext::WebGl1(ref gl) => gl.attach_shader(raw_program, raw_shader),
279 | RawRenderingContext::WebGl2(ref gl) => gl.attach_shader(raw_program, raw_shader),
280 | }
281 | }
282 |
283 | unsafe fn detach_shader(&self, program: Self::Program, shader: Self::Shader) {
284 | let programs = self.programs.borrow();
285 | let shaders = self.shaders.borrow();
286 | let raw_program = programs.1.get_unchecked(program);
287 | let raw_shader = shaders.1.get_unchecked(shader);
288 | match self.raw {
289 | RawRenderingContext::WebGl1(ref gl) => gl.detach_shader(raw_program, raw_shader),
290 | RawRenderingContext::WebGl2(ref gl) => gl.detach_shader(raw_program, raw_shader),
291 | }
292 | }
293 |
294 | unsafe fn link_program(&self, program: Self::Program) {
295 | let programs = self.programs.borrow();
296 | let raw_program = programs.1.get_unchecked(program);
297 | match self.raw {
298 | RawRenderingContext::WebGl1(ref gl) => gl.link_program(raw_program),
299 | RawRenderingContext::WebGl2(ref gl) => gl.link_program(raw_program),
300 | }
301 | }
302 |
303 | unsafe fn get_program_link_status(&self, program: Self::Program) -> bool {
304 | let programs = self.programs.borrow();
305 | let raw_program = programs.1.get_unchecked(program);
306 | match self.raw {
307 | RawRenderingContext::WebGl1(ref gl) => {
308 | gl.get_program_parameter(raw_program, LINK_STATUS)
309 | }
310 | RawRenderingContext::WebGl2(ref gl) => {
311 | gl.get_program_parameter(raw_program, LINK_STATUS)
312 | }
313 | }
314 | .as_bool()
315 | .unwrap_or(false)
316 | }
317 |
318 | unsafe fn get_program_info_log(&self, program: Self::Program) -> String {
319 | let programs = self.programs.borrow();
320 | let raw_program = programs.1.get_unchecked(program);
321 | match self.raw {
322 | RawRenderingContext::WebGl1(ref gl) => gl.get_program_info_log(raw_program),
323 | RawRenderingContext::WebGl2(ref gl) => gl.get_program_info_log(raw_program),
324 | }
325 | .unwrap_or_else(|| String::from(""))
326 | }
327 |
328 | unsafe fn use_program(&self, program: Option) {
329 | let programs = self.programs.borrow();
330 | let raw_program = program.map(|p| programs.1.get_unchecked(p));
331 | match self.raw {
332 | RawRenderingContext::WebGl1(ref gl) => gl.use_program(raw_program),
333 | RawRenderingContext::WebGl2(ref gl) => gl.use_program(raw_program),
334 | }
335 | }
336 |
337 | unsafe fn create_buffer(&self) -> Result {
338 | let raw_buffer = match self.raw {
339 | RawRenderingContext::WebGl1(ref gl) => gl.create_buffer(),
340 | RawRenderingContext::WebGl2(ref gl) => gl.create_buffer(),
341 | };
342 |
343 | match raw_buffer {
344 | Some(p) => {
345 | let key = self.buffers.borrow_mut().0.insert(());
346 | self.buffers.borrow_mut().1.insert(key, p);
347 | Ok(key)
348 | }
349 | None => Err(String::from("Unable to create buffer object")),
350 | }
351 | }
352 |
353 | unsafe fn bind_buffer(&self, target: u32, buffer: Option) {
354 | let buffers = self.buffers.borrow();
355 | let raw_buffer = buffer.map(|b| buffers.1.get_unchecked(b));
356 | match self.raw {
357 | RawRenderingContext::WebGl1(ref gl) => gl.bind_buffer(target, raw_buffer),
358 | RawRenderingContext::WebGl2(ref gl) => gl.bind_buffer(target, raw_buffer),
359 | }
360 | }
361 |
362 | unsafe fn bind_buffer_range(
363 | &self,
364 | _target: u32,
365 | _index: u32,
366 | _buffer: Option,
367 | _offset: i32,
368 | _size: i32,
369 | ) {
370 | // Blocked by https://github.com/rustwasm/wasm-bindgen/issues/1038
371 | panic!("Bind buffer range is not supported yet");
372 | }
373 |
374 | unsafe fn bind_framebuffer(&self, target: u32, framebuffer: Option) {
375 | let framebuffers = self.framebuffers.borrow();
376 | let raw_framebuffer = framebuffer.map(|f| framebuffers.1.get_unchecked(f));
377 | match self.raw {
378 | RawRenderingContext::WebGl1(ref gl) => gl.bind_framebuffer(target, raw_framebuffer),
379 | RawRenderingContext::WebGl2(ref gl) => gl.bind_framebuffer(target, raw_framebuffer),
380 | }
381 | }
382 |
383 | unsafe fn bind_renderbuffer(&self, target: u32, renderbuffer: Option) {
384 | let renderbuffers = self.renderbuffers.borrow();
385 | let raw_renderbuffer = renderbuffer.map(|r| renderbuffers.1.get_unchecked(r));
386 | match self.raw {
387 | RawRenderingContext::WebGl1(ref gl) => gl.bind_renderbuffer(target, raw_renderbuffer),
388 | RawRenderingContext::WebGl2(ref gl) => gl.bind_renderbuffer(target, raw_renderbuffer),
389 | }
390 | }
391 |
392 | unsafe fn create_vertex_array(&self) -> Result {
393 | let raw_vertex_array = match self.raw {
394 | RawRenderingContext::WebGl1(ref _gl) => {
395 | panic!("Vertex array objects are not supported"); // TODO: Extension
396 | }
397 | RawRenderingContext::WebGl2(ref gl) => gl.create_vertex_array(),
398 | };
399 |
400 | match raw_vertex_array {
401 | Some(va) => {
402 | let key = self.vertex_arrays.borrow_mut().0.insert(());
403 | self.vertex_arrays.borrow_mut().1.insert(key, va);
404 | Ok(key)
405 | }
406 | None => Err(String::from("Unable to create vertex array object")),
407 | }
408 | }
409 |
410 | unsafe fn delete_vertex_array(&self, vertex_array: Self::VertexArray) {
411 | let mut vertex_arrays = self.vertex_arrays.borrow_mut();
412 | match vertex_arrays.1.remove(vertex_array) {
413 | Some(ref va) => match self.raw {
414 | RawRenderingContext::WebGl1(ref _gl) => {
415 | panic!("Vertex array objects are not supported"); // TODO: Extension
416 | }
417 | RawRenderingContext::WebGl2(ref gl) => gl.delete_vertex_array(Some(va)),
418 | },
419 | None => {}
420 | }
421 | }
422 |
423 | unsafe fn bind_vertex_array(&self, vertex_array: Option) {
424 | let vertex_arrays = self.vertex_arrays.borrow();
425 | let raw_vertex_array = vertex_array.map(|va| vertex_arrays.1.get_unchecked(va));
426 | match self.raw {
427 | RawRenderingContext::WebGl1(ref _gl) => {
428 | panic!("Vertex array objects are not supported"); // TODO: Extension
429 | }
430 | RawRenderingContext::WebGl2(ref gl) => gl.bind_vertex_array(raw_vertex_array),
431 | }
432 | }
433 |
434 | unsafe fn clear_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
435 | match self.raw {
436 | RawRenderingContext::WebGl1(ref gl) => gl.clear_color(red, green, blue, alpha),
437 | RawRenderingContext::WebGl2(ref gl) => gl.clear_color(red, green, blue, alpha),
438 | }
439 | }
440 |
441 | unsafe fn supports_f64_precision() -> bool {
442 | false
443 | }
444 |
445 | unsafe fn clear_depth_f64(&self, _depth: f64) {
446 | panic!("64-bit float precision is not supported in WebGL");
447 | }
448 |
449 | unsafe fn clear_depth_f32(&self, depth: f32) {
450 | match self.raw {
451 | RawRenderingContext::WebGl1(ref gl) => gl.clear_depth(depth),
452 | RawRenderingContext::WebGl2(ref gl) => gl.clear_depth(depth),
453 | }
454 | }
455 |
456 | unsafe fn clear_stencil(&self, stencil: i32) {
457 | match self.raw {
458 | RawRenderingContext::WebGl1(ref gl) => gl.clear_stencil(stencil),
459 | RawRenderingContext::WebGl2(ref gl) => gl.clear_stencil(stencil),
460 | }
461 | }
462 |
463 | unsafe fn clear(&self, mask: u32) {
464 | match self.raw {
465 | RawRenderingContext::WebGl1(ref gl) => gl.clear(mask),
466 | RawRenderingContext::WebGl2(ref gl) => gl.clear(mask),
467 | }
468 | }
469 |
470 | unsafe fn patch_parameter_i32(&self, _parameter: u32, _value: i32) {
471 | panic!("Patch parameter is not supported");
472 | }
473 |
474 | unsafe fn pixel_store_i32(&self, parameter: u32, value: i32) {
475 | match self.raw {
476 | RawRenderingContext::WebGl1(ref gl) => gl.pixel_storei(parameter, value),
477 | RawRenderingContext::WebGl2(ref gl) => gl.pixel_storei(parameter, value),
478 | }
479 | }
480 |
481 | unsafe fn pixel_store_bool(&self, parameter: u32, value: bool) {
482 | match self.raw {
483 | RawRenderingContext::WebGl1(ref gl) => gl.pixel_storei(parameter, value as i32),
484 | RawRenderingContext::WebGl2(ref gl) => gl.pixel_storei(parameter, value as i32),
485 | }
486 | }
487 |
488 | unsafe fn bind_frag_data_location(
489 | &self,
490 | _program: Self::Program,
491 | _color_number: u32,
492 | _name: &str,
493 | ) {
494 | panic!("Bind frag data location is not supported");
495 | }
496 |
497 | unsafe fn buffer_data_size(&self, target: u32, size: i32, usage: u32) {
498 | match self.raw {
499 | RawRenderingContext::WebGl1(ref gl) => gl.buffer_data_with_i32(target, size, usage),
500 | RawRenderingContext::WebGl2(ref gl) => gl.buffer_data_with_i32(target, size, usage),
501 | }
502 | }
503 |
504 | unsafe fn buffer_data_u8_slice(&self, target: u32, data: &[u8], usage: u32) {
505 | match self.raw {
506 | RawRenderingContext::WebGl1(ref gl) => {
507 | gl.buffer_data_with_u8_array(target, data, usage)
508 | }
509 | RawRenderingContext::WebGl2(ref gl) => {
510 | gl.buffer_data_with_u8_array(target, data, usage)
511 | }
512 | }
513 | }
514 |
515 | unsafe fn buffer_storage(
516 | &self,
517 | _target: u32,
518 | _size: i32,
519 | _data: Option<&mut [u8]>,
520 | _flags: u32,
521 | ) {
522 | panic!("Buffer storage is not supported");
523 | }
524 |
525 | unsafe fn check_framebuffer_status(&self, target: u32) -> u32 {
526 | match self.raw {
527 | RawRenderingContext::WebGl1(ref gl) => gl.check_framebuffer_status(target),
528 | RawRenderingContext::WebGl2(ref gl) => gl.check_framebuffer_status(target),
529 | }
530 | }
531 |
532 | unsafe fn clear_buffer_i32_slice(&self, target: u32, draw_buffer: u32, values: &mut [i32]) {
533 | match self.raw {
534 | RawRenderingContext::WebGl1(ref _gl) => {
535 | panic!("Clear buffer with `i32` slice is not supported");
536 | }
537 | RawRenderingContext::WebGl2(ref gl) => {
538 | gl.clear_bufferiv_with_i32_array(target, draw_buffer as i32, values);
539 | }
540 | }
541 | }
542 |
543 | unsafe fn clear_buffer_u32_slice(&self, target: u32, draw_buffer: u32, values: &mut [u32]) {
544 | match self.raw {
545 | RawRenderingContext::WebGl1(ref _gl) => {
546 | panic!("Clear buffer with `u32` slice is not supported")
547 | }
548 | RawRenderingContext::WebGl2(ref gl) => {
549 | gl.clear_bufferuiv_with_u32_array(target, draw_buffer as i32, values)
550 | }
551 | }
552 | }
553 |
554 | unsafe fn clear_buffer_f32_slice(&self, target: u32, draw_buffer: u32, values: &mut [f32]) {
555 | match self.raw {
556 | RawRenderingContext::WebGl1(ref _gl) => {
557 | panic!("Clear buffer with `f32` slice is not supported")
558 | }
559 | RawRenderingContext::WebGl2(ref gl) => {
560 | gl.clear_bufferfv_with_f32_array(target, draw_buffer as i32, values)
561 | }
562 | }
563 | }
564 |
565 | unsafe fn clear_buffer_depth_stencil(
566 | &self,
567 | target: u32,
568 | draw_buffer: u32,
569 | depth: f32,
570 | stencil: i32,
571 | ) {
572 | match self.raw {
573 | RawRenderingContext::WebGl1(ref _gl) => {
574 | panic!("Clear buffer depth stencil is not supported")
575 | }
576 | RawRenderingContext::WebGl2(ref gl) => {
577 | gl.clear_bufferfi(target, draw_buffer as i32, depth, stencil)
578 | }
579 | }
580 | }
581 |
582 | unsafe fn client_wait_sync(&self, _fence: Self::Fence, _flags: u32, _timeout: i32) -> u32 {
583 | panic!("Client wait sync is not supported")
584 | }
585 |
586 | unsafe fn copy_buffer_sub_data(
587 | &self,
588 | src_target: u32,
589 | dst_target: u32,
590 | src_offset: i32,
591 | dst_offset: i32,
592 | size: i32,
593 | ) {
594 | match self.raw {
595 | RawRenderingContext::WebGl1(ref _gl) => panic!("Copy buffer subdata is not supported"),
596 | RawRenderingContext::WebGl2(ref gl) => gl
597 | .copy_buffer_sub_data_with_i32_and_i32_and_i32(
598 | src_target, dst_target, src_offset, dst_offset, size,
599 | ),
600 | }
601 | }
602 |
603 | unsafe fn delete_buffer(&self, buffer: Self::Buffer) {
604 | let mut buffers = self.buffers.borrow_mut();
605 | match buffers.1.remove(buffer) {
606 | Some(ref b) => match self.raw {
607 | RawRenderingContext::WebGl1(ref gl) => gl.delete_buffer(Some(b)),
608 | RawRenderingContext::WebGl2(ref gl) => gl.delete_buffer(Some(b)),
609 | },
610 | None => {}
611 | }
612 | }
613 |
614 | unsafe fn delete_framebuffer(&self, framebuffer: Self::Framebuffer) {
615 | let mut framebuffers = self.framebuffers.borrow_mut();
616 | match framebuffers.1.remove(framebuffer) {
617 | Some(ref f) => match self.raw {
618 | RawRenderingContext::WebGl1(ref gl) => gl.delete_framebuffer(Some(f)),
619 | RawRenderingContext::WebGl2(ref gl) => gl.delete_framebuffer(Some(f)),
620 | },
621 | None => {}
622 | }
623 | }
624 |
625 | unsafe fn delete_renderbuffer(&self, renderbuffer: Self::Renderbuffer) {
626 | let mut renderbuffers = self.renderbuffers.borrow_mut();
627 | match renderbuffers.1.remove(renderbuffer) {
628 | Some(ref r) => match self.raw {
629 | RawRenderingContext::WebGl1(ref gl) => gl.delete_renderbuffer(Some(r)),
630 | RawRenderingContext::WebGl2(ref gl) => gl.delete_renderbuffer(Some(r)),
631 | },
632 | None => {}
633 | }
634 | }
635 |
636 | unsafe fn delete_sampler(&self, sampler: Self::Sampler) {
637 | let mut samplers = self.samplers.borrow_mut();
638 | match samplers.1.remove(sampler) {
639 | Some(ref s) => match self.raw {
640 | RawRenderingContext::WebGl1(ref _gl) => panic!("Samplers are not supported"),
641 | RawRenderingContext::WebGl2(ref gl) => gl.delete_sampler(Some(s)),
642 | },
643 | None => {}
644 | }
645 | }
646 |
647 | unsafe fn delete_sync(&self, fence: Self::Fence) {
648 | let mut fences = self.fences.borrow_mut();
649 | match fences.1.remove(fence) {
650 | Some(ref f) => match self.raw {
651 | RawRenderingContext::WebGl1(ref _gl) => panic!("Fences are not supported"),
652 | RawRenderingContext::WebGl2(ref gl) => gl.delete_sync(Some(f)),
653 | },
654 | None => {}
655 | }
656 | }
657 |
658 | unsafe fn delete_texture(&self, texture: Self::Texture) {
659 | let mut textures = self.textures.borrow_mut();
660 | match textures.1.remove(texture) {
661 | Some(ref t) => match self.raw {
662 | RawRenderingContext::WebGl1(ref gl) => gl.delete_texture(Some(t)),
663 | RawRenderingContext::WebGl2(ref gl) => gl.delete_texture(Some(t)),
664 | },
665 | None => {}
666 | }
667 | }
668 |
669 | unsafe fn disable(&self, parameter: u32) {
670 | match self.raw {
671 | RawRenderingContext::WebGl1(ref gl) => gl.disable(parameter),
672 | RawRenderingContext::WebGl2(ref gl) => gl.disable(parameter),
673 | }
674 | }
675 |
676 | unsafe fn disable_draw_buffer(&self, _parameter: u32, _draw_buffer: u32) {
677 | panic!("Draw buffer disable is not supported");
678 | }
679 |
680 | unsafe fn disable_vertex_attrib_array(&self, index: u32) {
681 | match self.raw {
682 | RawRenderingContext::WebGl1(ref gl) => gl.disable_vertex_attrib_array(index),
683 | RawRenderingContext::WebGl2(ref gl) => gl.disable_vertex_attrib_array(index),
684 | }
685 | }
686 |
687 | unsafe fn dispatch_compute(&self, _groups_x: u32, _groups_y: u32, _groups_z: u32) {
688 | panic!("Dispatch compute is not supported");
689 | }
690 |
691 | unsafe fn dispatch_compute_indirect(&self, _offset: i32) {
692 | panic!("Dispatch compute indirect is not supported");
693 | }
694 |
695 | unsafe fn draw_arrays(&self, mode: u32, first: i32, count: i32) {
696 | match self.raw {
697 | RawRenderingContext::WebGl1(ref gl) => gl.draw_arrays(mode as u32, first, count),
698 | RawRenderingContext::WebGl2(ref gl) => gl.draw_arrays(mode as u32, first, count),
699 | }
700 | }
701 |
702 | unsafe fn draw_arrays_instanced(&self, mode: u32, first: i32, count: i32, instance_count: i32) {
703 | match self.raw {
704 | RawRenderingContext::WebGl1(ref _gl) => {
705 | panic!("Draw arrays instanced is not supported") // TODO: Extension
706 | }
707 | RawRenderingContext::WebGl2(ref gl) => {
708 | gl.draw_arrays_instanced(mode as u32, first, count, instance_count)
709 | }
710 | }
711 | }
712 |
713 | unsafe fn draw_arrays_instanced_base_instance(
714 | &self,
715 | _mode: u32,
716 | _first: i32,
717 | _count: i32,
718 | _instance_count: i32,
719 | _base_instance: u32,
720 | ) {
721 | panic!("Draw arrays instanced base instance is not supported");
722 | }
723 |
724 | unsafe fn draw_buffer(&self, _draw_buffer: u32) {
725 | // Blocked by https://github.com/rustwasm/wasm-bindgen/issues/1038
726 | panic!("Draw buffer is not supported yet");
727 | }
728 |
729 | unsafe fn draw_buffers(&self, _buffers: &[u32]) {
730 | // Blocked by https://github.com/rustwasm/wasm-bindgen/issues/1038
731 | panic!("Draw buffers is not supported yet");
732 | }
733 |
734 | unsafe fn draw_elements(&self, mode: u32, count: i32, element_type: u32, offset: i32) {
735 | match self.raw {
736 | RawRenderingContext::WebGl1(ref gl) => {
737 | gl.draw_elements_with_i32(mode as u32, count, element_type as u32, offset);
738 | }
739 | RawRenderingContext::WebGl2(ref gl) => {
740 | gl.draw_elements_with_i32(mode as u32, count, element_type as u32, offset);
741 | }
742 | }
743 | }
744 |
745 | unsafe fn draw_elements_base_vertex(
746 | &self,
747 | _mode: u32,
748 | _count: i32,
749 | _element_type: u32,
750 | _offset: i32,
751 | _base_vertex: i32,
752 | ) {
753 | panic!("Draw elements base vertex is not supported");
754 | }
755 |
756 | unsafe fn draw_elements_instanced(
757 | &self,
758 | mode: u32,
759 | count: i32,
760 | element_type: u32,
761 | offset: i32,
762 | instance_count: i32,
763 | ) {
764 | match self.raw {
765 | RawRenderingContext::WebGl1(ref _gl) => {
766 | panic!("Draw elements instanced is not supported") // TODO: Extension
767 | }
768 | RawRenderingContext::WebGl2(ref gl) => {
769 | gl.draw_elements_instanced_with_i32(
770 | mode as u32,
771 | count,
772 | element_type as u32,
773 | offset,
774 | instance_count,
775 | );
776 | }
777 | }
778 | }
779 |
780 | unsafe fn draw_elements_instanced_base_vertex(
781 | &self,
782 | _mode: u32,
783 | _count: i32,
784 | _element_type: u32,
785 | _offset: i32,
786 | _instance_count: i32,
787 | _base_vertex: i32,
788 | ) {
789 | panic!("Draw elements instanced base vertex is not supported");
790 | }
791 |
792 | unsafe fn draw_elements_instanced_base_vertex_base_instance(
793 | &self,
794 | _mode: u32,
795 | _count: i32,
796 | _element_type: u32,
797 | _offset: i32,
798 | _instance_count: i32,
799 | _base_vertex: i32,
800 | _base_instance: u32,
801 | ) {
802 | panic!("Draw elements instanced base vertex base instance is not supported");
803 | }
804 |
805 | unsafe fn enable(&self, parameter: u32) {
806 | match self.raw {
807 | RawRenderingContext::WebGl1(ref gl) => gl.enable(parameter),
808 | RawRenderingContext::WebGl2(ref gl) => gl.enable(parameter),
809 | }
810 | }
811 |
812 | unsafe fn enable_draw_buffer(&self, _parameter: u32, _draw_buffer: u32) {
813 | panic!("Draw buffer enable is not supported");
814 | }
815 |
816 | unsafe fn enable_vertex_attrib_array(&self, index: u32) {
817 | match self.raw {
818 | RawRenderingContext::WebGl1(ref gl) => gl.enable_vertex_attrib_array(index),
819 | RawRenderingContext::WebGl2(ref gl) => gl.enable_vertex_attrib_array(index),
820 | }
821 | }
822 |
823 | unsafe fn flush(&self) {
824 | match self.raw {
825 | RawRenderingContext::WebGl1(ref gl) => gl.flush(),
826 | RawRenderingContext::WebGl2(ref gl) => gl.flush(),
827 | }
828 | }
829 |
830 | unsafe fn framebuffer_renderbuffer(
831 | &self,
832 | target: u32,
833 | attachment: u32,
834 | renderbuffer_target: u32,
835 | renderbuffer: Option,
836 | ) {
837 | let renderbuffers = self.renderbuffers.borrow();
838 | let raw_renderbuffer = renderbuffer.map(|r| renderbuffers.1.get_unchecked(r));
839 | match self.raw {
840 | RawRenderingContext::WebGl1(ref _gl) => {
841 | panic!("Framebuffer renderbuffer is not supported");
842 | }
843 | RawRenderingContext::WebGl2(ref gl) => gl.framebuffer_renderbuffer(
844 | target,
845 | attachment,
846 | renderbuffer_target,
847 | raw_renderbuffer,
848 | ),
849 | }
850 | }
851 |
852 | unsafe fn framebuffer_texture(
853 | &self,
854 | _target: u32,
855 | _attachment: u32,
856 | _texture: Option,
857 | _level: i32,
858 | ) {
859 | panic!("Framebuffer texture is not supported");
860 | }
861 |
862 | unsafe fn framebuffer_texture_2d(
863 | &self,
864 | target: u32,
865 | attachment: u32,
866 | texture_target: u32,
867 | texture: Option,
868 | level: i32,
869 | ) {
870 | let textures = self.textures.borrow();
871 | let raw_texture = texture.map(|t| textures.1.get_unchecked(t));
872 | match self.raw {
873 | RawRenderingContext::WebGl1(ref gl) => {
874 | gl.framebuffer_texture_2d(target, attachment, texture_target, raw_texture, level);
875 | }
876 | RawRenderingContext::WebGl2(ref gl) => {
877 | gl.framebuffer_texture_2d(target, attachment, texture_target, raw_texture, level);
878 | }
879 | }
880 | }
881 |
882 | unsafe fn framebuffer_texture_3d(
883 | &self,
884 | _target: u32,
885 | _attachment: u32,
886 | _texture_target: u32,
887 | _texture: Option,
888 | _level: i32,
889 | _layer: i32,
890 | ) {
891 | panic!("Framebuffer texture 3D is not supported");
892 | }
893 |
894 | unsafe fn framebuffer_texture_layer(
895 | &self,
896 | target: u32,
897 | attachment: u32,
898 | texture: Option,
899 | level: i32,
900 | layer: i32,
901 | ) {
902 | let textures = self.textures.borrow();
903 | let raw_texture = texture.map(|t| textures.1.get_unchecked(t));
904 | match self.raw {
905 | RawRenderingContext::WebGl1(ref _gl) => {
906 | panic!("Framebuffer texture layer is not supported");
907 | }
908 | RawRenderingContext::WebGl2(ref gl) => {
909 | gl.framebuffer_texture_layer(target, attachment, raw_texture, level, layer);
910 | }
911 | }
912 | }
913 |
914 | unsafe fn front_face(&self, value: u32) {
915 | match self.raw {
916 | RawRenderingContext::WebGl1(ref gl) => gl.front_face(value as u32),
917 | RawRenderingContext::WebGl2(ref gl) => gl.front_face(value as u32),
918 | }
919 | }
920 |
921 | unsafe fn get_error(&self) -> u32 {
922 | match self.raw {
923 | RawRenderingContext::WebGl1(ref gl) => gl.get_error(),
924 | RawRenderingContext::WebGl2(ref gl) => gl.get_error(),
925 | }
926 | }
927 |
928 | unsafe fn get_parameter_i32(&self, parameter: u32) -> i32 {
929 | match self.raw {
930 | RawRenderingContext::WebGl1(ref gl) => gl.get_parameter(parameter),
931 | RawRenderingContext::WebGl2(ref gl) => gl.get_parameter(parameter),
932 | }
933 | .unwrap()
934 | .as_f64()
935 | .map(|v| v as i32)
936 | // Errors will be caught by the browser or through `get_error`
937 | // so return a default instead
938 | .unwrap_or(0)
939 | }
940 |
941 | unsafe fn get_parameter_indexed_i32(&self, parameter: u32, index: u32) -> i32 {
942 | match self.raw {
943 | RawRenderingContext::WebGl1(ref _gl) => {
944 | panic!("Get parameter indexed is not supported")
945 | }
946 | RawRenderingContext::WebGl2(ref gl) => gl.get_indexed_parameter(parameter, index),
947 | }
948 | .unwrap()
949 | .as_f64()
950 | .map(|v| v as i32)
951 | // Errors will be caught by the browser or through `get_error`
952 | // so return a default instead
953 | .unwrap_or(0)
954 | }
955 |
956 | unsafe fn get_parameter_indexed_string(&self, parameter: u32, index: u32) -> String {
957 | match self.raw {
958 | RawRenderingContext::WebGl1(ref _gl) => {
959 | panic!("Get parameter indexed is not supported")
960 | }
961 | RawRenderingContext::WebGl2(ref gl) => gl.get_indexed_parameter(parameter, index),
962 | }
963 | .unwrap()
964 | .as_string()
965 | // Errors will be caught by the browser or through `get_error`
966 | // so return a default instead
967 | .unwrap_or(String::from(""))
968 | }
969 |
970 | unsafe fn get_parameter_string(&self, parameter: u32) -> String {
971 | match self.raw {
972 | RawRenderingContext::WebGl1(ref gl) => gl.get_parameter(parameter),
973 | RawRenderingContext::WebGl2(ref gl) => gl.get_parameter(parameter),
974 | }
975 | .unwrap()
976 | .as_string()
977 | // Errors will be caught by the browser or through `get_error`
978 | // so return a default instead
979 | .unwrap_or(String::from(""))
980 | }
981 |
982 | unsafe fn get_uniform_location(
983 | &self,
984 | program: Self::Program,
985 | name: &str,
986 | ) -> Option {
987 | let programs = self.programs.borrow();
988 | let raw_program = programs.1.get_unchecked(program);
989 | let raw_uniform = match self.raw {
990 | RawRenderingContext::WebGl1(ref gl) => gl.get_uniform_location(raw_program, name),
991 | RawRenderingContext::WebGl2(ref gl) => gl.get_uniform_location(raw_program, name),
992 | };
993 | if let Some(u) = raw_uniform {
994 | let mut uniform_locations = self.uniform_locations.borrow_mut();
995 | let key = uniform_locations.0.insert(());
996 | uniform_locations.1.insert(key, u);
997 | Some(key)
998 | } else {
999 | None
1000 | }
1001 | }
1002 |
1003 | unsafe fn get_attrib_location(
1004 | &self,
1005 | program: Self::Program,
1006 | name: &str,
1007 | ) -> i32 {
1008 | let programs = self.programs.borrow();
1009 | let raw_program = programs.1.get_unchecked(program);
1010 | match self.raw {
1011 | RawRenderingContext::WebGl1(ref gl) => gl.get_attrib_location(raw_program, name),
1012 | RawRenderingContext::WebGl2(ref gl) => gl.get_attrib_location(raw_program, name),
1013 | }
1014 | }
1015 |
1016 | unsafe fn is_sync(&self, fence: Self::Fence) -> bool {
1017 | let fences = self.fences.borrow();
1018 | let raw_fence = fences.1.get_unchecked(fence);
1019 | match self.raw {
1020 | RawRenderingContext::WebGl1(ref _gl) => panic!("Sync is not supported"),
1021 | RawRenderingContext::WebGl2(ref gl) => gl.is_sync(Some(raw_fence)),
1022 | }
1023 | }
1024 |
1025 | unsafe fn renderbuffer_storage(
1026 | &self,
1027 | target: u32,
1028 | internal_format: u32,
1029 | width: i32,
1030 | height: i32,
1031 | ) {
1032 | match self.raw {
1033 | RawRenderingContext::WebGl1(ref gl) => {
1034 | gl.renderbuffer_storage(target, internal_format, width, height);
1035 | }
1036 | RawRenderingContext::WebGl2(ref gl) => {
1037 | gl.renderbuffer_storage(target, internal_format, width, height);
1038 | }
1039 | }
1040 | }
1041 |
1042 | unsafe fn sampler_parameter_f32(&self, sampler: Self::Sampler, name: u32, value: f32) {
1043 | let samplers = self.samplers.borrow();
1044 | let raw_sampler = samplers.1.get_unchecked(sampler);
1045 | match self.raw {
1046 | RawRenderingContext::WebGl1(ref _gl) => {
1047 | panic!("Samper parameter for `f32` is not supported")
1048 | }
1049 | RawRenderingContext::WebGl2(ref gl) => {
1050 | gl.sampler_parameterf(raw_sampler, name, value);
1051 | }
1052 | }
1053 | }
1054 |
1055 | unsafe fn sampler_parameter_f32_slice(
1056 | &self,
1057 | _sampler: Self::Sampler,
1058 | _name: u32,
1059 | _value: &mut [f32],
1060 | ) {
1061 | panic!("Sampler parameter for `f32` slice is not supported");
1062 | }
1063 |
1064 | unsafe fn sampler_parameter_i32(&self, sampler: Self::Sampler, name: u32, value: i32) {
1065 | let samplers = self.samplers.borrow();
1066 | let raw_sampler = samplers.1.get_unchecked(sampler);
1067 | match self.raw {
1068 | RawRenderingContext::WebGl1(ref _gl) => {
1069 | panic!("Samper parameter for `i32` is not supported")
1070 | }
1071 | RawRenderingContext::WebGl2(ref gl) => {
1072 | gl.sampler_parameteri(raw_sampler, name, value);
1073 | }
1074 | }
1075 | }
1076 |
1077 | unsafe fn tex_image_2d(
1078 | &self,
1079 | target: u32,
1080 | level: i32,
1081 | internal_format: i32,
1082 | width: i32,
1083 | height: i32,
1084 | border: i32,
1085 | format: u32,
1086 | ty: u32,
1087 | pixels: Option<&[u8]>,
1088 | ) {
1089 | match self.raw {
1090 | RawRenderingContext::WebGl1(ref gl) => {
1091 | // TODO: Handle return value?
1092 | gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
1093 | target,
1094 | level,
1095 | internal_format,
1096 | width,
1097 | height,
1098 | border,
1099 | format,
1100 | ty,
1101 | pixels,
1102 | )
1103 | .unwrap();
1104 | }
1105 | RawRenderingContext::WebGl2(ref gl) => {
1106 | // TODO: Handle return value?
1107 | gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
1108 | target,
1109 | level,
1110 | internal_format,
1111 | width,
1112 | height,
1113 | border,
1114 | format,
1115 | ty,
1116 | pixels,
1117 | )
1118 | .unwrap();
1119 | }
1120 | }
1121 | }
1122 |
1123 | unsafe fn tex_storage_2d(
1124 | &self,
1125 | target: u32,
1126 | levels: i32,
1127 | internal_format: u32,
1128 | width: i32,
1129 | height: i32,
1130 | ) {
1131 | match self.raw {
1132 | RawRenderingContext::WebGl1(ref _gl) => panic!("Tex storage 2D is not supported"),
1133 | RawRenderingContext::WebGl2(ref gl) => {
1134 | gl.tex_storage_2d(target, levels, internal_format, width, height);
1135 | }
1136 | }
1137 | }
1138 |
1139 | unsafe fn uniform_1_i32(&self, uniform_location: Option, x: i32) {
1140 | let uniform_locations = self.uniform_locations.borrow();
1141 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1142 | match self.raw {
1143 | RawRenderingContext::WebGl1(ref gl) => gl.uniform1i(raw_uniform_location, x),
1144 | RawRenderingContext::WebGl2(ref gl) => gl.uniform1i(raw_uniform_location, x),
1145 | }
1146 | }
1147 |
1148 | unsafe fn uniform_2_i32(&self, uniform_location: Option, x: i32, y: i32) {
1149 | let uniform_locations = self.uniform_locations.borrow();
1150 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1151 | match self.raw {
1152 | RawRenderingContext::WebGl1(ref gl) => gl.uniform2i(raw_uniform_location, x, y),
1153 | RawRenderingContext::WebGl2(ref gl) => gl.uniform2i(raw_uniform_location, x, y),
1154 | }
1155 | }
1156 |
1157 | unsafe fn uniform_3_i32(&self, uniform_location: Option, x: i32, y: i32, z: i32) {
1158 | let uniform_locations = self.uniform_locations.borrow();
1159 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1160 | match self.raw {
1161 | RawRenderingContext::WebGl1(ref gl) => gl.uniform3i(raw_uniform_location, x, y, z),
1162 | RawRenderingContext::WebGl2(ref gl) => gl.uniform3i(raw_uniform_location, x, y, z),
1163 | }
1164 | }
1165 |
1166 | unsafe fn uniform_4_i32(&self, uniform_location: Option, x: i32, y: i32, z: i32, w: i32) {
1167 | let uniform_locations = self.uniform_locations.borrow();
1168 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1169 | match self.raw {
1170 | RawRenderingContext::WebGl1(ref gl) => gl.uniform4i(raw_uniform_location, x, y, z, w),
1171 | RawRenderingContext::WebGl2(ref gl) => gl.uniform4i(raw_uniform_location, x, y, z, w),
1172 | }
1173 | }
1174 |
1175 | unsafe fn uniform_1_i32_slice(&self, uniform_location: Option, v: &mut [i32; 1]) {
1176 | let uniform_locations = self.uniform_locations.borrow();
1177 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1178 | match self.raw {
1179 | RawRenderingContext::WebGl1(ref gl) => gl.uniform1iv_with_i32_array(raw_uniform_location, v),
1180 | RawRenderingContext::WebGl2(ref gl) => gl.uniform1iv_with_i32_array(raw_uniform_location, v),
1181 | }
1182 | }
1183 |
1184 | unsafe fn uniform_2_i32_slice(&self, uniform_location: Option, v: &mut [i32; 2]) {
1185 | let uniform_locations = self.uniform_locations.borrow();
1186 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1187 | match self.raw {
1188 | RawRenderingContext::WebGl1(ref gl) => gl.uniform2iv_with_i32_array(raw_uniform_location, v),
1189 | RawRenderingContext::WebGl2(ref gl) => gl.uniform2iv_with_i32_array(raw_uniform_location, v),
1190 | }
1191 | }
1192 |
1193 | unsafe fn uniform_3_i32_slice(&self, uniform_location: Option, v: &mut [i32; 3]) {
1194 | let uniform_locations = self.uniform_locations.borrow();
1195 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1196 | match self.raw {
1197 | RawRenderingContext::WebGl1(ref gl) => gl.uniform3iv_with_i32_array(raw_uniform_location, v),
1198 | RawRenderingContext::WebGl2(ref gl) => gl.uniform3iv_with_i32_array(raw_uniform_location, v),
1199 | }
1200 | }
1201 |
1202 | unsafe fn uniform_4_i32_slice(&self, uniform_location: Option, v: &mut [i32; 4]) {
1203 | let uniform_locations = self.uniform_locations.borrow();
1204 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1205 | match self.raw {
1206 | RawRenderingContext::WebGl1(ref gl) => gl.uniform4iv_with_i32_array(raw_uniform_location, v),
1207 | RawRenderingContext::WebGl2(ref gl) => gl.uniform4iv_with_i32_array(raw_uniform_location, v),
1208 | }
1209 | }
1210 |
1211 | unsafe fn uniform_1_f32(&self, uniform_location: Option, x: f32) {
1212 | let uniform_locations = self.uniform_locations.borrow();
1213 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1214 | match self.raw {
1215 | RawRenderingContext::WebGl1(ref gl) => gl.uniform1f(raw_uniform_location, x),
1216 | RawRenderingContext::WebGl2(ref gl) => gl.uniform1f(raw_uniform_location, x),
1217 | }
1218 | }
1219 |
1220 | unsafe fn uniform_2_f32(&self, uniform_location: Option, x: f32, y: f32) {
1221 | let uniform_locations = self.uniform_locations.borrow();
1222 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1223 | match self.raw {
1224 | RawRenderingContext::WebGl1(ref gl) => gl.uniform2f(raw_uniform_location, x, y),
1225 | RawRenderingContext::WebGl2(ref gl) => gl.uniform2f(raw_uniform_location, x, y),
1226 | }
1227 | }
1228 |
1229 | unsafe fn uniform_3_f32(&self, uniform_location: Option, x: f32, y: f32, z: f32) {
1230 | let uniform_locations = self.uniform_locations.borrow();
1231 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1232 | match self.raw {
1233 | RawRenderingContext::WebGl1(ref gl) => gl.uniform3f(raw_uniform_location, x, y, z),
1234 | RawRenderingContext::WebGl2(ref gl) => gl.uniform3f(raw_uniform_location, x, y, z),
1235 | }
1236 | }
1237 |
1238 | unsafe fn uniform_4_f32(&self, uniform_location: Option, x: f32, y: f32, z: f32, w: f32) {
1239 | let uniform_locations = self.uniform_locations.borrow();
1240 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1241 | match self.raw {
1242 | RawRenderingContext::WebGl1(ref gl) => gl.uniform4f(raw_uniform_location, x, y, z, w),
1243 | RawRenderingContext::WebGl2(ref gl) => gl.uniform4f(raw_uniform_location, x, y, z, w),
1244 | }
1245 | }
1246 |
1247 | unsafe fn uniform_1_f32_slice(&self, uniform_location: Option, v: &[f32; 1]) {
1248 | let uniform_locations = self.uniform_locations.borrow();
1249 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1250 | match self.raw {
1251 | RawRenderingContext::WebGl1(ref gl) => gl.uniform1fv_with_f32_array(raw_uniform_location, v),
1252 | RawRenderingContext::WebGl2(ref gl) => gl.uniform1fv_with_f32_array(raw_uniform_location, v),
1253 | }
1254 | }
1255 |
1256 | unsafe fn uniform_2_f32_slice(&self, uniform_location: Option, v: &[f32; 2]) {
1257 | let uniform_locations = self.uniform_locations.borrow();
1258 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1259 | match self.raw {
1260 | RawRenderingContext::WebGl1(ref gl) => gl.uniform2fv_with_f32_array(raw_uniform_location, v),
1261 | RawRenderingContext::WebGl2(ref gl) => gl.uniform2fv_with_f32_array(raw_uniform_location, v),
1262 | }
1263 | }
1264 |
1265 | unsafe fn uniform_3_f32_slice(&self, uniform_location: Option, v: &[f32; 3]) {
1266 | let uniform_locations = self.uniform_locations.borrow();
1267 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1268 | match self.raw {
1269 | RawRenderingContext::WebGl1(ref gl) => gl.uniform3fv_with_f32_array(raw_uniform_location, v),
1270 | RawRenderingContext::WebGl2(ref gl) => gl.uniform3fv_with_f32_array(raw_uniform_location, v),
1271 | }
1272 | }
1273 |
1274 | unsafe fn uniform_4_f32_slice(&self, uniform_location: Option, v: &[f32; 4]) {
1275 | let uniform_locations = self.uniform_locations.borrow();
1276 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1277 | match self.raw {
1278 | RawRenderingContext::WebGl1(ref gl) => gl.uniform4fv_with_f32_array(raw_uniform_location, v),
1279 | RawRenderingContext::WebGl2(ref gl) => gl.uniform4fv_with_f32_array(raw_uniform_location, v),
1280 | }
1281 | }
1282 |
1283 | unsafe fn uniform_matrix_2_f32_slice(&self, uniform_location: Option, transpose: bool, v: &[f32; 4]) {
1284 | let uniform_locations = self.uniform_locations.borrow();
1285 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1286 | match self.raw {
1287 | RawRenderingContext::WebGl1(ref gl) => gl.uniform_matrix2fv_with_f32_array(raw_uniform_location, transpose, v),
1288 | RawRenderingContext::WebGl2(ref gl) => gl.uniform_matrix2fv_with_f32_array(raw_uniform_location, transpose, v),
1289 | }
1290 | }
1291 |
1292 | unsafe fn uniform_matrix_3_f32_slice(&self, uniform_location: Option, transpose: bool, v: &[f32; 9]) {
1293 | let uniform_locations = self.uniform_locations.borrow();
1294 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1295 | match self.raw {
1296 | RawRenderingContext::WebGl1(ref gl) => gl.uniform_matrix3fv_with_f32_array(raw_uniform_location, transpose, v),
1297 | RawRenderingContext::WebGl2(ref gl) => gl.uniform_matrix3fv_with_f32_array(raw_uniform_location, transpose, v),
1298 | }
1299 | }
1300 |
1301 | unsafe fn uniform_matrix_4_f32_slice(&self, uniform_location: Option, transpose: bool, v: &[f32; 16]) {
1302 | let uniform_locations = self.uniform_locations.borrow();
1303 | let raw_uniform_location = uniform_location.map(|u| uniform_locations.1.get_unchecked(u));
1304 | match self.raw {
1305 | RawRenderingContext::WebGl1(ref gl) => gl.uniform_matrix4fv_with_f32_array(raw_uniform_location, transpose, v),
1306 | RawRenderingContext::WebGl2(ref gl) => gl.uniform_matrix4fv_with_f32_array(raw_uniform_location, transpose, v),
1307 | }
1308 | }
1309 |
1310 | unsafe fn unmap_buffer(&self, _target: u32) {
1311 | panic!("Unmap buffer is not supported");
1312 | }
1313 |
1314 | unsafe fn cull_face(&self, value: u32) {
1315 | match self.raw {
1316 | RawRenderingContext::WebGl1(ref gl) => gl.cull_face(value as u32),
1317 | RawRenderingContext::WebGl2(ref gl) => gl.cull_face(value as u32),
1318 | }
1319 | }
1320 |
1321 | unsafe fn color_mask(&self, red: bool, green: bool, blue: bool, alpha: bool) {
1322 | match self.raw {
1323 | RawRenderingContext::WebGl1(ref gl) => gl.color_mask(red, green, blue, alpha),
1324 | RawRenderingContext::WebGl2(ref gl) => gl.color_mask(red, green, blue, alpha),
1325 | }
1326 | }
1327 |
1328 | unsafe fn color_mask_draw_buffer(
1329 | &self,
1330 | _draw_buffer: u32,
1331 | _red: bool,
1332 | _green: bool,
1333 | _blue: bool,
1334 | _alpha: bool,
1335 | ) {
1336 | panic!("Draw buffer color masks are not supported");
1337 | }
1338 |
1339 | unsafe fn depth_mask(&self, value: bool) {
1340 | match self.raw {
1341 | RawRenderingContext::WebGl1(ref gl) => gl.depth_mask(value),
1342 | RawRenderingContext::WebGl2(ref gl) => gl.depth_mask(value),
1343 | }
1344 | }
1345 |
1346 | unsafe fn blend_color(&self, red: f32, green: f32, blue: f32, alpha: f32) {
1347 | match self.raw {
1348 | RawRenderingContext::WebGl1(ref gl) => gl.blend_color(red, green, blue, alpha),
1349 | RawRenderingContext::WebGl2(ref gl) => gl.blend_color(red, green, blue, alpha),
1350 | }
1351 | }
1352 |
1353 | unsafe fn line_width(&self, width: f32) {
1354 | match self.raw {
1355 | RawRenderingContext::WebGl1(ref gl) => gl.line_width(width),
1356 | RawRenderingContext::WebGl2(ref gl) => gl.line_width(width),
1357 | }
1358 | }
1359 |
1360 | unsafe fn map_buffer_range(
1361 | &self,
1362 | _target: u32,
1363 | _offset: i32,
1364 | _length: i32,
1365 | _access: u32,
1366 | ) -> *mut u8 {
1367 | panic!("Map buffer range is not supported")
1368 | }
1369 |
1370 | unsafe fn polygon_offset(&self, factor: f32, units: f32) {
1371 | match self.raw {
1372 | RawRenderingContext::WebGl1(ref gl) => gl.polygon_offset(factor, units),
1373 | RawRenderingContext::WebGl2(ref gl) => gl.polygon_offset(factor, units),
1374 | }
1375 | }
1376 |
1377 | unsafe fn polygon_mode(&self, _face: u32, _mode: u32) {
1378 | panic!("Polygon mode is not supported");
1379 | }
1380 |
1381 | unsafe fn finish(&self) {
1382 | match self.raw {
1383 | RawRenderingContext::WebGl1(ref gl) => gl.finish(),
1384 | RawRenderingContext::WebGl2(ref gl) => gl.finish(),
1385 | }
1386 | }
1387 |
1388 | unsafe fn bind_texture(&self, target: u32, texture: Option) {
1389 | let textures = self.textures.borrow();
1390 | let raw_texture = texture.map(|t| textures.1.get_unchecked(t));
1391 | match self.raw {
1392 | RawRenderingContext::WebGl1(ref gl) => gl.bind_texture(target, raw_texture),
1393 | RawRenderingContext::WebGl2(ref gl) => gl.bind_texture(target, raw_texture),
1394 | }
1395 | }
1396 |
1397 | unsafe fn bind_sampler(&self, unit: u32, sampler: Option) {
1398 | let samplers = self.samplers.borrow();
1399 | let raw_sampler = sampler.map(|s| samplers.1.get_unchecked(s));
1400 | match self.raw {
1401 | RawRenderingContext::WebGl1(ref _gl) => panic!("Bind sampler is not supported"),
1402 | RawRenderingContext::WebGl2(ref gl) => gl.bind_sampler(unit, raw_sampler),
1403 | }
1404 | }
1405 |
1406 | unsafe fn active_texture(&self, unit: u32) {
1407 | match self.raw {
1408 | RawRenderingContext::WebGl1(ref gl) => gl.active_texture(unit),
1409 | RawRenderingContext::WebGl2(ref gl) => gl.active_texture(unit),
1410 | }
1411 | }
1412 |
1413 | unsafe fn fence_sync(&self, condition: u32, flags: u32) -> Result {
1414 | let raw_fence = match self.raw {
1415 | RawRenderingContext::WebGl1(ref _gl) => panic!("Fences are not supported"), // TODO: Extension
1416 | RawRenderingContext::WebGl2(ref gl) => gl.fence_sync(condition as u32, flags),
1417 | };
1418 | match raw_fence {
1419 | Some(f) => {
1420 | let key = self.fences.borrow_mut().0.insert(());
1421 | self.fences.borrow_mut().1.insert(key, f);
1422 | Ok(key)
1423 | }
1424 | None => Err(String::from("Unable to create fence object")),
1425 | }
1426 | }
1427 |
1428 | unsafe fn tex_parameter_f32(&self, target: u32, parameter: u32, value: f32) {
1429 | match self.raw {
1430 | RawRenderingContext::WebGl1(ref gl) => gl.tex_parameterf(target, parameter, value),
1431 | RawRenderingContext::WebGl2(ref gl) => gl.tex_parameterf(target, parameter, value),
1432 | }
1433 | }
1434 |
1435 | unsafe fn tex_parameter_i32(&self, target: u32, parameter: u32, value: i32) {
1436 | match self.raw {
1437 | RawRenderingContext::WebGl1(ref gl) => gl.tex_parameteri(target, parameter, value),
1438 | RawRenderingContext::WebGl2(ref gl) => gl.tex_parameteri(target, parameter, value),
1439 | }
1440 | }
1441 |
1442 | unsafe fn tex_parameter_f32_slice(&self, _target: u32, _parameter: u32, _values: &[f32]) {
1443 | // Blocked by https://github.com/rustwasm/wasm-bindgen/issues/1038
1444 | panic!("Texture parameters for `&[f32]` are not supported yet");
1445 | }
1446 |
1447 | unsafe fn tex_parameter_i32_slice(&self, _target: u32, _parameter: u32, _values: &[i32]) {
1448 | panic!("Texture parameters for `&[i32]` are not supported yet");
1449 | }
1450 |
1451 | unsafe fn tex_sub_image_2d_u8_slice(
1452 | &self,
1453 | target: u32,
1454 | level: i32,
1455 | x_offset: i32,
1456 | y_offset: i32,
1457 | width: i32,
1458 | height: i32,
1459 | format: u32,
1460 | ty: u32,
1461 | pixels: Option<&[u8]>,
1462 | ) {
1463 | match self.raw {
1464 | RawRenderingContext::WebGl1(ref gl) => {
1465 | gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
1466 | target, level, x_offset, y_offset, width, height, format, ty, pixels,
1467 | )
1468 | .unwrap(); // TODO: Handle return value?
1469 | }
1470 | RawRenderingContext::WebGl2(ref gl) => {
1471 | gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_opt_u8_array(
1472 | target, level, x_offset, y_offset, width, height, format, ty, pixels,
1473 | )
1474 | .unwrap(); // TODO: Handle return value?
1475 | }
1476 | }
1477 | }
1478 |
1479 | unsafe fn tex_sub_image_2d_pixel_buffer_offset(
1480 | &self,
1481 | target: u32,
1482 | level: i32,
1483 | x_offset: i32,
1484 | y_offset: i32,
1485 | width: i32,
1486 | height: i32,
1487 | format: u32,
1488 | ty: u32,
1489 | pixel_buffer_offset: i32,
1490 | ) {
1491 | match self.raw {
1492 | RawRenderingContext::WebGl1(ref _gl) => {
1493 | panic!("Sub image 2D pixel buffer offset is not supported")
1494 | }
1495 | RawRenderingContext::WebGl2(ref gl) => {
1496 | gl.tex_sub_image_2d_with_i32_and_i32_and_u32_and_type_and_i32(
1497 | target,
1498 | level,
1499 | x_offset,
1500 | y_offset,
1501 | width,
1502 | height,
1503 | format,
1504 | ty,
1505 | pixel_buffer_offset,
1506 | )
1507 | .unwrap(); // TODO: Handle return value?
1508 | }
1509 | }
1510 | }
1511 |
1512 | unsafe fn depth_func(&self, func: u32) {
1513 | match self.raw {
1514 | RawRenderingContext::WebGl1(ref gl) => gl.depth_func(func as u32),
1515 | RawRenderingContext::WebGl2(ref gl) => gl.depth_func(func as u32),
1516 | }
1517 | }
1518 |
1519 | unsafe fn depth_range_f32(&self, near: f32, far: f32) {
1520 | match self.raw {
1521 | RawRenderingContext::WebGl1(ref gl) => gl.depth_range(near, far),
1522 | RawRenderingContext::WebGl2(ref gl) => gl.depth_range(near, far),
1523 | }
1524 | }
1525 |
1526 | unsafe fn depth_range_f64(&self, _near: f64, _far: f64) {
1527 | panic!("Depth range with 64-bit float values is not supported");
1528 | }
1529 |
1530 | unsafe fn depth_range_f64_slice(&self, _first: u32, _count: i32, _values: &[[f64; 2]]) {
1531 | panic!("Depth range with 64-bit float slices is not supported");
1532 | }
1533 |
1534 | unsafe fn scissor(&self, x: i32, y: i32, width: i32, height: i32) {
1535 | match self.raw {
1536 | RawRenderingContext::WebGl1(ref gl) => gl.scissor(x, y, width, height),
1537 | RawRenderingContext::WebGl2(ref gl) => gl.scissor(x, y, width, height),
1538 | }
1539 | }
1540 |
1541 | unsafe fn scissor_slice(&self, _first: u32, _count: i32, _scissors: &[[i32; 4]]) {
1542 | panic!("Scissor slice is not supported");
1543 | }
1544 |
1545 | unsafe fn vertex_attrib_divisor(&self, index: u32, divisor: u32) {
1546 | match self.raw {
1547 | RawRenderingContext::WebGl1(ref _gl) => {
1548 | panic!("Vertex attrib divisor is not supported"); // TODO: Extension
1549 | }
1550 | RawRenderingContext::WebGl2(ref gl) => gl.vertex_attrib_divisor(index, divisor),
1551 | }
1552 | }
1553 |
1554 | unsafe fn vertex_attrib_pointer_f32(
1555 | &self,
1556 | index: u32,
1557 | size: i32,
1558 | data_type: u32,
1559 | normalized: bool,
1560 | stride: i32,
1561 | offset: i32,
1562 | ) {
1563 | match self.raw {
1564 | RawRenderingContext::WebGl1(ref gl) => gl
1565 | .vertex_attrib_pointer_with_i32(index, size, data_type, normalized, stride, offset),
1566 | RawRenderingContext::WebGl2(ref gl) => gl
1567 | .vertex_attrib_pointer_with_i32(index, size, data_type, normalized, stride, offset),
1568 | }
1569 | }
1570 |
1571 | unsafe fn vertex_attrib_pointer_i32(
1572 | &self,
1573 | index: u32,
1574 | size: i32,
1575 | data_type: u32,
1576 | stride: i32,
1577 | offset: i32,
1578 | ) {
1579 | match self.raw {
1580 | RawRenderingContext::WebGl1(ref _gl) => {
1581 | panic!("Integer vertex attrib pointer is not supported")
1582 | }
1583 | RawRenderingContext::WebGl2(ref gl) => {
1584 | gl.vertex_attrib_i_pointer_with_i32(index, size, data_type, stride, offset)
1585 | }
1586 | }
1587 | }
1588 |
1589 | unsafe fn vertex_attrib_pointer_f64(
1590 | &self,
1591 | _index: u32,
1592 | _size: i32,
1593 | _data_type: u32,
1594 | _stride: i32,
1595 | _offset: i32,
1596 | ) {
1597 | panic!("64-bit float precision is not supported in WebGL");
1598 | }
1599 |
1600 | unsafe fn viewport(&self, x: i32, y: i32, width: i32, height: i32) {
1601 | match self.raw {
1602 | RawRenderingContext::WebGl1(ref gl) => gl.viewport(x, y, width, height),
1603 | RawRenderingContext::WebGl2(ref gl) => gl.viewport(x, y, width, height),
1604 | }
1605 | }
1606 |
1607 | unsafe fn viewport_f32_slice(&self, _first: u32, _count: i32, _values: &[[f32; 4]]) {
1608 | panic!("Viewport `f32` slice is not supported");
1609 | }
1610 |
1611 | unsafe fn blend_func(&self, src: u32, dst: u32) {
1612 | match self.raw {
1613 | RawRenderingContext::WebGl1(ref gl) => gl.blend_func(src as u32, dst as u32),
1614 | RawRenderingContext::WebGl2(ref gl) => gl.blend_func(src as u32, dst as u32),
1615 | }
1616 | }
1617 |
1618 | unsafe fn blend_func_draw_buffer(&self, _draw_buffer: u32, _src: u32, _dst: u32) {
1619 | panic!("Draw buffer blend func is not supported");
1620 | }
1621 |
1622 | unsafe fn blend_func_separate(
1623 | &self,
1624 | src_rgb: u32,
1625 | dst_rgb: u32,
1626 | src_alpha: u32,
1627 | dst_alpha: u32,
1628 | ) {
1629 | match self.raw {
1630 | RawRenderingContext::WebGl1(ref gl) => gl.blend_func_separate(
1631 | src_rgb as u32,
1632 | dst_rgb as u32,
1633 | src_alpha as u32,
1634 | dst_alpha as u32,
1635 | ),
1636 | RawRenderingContext::WebGl2(ref gl) => gl.blend_func_separate(
1637 | src_rgb as u32,
1638 | dst_rgb as u32,
1639 | src_alpha as u32,
1640 | dst_alpha as u32,
1641 | ),
1642 | }
1643 | }
1644 |
1645 | unsafe fn blend_func_separate_draw_buffer(
1646 | &self,
1647 | _draw_buffer: u32,
1648 | _src_rgb: u32,
1649 | _dst_rgb: u32,
1650 | _src_alpha: u32,
1651 | _dst_alpha: u32,
1652 | ) {
1653 | panic!("Draw buffer blend func separate is not supported");
1654 | }
1655 |
1656 | unsafe fn blend_equation(&self, mode: u32) {
1657 | match self.raw {
1658 | RawRenderingContext::WebGl1(ref gl) => gl.blend_equation(mode as u32),
1659 | RawRenderingContext::WebGl2(ref gl) => gl.blend_equation(mode as u32),
1660 | }
1661 | }
1662 |
1663 | unsafe fn blend_equation_draw_buffer(&self, _draw_buffer: u32, _mode: u32) {
1664 | panic!("Draw buffer blend equation is not supported");
1665 | }
1666 |
1667 | unsafe fn blend_equation_separate(&self, mode_rgb: u32, mode_alpha: u32) {
1668 | match self.raw {
1669 | RawRenderingContext::WebGl1(ref gl) => {
1670 | gl.blend_equation_separate(mode_rgb as u32, mode_alpha as u32)
1671 | }
1672 | RawRenderingContext::WebGl2(ref gl) => {
1673 | gl.blend_equation_separate(mode_rgb as u32, mode_alpha as u32)
1674 | }
1675 | }
1676 | }
1677 |
1678 | unsafe fn blend_equation_separate_draw_buffer(
1679 | &self,
1680 | _draw_buffer: u32,
1681 | _mode_rgb: u32,
1682 | _mode_alpha: u32,
1683 | ) {
1684 | panic!("Draw buffer blend equation separate is not supported");
1685 | }
1686 |
1687 | unsafe fn stencil_func(&self, func: u32, reference: i32, mask: u32) {
1688 | match self.raw {
1689 | RawRenderingContext::WebGl1(ref gl) => gl.stencil_func(func as u32, reference, mask),
1690 | RawRenderingContext::WebGl2(ref gl) => gl.stencil_func(func as u32, reference, mask),
1691 | }
1692 | }
1693 |
1694 | unsafe fn stencil_func_separate(&self, face: u32, func: u32, reference: i32, mask: u32) {
1695 | match self.raw {
1696 | RawRenderingContext::WebGl1(ref gl) => {
1697 | gl.stencil_func_separate(face as u32, func as u32, reference, mask)
1698 | }
1699 | RawRenderingContext::WebGl2(ref gl) => {
1700 | gl.stencil_func_separate(face as u32, func as u32, reference, mask)
1701 | }
1702 | }
1703 | }
1704 |
1705 | unsafe fn stencil_mask(&self, mask: u32) {
1706 | match self.raw {
1707 | RawRenderingContext::WebGl1(ref gl) => gl.stencil_mask(mask),
1708 | RawRenderingContext::WebGl2(ref gl) => gl.stencil_mask(mask),
1709 | }
1710 | }
1711 |
1712 | unsafe fn stencil_mask_separate(&self, face: u32, mask: u32) {
1713 | match self.raw {
1714 | RawRenderingContext::WebGl1(ref gl) => gl.stencil_mask_separate(face as u32, mask),
1715 | RawRenderingContext::WebGl2(ref gl) => gl.stencil_mask_separate(face as u32, mask),
1716 | }
1717 | }
1718 |
1719 | unsafe fn stencil_op(&self, stencil_fail: u32, depth_fail: u32, pass: u32) {
1720 | match self.raw {
1721 | RawRenderingContext::WebGl1(ref gl) => {
1722 | gl.stencil_op(stencil_fail as u32, depth_fail as u32, pass as u32)
1723 | }
1724 | RawRenderingContext::WebGl2(ref gl) => {
1725 | gl.stencil_op(stencil_fail as u32, depth_fail as u32, pass as u32)
1726 | }
1727 | }
1728 | }
1729 |
1730 | unsafe fn stencil_op_separate(&self, face: u32, stencil_fail: u32, depth_fail: u32, pass: u32) {
1731 | match self.raw {
1732 | RawRenderingContext::WebGl1(ref gl) => gl.stencil_op_separate(
1733 | face as u32,
1734 | stencil_fail as u32,
1735 | depth_fail as u32,
1736 | pass as u32,
1737 | ),
1738 | RawRenderingContext::WebGl2(ref gl) => gl.stencil_op_separate(
1739 | face as u32,
1740 | stencil_fail as u32,
1741 | depth_fail as u32,
1742 | pass as u32,
1743 | ),
1744 | }
1745 | }
1746 | }
1747 |
1748 | pub struct RenderLoop;
1749 |
1750 | impl RenderLoop {
1751 | pub fn from_request_animation_frame() -> Self {
1752 | RenderLoop
1753 | }
1754 | }
1755 |
1756 | impl super::RenderLoop for RenderLoop {
1757 | type Window = ();
1758 |
1759 | fn run(&self, mut callback: F) {
1760 | fn request_animation_frame(f: &Closure) {
1761 | use wasm_bindgen::JsCast;
1762 | web_sys::window()
1763 | .unwrap()
1764 | .request_animation_frame(f.as_ref().unchecked_ref())
1765 | .unwrap();
1766 | }
1767 |
1768 | let mut running = true;
1769 | let f = std::rc::Rc::new(std::cell::RefCell::new(None));
1770 | let g = f.clone();
1771 | *g.borrow_mut() = Some(Closure::wrap(Box::new(move || {
1772 | callback(&mut running);
1773 | if !running {
1774 | let _ = f.borrow_mut().take();
1775 | return;
1776 | }
1777 | request_animation_frame(f.borrow().as_ref().unwrap());
1778 | }) as Box));
1779 |
1780 | request_animation_frame(g.borrow().as_ref().unwrap());
1781 | }
1782 | }
1783 |
--------------------------------------------------------------------------------