├── rustfmt.toml ├── .gitignore ├── README.md ├── COPYING ├── Cargo.toml ├── src ├── lib.rs ├── gl.rs ├── gl_fns.rs └── gles_fns.rs ├── .github └── workflows │ └── main.yml ├── LICENSE-MIT └── LICENSE-APACHE /rustfmt.toml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | servo-gl 2 | ======== 3 | 4 | [Documentation](https://docs.rs/gleam) 5 | 6 | OpenGL bindings for Servo. 7 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 or the MIT license 3 | , at your 4 | option. All files in the project carrying such notice may not be 5 | copied, modified, or distributed except according to those terms. 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gleam" 3 | version = "0.15.1" 4 | authors = ["The Servo Project Developers"] 5 | description = "Generated OpenGL bindings and wrapper for Servo." 6 | documentation = "https://docs.rs/gleam" 7 | repository = "https://github.com/servo/gleam" 8 | license = "MIT OR Apache-2.0" 9 | build = "build.rs" 10 | 11 | [build-dependencies] 12 | gl_generator = "0.14" 13 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | #![crate_name = "gleam"] 11 | #![crate_type = "lib"] 12 | 13 | pub mod gl; 14 | 15 | mod ffi { 16 | include!(concat!(env!("OUT_DIR"), "/gl_and_gles_bindings.rs")); 17 | } 18 | 19 | mod ffi_gl { 20 | include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs")); 21 | } 22 | 23 | mod ffi_gles { 24 | include!(concat!(env!("OUT_DIR"), "/gles_bindings.rs")); 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | workflow_dispatch: 8 | merge_group: 9 | types: [checks_requested] 10 | 11 | jobs: 12 | linux-ci: 13 | name: Linux 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | toolchain: ["stable", "beta", "nightly"] 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Install nightly toolchain 22 | uses: actions-rs/toolchain@v1 23 | with: 24 | profile: minimal 25 | toolchain: ${{ matrix.toolchain }} 26 | override: true 27 | 28 | - name: Cargo test 29 | run: cargo test 30 | 31 | build_result: 32 | name: Result 33 | runs-on: ubuntu-latest 34 | needs: 35 | - "linux-ci" 36 | 37 | steps: 38 | - name: Mark the job as successful 39 | run: exit 0 40 | if: success() 41 | - name: Mark the job as unsuccessful 42 | run: exit 1 43 | if: "!success()" 44 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Mozilla Foundation 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /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. 202 | -------------------------------------------------------------------------------- /src/gl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use ffi; 11 | use std::ffi::{CStr, CString}; 12 | use std::mem; 13 | use std::mem::size_of; 14 | use std::os::raw::{c_char, c_int, c_void}; 15 | use std::ptr; 16 | use std::rc::Rc; 17 | use std::str; 18 | use std::time::{Duration, Instant}; 19 | 20 | pub use ffi::types::*; 21 | pub use ffi::*; 22 | 23 | pub use ffi_gl::Gl as GlFfi; 24 | pub use ffi_gles::Gles2 as GlesFfi; 25 | 26 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] 27 | pub enum GlType { 28 | Gl, 29 | Gles, 30 | } 31 | 32 | impl Default for GlType { 33 | #[cfg(any(target_os = "android", target_os = "ios"))] 34 | fn default() -> GlType { 35 | GlType::Gles 36 | } 37 | #[cfg(not(any(target_os = "android", target_os = "ios")))] 38 | fn default() -> GlType { 39 | GlType::Gl 40 | } 41 | } 42 | 43 | fn bpp(format: GLenum, pixel_type: GLenum) -> GLsizei { 44 | let colors = match format { 45 | ffi::RED => 1, 46 | ffi::RGB => 3, 47 | ffi::BGR => 3, 48 | 49 | ffi::RGBA => 4, 50 | ffi::BGRA => 4, 51 | 52 | ffi::ALPHA => 1, 53 | ffi::R16 => 1, 54 | ffi::LUMINANCE => 1, 55 | ffi::DEPTH_COMPONENT => 1, 56 | _ => panic!("unsupported format for read_pixels: {:?}", format), 57 | }; 58 | let depth = match pixel_type { 59 | ffi::UNSIGNED_BYTE => 1, 60 | ffi::UNSIGNED_SHORT => 2, 61 | ffi::SHORT => 2, 62 | ffi::FLOAT => 4, 63 | ffi::UNSIGNED_INT_8_8_8_8_REV => return 4, 64 | _ => panic!("unsupported pixel_type for read_pixels: {:?}", pixel_type), 65 | }; 66 | colors * depth 67 | } 68 | 69 | fn calculate_length(width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> usize { 70 | (width * height * bpp(format, pixel_type)) as usize 71 | } 72 | 73 | pub struct DebugMessage { 74 | pub message: String, 75 | pub source: GLenum, 76 | pub ty: GLenum, 77 | pub id: GLenum, 78 | pub severity: GLenum, 79 | } 80 | 81 | macro_rules! declare_gl_apis { 82 | // garbo is a hack to handle unsafe methods. 83 | ($($(unsafe $([$garbo:expr])*)* fn $name:ident(&self $(, $arg:ident: $t:ty)* $(,)*) $(-> $retty:ty)* ;)+) => { 84 | pub trait Gl { 85 | $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* ;)+ 86 | } 87 | 88 | impl Gl for ErrorCheckingGl { 89 | $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* { 90 | let rv = self.gl.$name($($arg,)*); 91 | assert_eq!(self.gl.get_error(), 0); 92 | rv 93 | })+ 94 | } 95 | 96 | impl Gl for ErrorReactingGl { 97 | $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* { 98 | let rv = self.gl.$name($($arg,)*); 99 | let error = self.gl.get_error(); 100 | if error != 0 { 101 | (self.callback)(&*self.gl, stringify!($name), error); 102 | } 103 | rv 104 | })+ 105 | } 106 | 107 | impl Gl for ProfilingGl { 108 | $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* { 109 | let start = Instant::now(); 110 | let rv = self.gl.$name($($arg,)*); 111 | let duration = Instant::now() - start; 112 | if duration > self.threshold { 113 | (self.callback)(stringify!($name), duration); 114 | } 115 | rv 116 | })+ 117 | } 118 | } 119 | } 120 | 121 | declare_gl_apis! { 122 | fn get_type(&self) -> GlType; 123 | fn buffer_data_untyped( 124 | &self, 125 | target: GLenum, 126 | size: GLsizeiptr, 127 | data: *const GLvoid, 128 | usage: GLenum, 129 | ); 130 | fn buffer_sub_data_untyped( 131 | &self, 132 | target: GLenum, 133 | offset: isize, 134 | size: GLsizeiptr, 135 | data: *const GLvoid, 136 | ); 137 | fn map_buffer(&self, target: GLenum, access: GLbitfield) -> *mut c_void; 138 | fn map_buffer_range( 139 | &self, 140 | target: GLenum, 141 | offset: GLintptr, 142 | length: GLsizeiptr, 143 | access: GLbitfield, 144 | ) -> *mut c_void; 145 | fn unmap_buffer(&self, target: GLenum) -> GLboolean; 146 | fn tex_buffer(&self, target: GLenum, internal_format: GLenum, buffer: GLuint); 147 | fn shader_source(&self, shader: GLuint, strings: &[&[u8]]); 148 | fn read_buffer(&self, mode: GLenum); 149 | fn read_pixels_into_buffer( 150 | &self, 151 | x: GLint, 152 | y: GLint, 153 | width: GLsizei, 154 | height: GLsizei, 155 | format: GLenum, 156 | pixel_type: GLenum, 157 | dst_buffer: &mut [u8], 158 | ); 159 | fn read_pixels( 160 | &self, 161 | x: GLint, 162 | y: GLint, 163 | width: GLsizei, 164 | height: GLsizei, 165 | format: GLenum, 166 | pixel_type: GLenum, 167 | ) -> Vec; 168 | unsafe fn read_pixels_into_pbo( 169 | &self, 170 | x: GLint, 171 | y: GLint, 172 | width: GLsizei, 173 | height: GLsizei, 174 | format: GLenum, 175 | pixel_type: GLenum, 176 | ); 177 | fn sample_coverage(&self, value: GLclampf, invert: bool); 178 | fn polygon_offset(&self, factor: GLfloat, units: GLfloat); 179 | fn pixel_store_i(&self, name: GLenum, param: GLint); 180 | fn gen_buffers(&self, n: GLsizei) -> Vec; 181 | fn gen_renderbuffers(&self, n: GLsizei) -> Vec; 182 | fn gen_framebuffers(&self, n: GLsizei) -> Vec; 183 | fn gen_textures(&self, n: GLsizei) -> Vec; 184 | fn gen_vertex_arrays(&self, n: GLsizei) -> Vec; 185 | fn gen_vertex_arrays_apple(&self, n: GLsizei) -> Vec; 186 | fn gen_queries(&self, n: GLsizei) -> Vec; 187 | fn begin_query(&self, target: GLenum, id: GLuint); 188 | fn end_query(&self, target: GLenum); 189 | fn query_counter(&self, id: GLuint, target: GLenum); 190 | fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32; 191 | fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32; 192 | fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64; 193 | fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64; 194 | fn delete_queries(&self, queries: &[GLuint]); 195 | fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]); 196 | fn delete_vertex_arrays_apple(&self, vertex_arrays: &[GLuint]); 197 | fn delete_buffers(&self, buffers: &[GLuint]); 198 | fn delete_renderbuffers(&self, renderbuffers: &[GLuint]); 199 | fn delete_framebuffers(&self, framebuffers: &[GLuint]); 200 | fn delete_textures(&self, textures: &[GLuint]); 201 | fn framebuffer_renderbuffer( 202 | &self, 203 | target: GLenum, 204 | attachment: GLenum, 205 | renderbuffertarget: GLenum, 206 | renderbuffer: GLuint, 207 | ); 208 | fn renderbuffer_storage( 209 | &self, 210 | target: GLenum, 211 | internalformat: GLenum, 212 | width: GLsizei, 213 | height: GLsizei, 214 | ); 215 | fn depth_func(&self, func: GLenum); 216 | fn active_texture(&self, texture: GLenum); 217 | fn attach_shader(&self, program: GLuint, shader: GLuint); 218 | fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str); 219 | unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]); 220 | unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]); 221 | fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint; 222 | fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec; 223 | fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint); 224 | fn bind_buffer_range( 225 | &self, 226 | target: GLenum, 227 | index: GLuint, 228 | buffer: GLuint, 229 | offset: GLintptr, 230 | size: GLsizeiptr, 231 | ); 232 | fn uniform_block_binding( 233 | &self, 234 | program: GLuint, 235 | uniform_block_index: GLuint, 236 | uniform_block_binding: GLuint, 237 | ); 238 | fn bind_buffer(&self, target: GLenum, buffer: GLuint); 239 | fn bind_vertex_array(&self, vao: GLuint); 240 | fn bind_vertex_array_apple(&self, vao: GLuint); 241 | fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint); 242 | fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint); 243 | fn bind_texture(&self, target: GLenum, texture: GLuint); 244 | fn bind_vertex_buffer(&self, binding_index: GLuint, buffer: GLuint, offset: GLintptr, stride: GLint); 245 | fn draw_buffers(&self, bufs: &[GLenum]); 246 | fn tex_image_2d( 247 | &self, 248 | target: GLenum, 249 | level: GLint, 250 | internal_format: GLint, 251 | width: GLsizei, 252 | height: GLsizei, 253 | border: GLint, 254 | format: GLenum, 255 | ty: GLenum, 256 | opt_data: Option<&[u8]>, 257 | ); 258 | fn compressed_tex_image_2d( 259 | &self, 260 | target: GLenum, 261 | level: GLint, 262 | internal_format: GLenum, 263 | width: GLsizei, 264 | height: GLsizei, 265 | border: GLint, 266 | data: &[u8], 267 | ); 268 | fn compressed_tex_sub_image_2d( 269 | &self, 270 | target: GLenum, 271 | level: GLint, 272 | xoffset: GLint, 273 | yoffset: GLint, 274 | width: GLsizei, 275 | height: GLsizei, 276 | format: GLenum, 277 | data: &[u8], 278 | ); 279 | fn tex_image_3d( 280 | &self, 281 | target: GLenum, 282 | level: GLint, 283 | internal_format: GLint, 284 | width: GLsizei, 285 | height: GLsizei, 286 | depth: GLsizei, 287 | border: GLint, 288 | format: GLenum, 289 | ty: GLenum, 290 | opt_data: Option<&[u8]>, 291 | ); 292 | fn copy_tex_image_2d( 293 | &self, 294 | target: GLenum, 295 | level: GLint, 296 | internal_format: GLenum, 297 | x: GLint, 298 | y: GLint, 299 | width: GLsizei, 300 | height: GLsizei, 301 | border: GLint, 302 | ); 303 | fn copy_tex_sub_image_2d( 304 | &self, 305 | target: GLenum, 306 | level: GLint, 307 | xoffset: GLint, 308 | yoffset: GLint, 309 | x: GLint, 310 | y: GLint, 311 | width: GLsizei, 312 | height: GLsizei, 313 | ); 314 | fn copy_tex_sub_image_3d( 315 | &self, 316 | target: GLenum, 317 | level: GLint, 318 | xoffset: GLint, 319 | yoffset: GLint, 320 | zoffset: GLint, 321 | x: GLint, 322 | y: GLint, 323 | width: GLsizei, 324 | height: GLsizei, 325 | ); 326 | fn tex_sub_image_2d( 327 | &self, 328 | target: GLenum, 329 | level: GLint, 330 | xoffset: GLint, 331 | yoffset: GLint, 332 | width: GLsizei, 333 | height: GLsizei, 334 | format: GLenum, 335 | ty: GLenum, 336 | data: &[u8], 337 | ); 338 | fn tex_sub_image_2d_pbo( 339 | &self, 340 | target: GLenum, 341 | level: GLint, 342 | xoffset: GLint, 343 | yoffset: GLint, 344 | width: GLsizei, 345 | height: GLsizei, 346 | format: GLenum, 347 | ty: GLenum, 348 | offset: usize, 349 | ); 350 | fn tex_sub_image_3d( 351 | &self, 352 | target: GLenum, 353 | level: GLint, 354 | xoffset: GLint, 355 | yoffset: GLint, 356 | zoffset: GLint, 357 | width: GLsizei, 358 | height: GLsizei, 359 | depth: GLsizei, 360 | format: GLenum, 361 | ty: GLenum, 362 | data: &[u8], 363 | ); 364 | fn tex_sub_image_3d_pbo( 365 | &self, 366 | target: GLenum, 367 | level: GLint, 368 | xoffset: GLint, 369 | yoffset: GLint, 370 | zoffset: GLint, 371 | width: GLsizei, 372 | height: GLsizei, 373 | depth: GLsizei, 374 | format: GLenum, 375 | ty: GLenum, 376 | offset: usize, 377 | ); 378 | fn tex_storage_2d( 379 | &self, 380 | target: GLenum, 381 | levels: GLint, 382 | internal_format: GLenum, 383 | width: GLsizei, 384 | height: GLsizei, 385 | ); 386 | fn tex_storage_3d( 387 | &self, 388 | target: GLenum, 389 | levels: GLint, 390 | internal_format: GLenum, 391 | width: GLsizei, 392 | height: GLsizei, 393 | depth: GLsizei, 394 | ); 395 | fn get_tex_image_into_buffer( 396 | &self, 397 | target: GLenum, 398 | level: GLint, 399 | format: GLenum, 400 | ty: GLenum, 401 | output: &mut [u8], 402 | ); 403 | unsafe fn copy_image_sub_data( 404 | &self, 405 | src_name: GLuint, 406 | src_target: GLenum, 407 | src_level: GLint, 408 | src_x: GLint, 409 | src_y: GLint, 410 | src_z: GLint, 411 | dst_name: GLuint, 412 | dst_target: GLenum, 413 | dst_level: GLint, 414 | dst_x: GLint, 415 | dst_y: GLint, 416 | dst_z: GLint, 417 | src_width: GLsizei, 418 | src_height: GLsizei, 419 | src_depth: GLsizei, 420 | ); 421 | 422 | fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]); 423 | fn invalidate_sub_framebuffer( 424 | &self, 425 | target: GLenum, 426 | attachments: &[GLenum], 427 | xoffset: GLint, 428 | yoffset: GLint, 429 | width: GLsizei, 430 | height: GLsizei, 431 | ); 432 | 433 | unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]); 434 | unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]); 435 | unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]); 436 | unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]); 437 | unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]); 438 | unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]); 439 | 440 | fn get_framebuffer_attachment_parameter_iv( 441 | &self, 442 | target: GLenum, 443 | attachment: GLenum, 444 | pname: GLenum, 445 | ) -> GLint; 446 | fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint; 447 | fn get_tex_parameter_iv(&self, target: GLenum, name: GLenum) -> GLint; 448 | fn get_tex_parameter_fv(&self, target: GLenum, name: GLenum) -> GLfloat; 449 | fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint); 450 | fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat); 451 | fn framebuffer_texture_2d( 452 | &self, 453 | target: GLenum, 454 | attachment: GLenum, 455 | textarget: GLenum, 456 | texture: GLuint, 457 | level: GLint, 458 | ); 459 | fn framebuffer_texture_layer( 460 | &self, 461 | target: GLenum, 462 | attachment: GLenum, 463 | texture: GLuint, 464 | level: GLint, 465 | layer: GLint, 466 | ); 467 | fn blit_framebuffer( 468 | &self, 469 | src_x0: GLint, 470 | src_y0: GLint, 471 | src_x1: GLint, 472 | src_y1: GLint, 473 | dst_x0: GLint, 474 | dst_y0: GLint, 475 | dst_x1: GLint, 476 | dst_y1: GLint, 477 | mask: GLbitfield, 478 | filter: GLenum, 479 | ); 480 | fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat); 481 | fn vertex_attrib_binding(&self, attrib_index: GLuint, binding_index: GLuint); 482 | fn vertex_attrib_pointer_f32( 483 | &self, 484 | index: GLuint, 485 | size: GLint, 486 | normalized: bool, 487 | stride: GLsizei, 488 | offset: GLuint, 489 | ); 490 | fn vertex_attrib_pointer( 491 | &self, 492 | index: GLuint, 493 | size: GLint, 494 | type_: GLenum, 495 | normalized: bool, 496 | stride: GLsizei, 497 | offset: GLuint, 498 | ); 499 | fn vertex_attrib_i_pointer( 500 | &self, 501 | index: GLuint, 502 | size: GLint, 503 | type_: GLenum, 504 | stride: GLsizei, 505 | offset: GLuint, 506 | ); 507 | fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint); 508 | fn vertex_attrib_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, normalized: bool, relative_offset: GLuint); 509 | fn vertex_attrib_i_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, relative_offset: GLuint); 510 | fn vertex_binding_divisor(&self, binding_index: GLuint, divisor: GLuint); 511 | fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei); 512 | fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei); 513 | fn line_width(&self, width: GLfloat); 514 | fn use_program(&self, program: GLuint); 515 | fn validate_program(&self, program: GLuint); 516 | fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei); 517 | fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei); 518 | fn draw_elements( 519 | &self, 520 | mode: GLenum, 521 | count: GLsizei, 522 | element_type: GLenum, 523 | indices_offset: GLuint, 524 | ); 525 | fn draw_elements_instanced( 526 | &self, 527 | mode: GLenum, 528 | count: GLsizei, 529 | element_type: GLenum, 530 | indices_offset: GLuint, 531 | primcount: GLsizei, 532 | ); 533 | fn blend_color(&self, r: f32, g: f32, b: f32, a: f32); 534 | fn blend_func(&self, sfactor: GLenum, dfactor: GLenum); 535 | fn blend_func_separate( 536 | &self, 537 | src_rgb: GLenum, 538 | dest_rgb: GLenum, 539 | src_alpha: GLenum, 540 | dest_alpha: GLenum, 541 | ); 542 | fn blend_equation(&self, mode: GLenum); 543 | fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum); 544 | fn color_mask(&self, r: bool, g: bool, b: bool, a: bool); 545 | fn cull_face(&self, mode: GLenum); 546 | fn front_face(&self, mode: GLenum); 547 | fn enable(&self, cap: GLenum); 548 | fn disable(&self, cap: GLenum); 549 | fn hint(&self, param_name: GLenum, param_val: GLenum); 550 | fn is_enabled(&self, cap: GLenum) -> GLboolean; 551 | fn is_shader(&self, shader: GLuint) -> GLboolean; 552 | fn is_texture(&self, texture: GLenum) -> GLboolean; 553 | fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean; 554 | fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean; 555 | fn check_frame_buffer_status(&self, target: GLenum) -> GLenum; 556 | fn enable_vertex_attrib_array(&self, index: GLuint); 557 | fn disable_vertex_attrib_array(&self, index: GLuint); 558 | fn uniform_1f(&self, location: GLint, v0: GLfloat); 559 | fn uniform_1fv(&self, location: GLint, values: &[f32]); 560 | fn uniform_1i(&self, location: GLint, v0: GLint); 561 | fn uniform_1iv(&self, location: GLint, values: &[i32]); 562 | fn uniform_1ui(&self, location: GLint, v0: GLuint); 563 | fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat); 564 | fn uniform_2fv(&self, location: GLint, values: &[f32]); 565 | fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint); 566 | fn uniform_2iv(&self, location: GLint, values: &[i32]); 567 | fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint); 568 | fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat); 569 | fn uniform_3fv(&self, location: GLint, values: &[f32]); 570 | fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint); 571 | fn uniform_3iv(&self, location: GLint, values: &[i32]); 572 | fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint); 573 | fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat); 574 | fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint); 575 | fn uniform_4iv(&self, location: GLint, values: &[i32]); 576 | fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint); 577 | fn uniform_4fv(&self, location: GLint, values: &[f32]); 578 | fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]); 579 | fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]); 580 | fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]); 581 | fn depth_mask(&self, flag: bool); 582 | fn depth_range(&self, near: f64, far: f64); 583 | fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String); 584 | fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String); 585 | fn get_active_uniforms_iv( 586 | &self, 587 | program: GLuint, 588 | indices: Vec, 589 | pname: GLenum, 590 | ) -> Vec; 591 | fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint; 592 | fn get_active_uniform_block_iv( 593 | &self, 594 | program: GLuint, 595 | index: GLuint, 596 | pname: GLenum, 597 | ) -> Vec; 598 | fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String; 599 | fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int; 600 | fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int; 601 | fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int; 602 | fn get_program_info_log(&self, program: GLuint) -> String; 603 | unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]); 604 | fn get_program_binary(&self, program: GLuint) -> (Vec, GLenum); 605 | fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]); 606 | fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint); 607 | unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]); 608 | unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]); 609 | fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr; 610 | fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint; 611 | fn get_shader_info_log(&self, shader: GLuint) -> String; 612 | fn get_string(&self, which: GLenum) -> String; 613 | fn get_string_i(&self, which: GLenum, index: GLuint) -> String; 614 | unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]); 615 | fn get_shader_precision_format( 616 | &self, 617 | shader_type: GLuint, 618 | precision_type: GLuint, 619 | ) -> (GLint, GLint, GLint); 620 | fn compile_shader(&self, shader: GLuint); 621 | fn create_program(&self) -> GLuint; 622 | fn delete_program(&self, program: GLuint); 623 | fn create_shader(&self, shader_type: GLenum) -> GLuint; 624 | fn delete_shader(&self, shader: GLuint); 625 | fn detach_shader(&self, program: GLuint, shader: GLuint); 626 | fn link_program(&self, program: GLuint); 627 | fn clear_color(&self, r: f32, g: f32, b: f32, a: f32); 628 | fn clear(&self, buffer_mask: GLbitfield); 629 | fn clear_depth(&self, depth: f64); 630 | fn clear_stencil(&self, s: GLint); 631 | fn flush(&self); 632 | fn finish(&self); 633 | fn get_error(&self) -> GLenum; 634 | fn stencil_mask(&self, mask: GLuint); 635 | fn stencil_mask_separate(&self, face: GLenum, mask: GLuint); 636 | fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint); 637 | fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint); 638 | fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum); 639 | fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum); 640 | fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES); 641 | fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES); 642 | fn generate_mipmap(&self, target: GLenum); 643 | fn insert_event_marker_ext(&self, message: &str); 644 | fn push_group_marker_ext(&self, message: &str); 645 | fn pop_group_marker_ext(&self); 646 | fn debug_message_insert_khr( 647 | &self, 648 | source: GLenum, 649 | type_: GLenum, 650 | id: GLuint, 651 | severity: GLenum, 652 | message: &str, 653 | ); 654 | fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str); 655 | fn pop_debug_group_khr(&self); 656 | fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync; 657 | fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum; 658 | fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64); 659 | fn delete_sync(&self, sync: GLsync); 660 | fn texture_range_apple(&self, target: GLenum, data: &[u8]); 661 | fn gen_fences_apple(&self, n: GLsizei) -> Vec; 662 | fn delete_fences_apple(&self, fences: &[GLuint]); 663 | fn set_fence_apple(&self, fence: GLuint); 664 | fn finish_fence_apple(&self, fence: GLuint); 665 | fn test_fence_apple(&self, fence: GLuint); 666 | fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean; 667 | fn finish_object_apple(&self, object: GLenum, name: GLuint); 668 | // GL_KHR_blend_equation_advanced 669 | fn blend_barrier_khr(&self); 670 | 671 | // GL_ARB_blend_func_extended 672 | fn bind_frag_data_location_indexed( 673 | &self, 674 | program: GLuint, 675 | color_number: GLuint, 676 | index: GLuint, 677 | name: &str, 678 | ); 679 | fn get_frag_data_index(&self, program: GLuint, name: &str) -> GLint; 680 | 681 | // GL_KHR_debug 682 | fn get_debug_messages(&self) -> Vec; 683 | 684 | // GL_ANGLE_provoking_vertex 685 | fn provoking_vertex_angle(&self, mode: GLenum); 686 | 687 | // GL_CHROMIUM_copy_texture 688 | fn copy_texture_chromium( 689 | &self, 690 | source_id: GLuint, 691 | source_level: GLint, 692 | dest_target: GLenum, 693 | dest_id: GLuint, 694 | dest_level: GLint, 695 | internal_format: GLint, 696 | dest_type: GLenum, 697 | unpack_flip_y: GLboolean, 698 | unpack_premultiply_alpha: GLboolean, 699 | unpack_unmultiply_alpha: GLboolean, 700 | ); 701 | fn copy_sub_texture_chromium( 702 | &self, 703 | source_id: GLuint, 704 | source_level: GLint, 705 | dest_target: GLenum, 706 | dest_id: GLuint, 707 | dest_level: GLint, 708 | x_offset: GLint, 709 | y_offset: GLint, 710 | x: GLint, 711 | y: GLint, 712 | width: GLsizei, 713 | height: GLsizei, 714 | unpack_flip_y: GLboolean, 715 | unpack_premultiply_alpha: GLboolean, 716 | unpack_unmultiply_alpha: GLboolean, 717 | ); 718 | 719 | // GL_ANGLE_copy_texture_3d 720 | fn copy_texture_3d_angle( 721 | &self, 722 | source_id: GLuint, 723 | source_level: GLint, 724 | dest_target: GLenum, 725 | dest_id: GLuint, 726 | dest_level: GLint, 727 | internal_format: GLint, 728 | dest_type: GLenum, 729 | unpack_flip_y: GLboolean, 730 | unpack_premultiply_alpha: GLboolean, 731 | unpack_unmultiply_alpha: GLboolean, 732 | ); 733 | 734 | fn copy_sub_texture_3d_angle( 735 | &self, 736 | source_id: GLuint, 737 | source_level: GLint, 738 | dest_target: GLenum, 739 | dest_id: GLuint, 740 | dest_level: GLint, 741 | x_offset: GLint, 742 | y_offset: GLint, 743 | z_offset: GLint, 744 | x: GLint, 745 | y: GLint, 746 | z: GLint, 747 | width: GLsizei, 748 | height: GLsizei, 749 | depth: GLsizei, 750 | unpack_flip_y: GLboolean, 751 | unpack_premultiply_alpha: GLboolean, 752 | unpack_unmultiply_alpha: GLboolean, 753 | ); 754 | 755 | fn buffer_storage( 756 | &self, 757 | target: GLenum, 758 | size: GLsizeiptr, 759 | data: *const GLvoid, 760 | flags: GLbitfield, 761 | ); 762 | 763 | fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr); 764 | 765 | fn start_tiling_qcom(&self, x: GLuint, y: GLuint, width: GLuint, height: GLuint, preserve_mask: GLbitfield); 766 | fn end_tiling_qcom(&self, preserve_mask: GLbitfield); 767 | } 768 | 769 | //#[deprecated(since = "0.6.11", note = "use ErrorReactingGl instead")] 770 | pub struct ErrorCheckingGl { 771 | gl: Rc, 772 | } 773 | 774 | impl ErrorCheckingGl { 775 | pub fn wrap(fns: Rc) -> Rc { 776 | Rc::new(ErrorCheckingGl { gl: fns }) as Rc 777 | } 778 | } 779 | 780 | /// A wrapper around GL context that calls a specified callback on each GL error. 781 | pub struct ErrorReactingGl { 782 | gl: Rc, 783 | callback: F, 784 | } 785 | 786 | impl ErrorReactingGl { 787 | pub fn wrap(fns: Rc, callback: F) -> Rc { 788 | Rc::new(ErrorReactingGl { gl: fns, callback }) as Rc 789 | } 790 | } 791 | 792 | /// A wrapper around GL context that times each call and invokes the callback 793 | /// if the call takes longer than the threshold. 794 | pub struct ProfilingGl { 795 | gl: Rc, 796 | threshold: Duration, 797 | callback: F, 798 | } 799 | 800 | impl ProfilingGl { 801 | pub fn wrap(fns: Rc, threshold: Duration, callback: F) -> Rc { 802 | Rc::new(ProfilingGl { 803 | gl: fns, 804 | threshold, 805 | callback, 806 | }) as Rc 807 | } 808 | } 809 | 810 | #[inline] 811 | pub fn buffer_data(gl_: &dyn Gl, target: GLenum, data: &[T], usage: GLenum) { 812 | gl_.buffer_data_untyped( 813 | target, 814 | (data.len() * size_of::()) as GLsizeiptr, 815 | data.as_ptr() as *const GLvoid, 816 | usage, 817 | ) 818 | } 819 | 820 | #[inline] 821 | pub fn buffer_data_raw(gl_: &dyn Gl, target: GLenum, data: &T, usage: GLenum) { 822 | gl_.buffer_data_untyped( 823 | target, 824 | size_of::() as GLsizeiptr, 825 | data as *const T as *const GLvoid, 826 | usage, 827 | ) 828 | } 829 | 830 | #[inline] 831 | pub fn buffer_sub_data(gl_: &dyn Gl, target: GLenum, offset: isize, data: &[T]) { 832 | gl_.buffer_sub_data_untyped( 833 | target, 834 | offset, 835 | (data.len() * size_of::()) as GLsizeiptr, 836 | data.as_ptr() as *const GLvoid, 837 | ); 838 | } 839 | 840 | include!("gl_fns.rs"); 841 | include!("gles_fns.rs"); 842 | -------------------------------------------------------------------------------- /src/gl_fns.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | pub struct GlFns { 11 | ffi_gl_: GlFfi, 12 | } 13 | 14 | impl GlFns { 15 | pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc 16 | where 17 | F: FnMut(&str) -> *const c_void, 18 | { 19 | let ffi_gl_ = GlFfi::load_with(loadfn); 20 | Rc::new(GlFns { ffi_gl_: ffi_gl_ }) as Rc 21 | } 22 | } 23 | 24 | impl Gl for GlFns { 25 | fn get_type(&self) -> GlType { 26 | GlType::Gl 27 | } 28 | 29 | fn buffer_data_untyped( 30 | &self, 31 | target: GLenum, 32 | size: GLsizeiptr, 33 | data: *const GLvoid, 34 | usage: GLenum, 35 | ) { 36 | unsafe { 37 | self.ffi_gl_.BufferData(target, size, data, usage); 38 | } 39 | } 40 | 41 | fn buffer_sub_data_untyped( 42 | &self, 43 | target: GLenum, 44 | offset: isize, 45 | size: GLsizeiptr, 46 | data: *const GLvoid, 47 | ) { 48 | unsafe { 49 | self.ffi_gl_.BufferSubData(target, offset, size, data); 50 | } 51 | } 52 | 53 | fn map_buffer(&self, 54 | target: GLenum, 55 | access: GLbitfield) -> *mut c_void { 56 | unsafe { 57 | return self.ffi_gl_.MapBuffer(target, access); 58 | } 59 | } 60 | 61 | fn map_buffer_range(&self, 62 | target: GLenum, 63 | offset: GLintptr, 64 | length: GLsizeiptr, 65 | access: GLbitfield) -> *mut c_void { 66 | unsafe { 67 | return self.ffi_gl_.MapBufferRange(target, offset, length, access); 68 | } 69 | } 70 | 71 | fn unmap_buffer(&self, target: GLenum) -> GLboolean { 72 | unsafe { 73 | return self.ffi_gl_.UnmapBuffer(target); 74 | } 75 | } 76 | 77 | fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) { 78 | let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect(); 79 | let lengths: Vec = strings.iter().map(|string| string.len() as GLint).collect(); 80 | unsafe { 81 | self.ffi_gl_.ShaderSource( 82 | shader, 83 | pointers.len() as GLsizei, 84 | pointers.as_ptr() as *const *const GLchar, 85 | lengths.as_ptr(), 86 | ); 87 | } 88 | drop(lengths); 89 | drop(pointers); 90 | } 91 | 92 | fn tex_buffer(&self, target: GLenum, internal_format: GLenum, buffer: GLuint) { 93 | unsafe { 94 | self.ffi_gl_.TexBuffer(target, internal_format, buffer); 95 | } 96 | } 97 | 98 | fn read_buffer(&self, mode: GLenum) { 99 | unsafe { 100 | self.ffi_gl_.ReadBuffer(mode); 101 | } 102 | } 103 | 104 | fn read_pixels_into_buffer( 105 | &self, 106 | x: GLint, 107 | y: GLint, 108 | width: GLsizei, 109 | height: GLsizei, 110 | format: GLenum, 111 | pixel_type: GLenum, 112 | dst_buffer: &mut [u8], 113 | ) { 114 | // Assumes that the user properly allocated the size for dst_buffer. 115 | let mut row_length = 0; 116 | unsafe { 117 | self.ffi_gl_.GetIntegerv(ffi::PACK_ROW_LENGTH, &mut row_length as _); 118 | } 119 | if row_length == 0 { 120 | row_length = width; 121 | } else { 122 | assert!(row_length >= width); 123 | } 124 | assert_eq!(calculate_length(row_length, height, format, pixel_type), dst_buffer.len()); 125 | 126 | unsafe { 127 | // We don't want any alignment padding on pixel rows. 128 | self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1); 129 | self.ffi_gl_.ReadPixels( 130 | x, 131 | y, 132 | width, 133 | height, 134 | format, 135 | pixel_type, 136 | dst_buffer.as_mut_ptr() as *mut c_void, 137 | ); 138 | } 139 | } 140 | 141 | fn read_pixels( 142 | &self, 143 | x: GLint, 144 | y: GLint, 145 | width: GLsizei, 146 | height: GLsizei, 147 | format: GLenum, 148 | pixel_type: GLenum, 149 | ) -> Vec { 150 | let len = calculate_length(width, height, format, pixel_type); 151 | let mut pixels: Vec = Vec::new(); 152 | pixels.reserve(len); 153 | unsafe { 154 | pixels.set_len(len); 155 | } 156 | 157 | self.read_pixels_into_buffer( 158 | x, 159 | y, 160 | width, 161 | height, 162 | format, 163 | pixel_type, 164 | pixels.as_mut_slice(), 165 | ); 166 | 167 | pixels 168 | } 169 | 170 | unsafe fn read_pixels_into_pbo(&self, 171 | x: GLint, 172 | y: GLint, 173 | width: GLsizei, 174 | height: GLsizei, 175 | format: GLenum, 176 | pixel_type: GLenum) { 177 | self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, ptr::null_mut()); 178 | } 179 | 180 | fn sample_coverage(&self, value: GLclampf, invert: bool) { 181 | unsafe { 182 | self.ffi_gl_.SampleCoverage(value, invert as GLboolean); 183 | } 184 | } 185 | 186 | fn polygon_offset(&self, factor: GLfloat, units: GLfloat) { 187 | unsafe { 188 | self.ffi_gl_.PolygonOffset(factor, units); 189 | } 190 | } 191 | 192 | fn pixel_store_i(&self, name: GLenum, param: GLint) { 193 | unsafe { 194 | self.ffi_gl_.PixelStorei(name, param); 195 | } 196 | } 197 | 198 | fn gen_buffers(&self, n: GLsizei) -> Vec { 199 | let mut result = vec![0 as GLuint; n as usize]; 200 | unsafe { 201 | self.ffi_gl_.GenBuffers(n, result.as_mut_ptr()); 202 | } 203 | result 204 | } 205 | 206 | fn gen_renderbuffers(&self, n: GLsizei) -> Vec { 207 | let mut result = vec![0 as GLuint; n as usize]; 208 | unsafe { 209 | self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr()); 210 | } 211 | result 212 | } 213 | 214 | fn gen_framebuffers(&self, n: GLsizei) -> Vec { 215 | let mut result = vec![0 as GLuint; n as usize]; 216 | unsafe { 217 | self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr()); 218 | } 219 | result 220 | } 221 | 222 | fn gen_textures(&self, n: GLsizei) -> Vec { 223 | let mut result = vec![0 as GLuint; n as usize]; 224 | unsafe { 225 | self.ffi_gl_.GenTextures(n, result.as_mut_ptr()); 226 | } 227 | result 228 | } 229 | 230 | fn gen_vertex_arrays(&self, n: GLsizei) -> Vec { 231 | let mut result = vec![0 as GLuint; n as usize]; 232 | unsafe { 233 | self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr()) 234 | } 235 | result 236 | } 237 | 238 | fn gen_vertex_arrays_apple(&self, n: GLsizei) -> Vec { 239 | let mut result = vec![0 as GLuint; n as usize]; 240 | unsafe { 241 | self.ffi_gl_.GenVertexArraysAPPLE(n, result.as_mut_ptr()) 242 | } 243 | result 244 | } 245 | 246 | fn gen_queries(&self, n: GLsizei) -> Vec { 247 | let mut result = vec![0 as GLuint; n as usize]; 248 | unsafe { 249 | self.ffi_gl_.GenQueries(n, result.as_mut_ptr()); 250 | } 251 | result 252 | } 253 | 254 | fn begin_query(&self, target: GLenum, id: GLuint) { 255 | unsafe { 256 | self.ffi_gl_.BeginQuery(target, id); 257 | } 258 | } 259 | 260 | fn end_query(&self, target: GLenum) { 261 | unsafe { 262 | self.ffi_gl_.EndQuery(target); 263 | } 264 | } 265 | 266 | fn query_counter(&self, id: GLuint, target: GLenum) { 267 | unsafe { 268 | self.ffi_gl_.QueryCounter(id, target); 269 | } 270 | } 271 | 272 | fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 { 273 | let mut result = 0; 274 | unsafe { 275 | self.ffi_gl_.GetQueryObjectiv(id, pname, &mut result); 276 | } 277 | result 278 | } 279 | 280 | fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 { 281 | let mut result = 0; 282 | unsafe { 283 | self.ffi_gl_.GetQueryObjectuiv(id, pname, &mut result); 284 | } 285 | result 286 | } 287 | 288 | fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 { 289 | let mut result = 0; 290 | unsafe { 291 | self.ffi_gl_.GetQueryObjecti64v(id, pname, &mut result); 292 | } 293 | result 294 | } 295 | 296 | fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 { 297 | let mut result = 0; 298 | unsafe { 299 | self.ffi_gl_.GetQueryObjectui64v(id, pname, &mut result); 300 | } 301 | result 302 | } 303 | 304 | fn delete_queries(&self, queries: &[GLuint]) { 305 | unsafe { 306 | self.ffi_gl_ 307 | .DeleteQueries(queries.len() as GLsizei, queries.as_ptr()); 308 | } 309 | } 310 | 311 | fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) { 312 | unsafe { 313 | self.ffi_gl_ 314 | .DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr()); 315 | } 316 | } 317 | 318 | fn delete_vertex_arrays_apple(&self, vertex_arrays: &[GLuint]) { 319 | unsafe { 320 | self.ffi_gl_ 321 | .DeleteVertexArraysAPPLE(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr()); 322 | } 323 | } 324 | 325 | fn delete_buffers(&self, buffers: &[GLuint]) { 326 | unsafe { 327 | self.ffi_gl_ 328 | .DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr()); 329 | } 330 | } 331 | 332 | fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) { 333 | unsafe { 334 | self.ffi_gl_ 335 | .DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr()); 336 | } 337 | } 338 | 339 | fn delete_framebuffers(&self, framebuffers: &[GLuint]) { 340 | unsafe { 341 | self.ffi_gl_ 342 | .DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr()); 343 | } 344 | } 345 | 346 | fn delete_textures(&self, textures: &[GLuint]) { 347 | unsafe { 348 | self.ffi_gl_ 349 | .DeleteTextures(textures.len() as GLsizei, textures.as_ptr()); 350 | } 351 | } 352 | 353 | fn framebuffer_renderbuffer( 354 | &self, 355 | target: GLenum, 356 | attachment: GLenum, 357 | renderbuffertarget: GLenum, 358 | renderbuffer: GLuint, 359 | ) { 360 | unsafe { 361 | self.ffi_gl_.FramebufferRenderbuffer( 362 | target, 363 | attachment, 364 | renderbuffertarget, 365 | renderbuffer, 366 | ); 367 | } 368 | } 369 | 370 | fn renderbuffer_storage( 371 | &self, 372 | target: GLenum, 373 | internalformat: GLenum, 374 | width: GLsizei, 375 | height: GLsizei, 376 | ) { 377 | unsafe { 378 | self.ffi_gl_ 379 | .RenderbufferStorage(target, internalformat, width, height); 380 | } 381 | } 382 | 383 | fn depth_func(&self, func: GLenum) { 384 | unsafe { 385 | self.ffi_gl_.DepthFunc(func); 386 | } 387 | } 388 | 389 | fn active_texture(&self, texture: GLenum) { 390 | unsafe { 391 | self.ffi_gl_.ActiveTexture(texture); 392 | } 393 | } 394 | 395 | fn attach_shader(&self, program: GLuint, shader: GLuint) { 396 | unsafe { 397 | self.ffi_gl_.AttachShader(program, shader); 398 | } 399 | } 400 | 401 | fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) { 402 | let c_string = CString::new(name).unwrap(); 403 | unsafe { 404 | self.ffi_gl_ 405 | .BindAttribLocation(program, index, c_string.as_ptr()) 406 | } 407 | } 408 | 409 | // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml 410 | unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) { 411 | assert!(!result.is_empty()); 412 | self.ffi_gl_ 413 | .GetUniformiv(program, location, result.as_mut_ptr()); 414 | } 415 | 416 | // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml 417 | unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) { 418 | assert!(!result.is_empty()); 419 | self.ffi_gl_ 420 | .GetUniformfv(program, location, result.as_mut_ptr()); 421 | } 422 | 423 | fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { 424 | let c_string = CString::new(name).unwrap(); 425 | unsafe { 426 | self.ffi_gl_ 427 | .GetUniformBlockIndex(program, c_string.as_ptr()) 428 | } 429 | } 430 | 431 | fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec { 432 | let c_strings: Vec = names.iter().map(|n| CString::new(*n).unwrap()).collect(); 433 | let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect(); 434 | let mut result = Vec::with_capacity(c_strings.len()); 435 | unsafe { 436 | result.set_len(c_strings.len()); 437 | self.ffi_gl_.GetUniformIndices( 438 | program, 439 | pointers.len() as GLsizei, 440 | pointers.as_ptr(), 441 | result.as_mut_ptr(), 442 | ); 443 | } 444 | result 445 | } 446 | 447 | fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) { 448 | unsafe { 449 | self.ffi_gl_.BindBufferBase(target, index, buffer); 450 | } 451 | } 452 | 453 | fn bind_buffer_range( 454 | &self, 455 | target: GLenum, 456 | index: GLuint, 457 | buffer: GLuint, 458 | offset: GLintptr, 459 | size: GLsizeiptr, 460 | ) { 461 | unsafe { 462 | self.ffi_gl_ 463 | .BindBufferRange(target, index, buffer, offset, size); 464 | } 465 | } 466 | 467 | fn uniform_block_binding( 468 | &self, 469 | program: GLuint, 470 | uniform_block_index: GLuint, 471 | uniform_block_binding: GLuint, 472 | ) { 473 | unsafe { 474 | self.ffi_gl_ 475 | .UniformBlockBinding(program, uniform_block_index, uniform_block_binding); 476 | } 477 | } 478 | 479 | fn bind_buffer(&self, target: GLenum, buffer: GLuint) { 480 | unsafe { 481 | self.ffi_gl_.BindBuffer(target, buffer); 482 | } 483 | } 484 | 485 | fn bind_vertex_array(&self, vao: GLuint) { 486 | unsafe { 487 | self.ffi_gl_.BindVertexArray(vao); 488 | } 489 | } 490 | 491 | fn bind_vertex_array_apple(&self, vao: GLuint) { 492 | unsafe { 493 | self.ffi_gl_.BindVertexArrayAPPLE(vao) 494 | } 495 | } 496 | 497 | fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) { 498 | unsafe { 499 | self.ffi_gl_.BindRenderbuffer(target, renderbuffer); 500 | } 501 | } 502 | 503 | fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) { 504 | unsafe { 505 | self.ffi_gl_.BindFramebuffer(target, framebuffer); 506 | } 507 | } 508 | 509 | fn bind_texture(&self, target: GLenum, texture: GLuint) { 510 | unsafe { 511 | self.ffi_gl_.BindTexture(target, texture); 512 | } 513 | } 514 | 515 | fn bind_vertex_buffer(&self, binding_index: GLuint, buffer: GLuint, offset: GLintptr, stride: GLint) { 516 | unsafe { self.ffi_gl_.BindVertexBuffer(binding_index, buffer, offset, stride) } 517 | } 518 | 519 | fn draw_buffers(&self, bufs: &[GLenum]) { 520 | unsafe { 521 | self.ffi_gl_ 522 | .DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr()); 523 | } 524 | } 525 | 526 | // FIXME: Does not verify buffer size -- unsafe! 527 | fn tex_image_2d( 528 | &self, 529 | target: GLenum, 530 | level: GLint, 531 | internal_format: GLint, 532 | width: GLsizei, 533 | height: GLsizei, 534 | border: GLint, 535 | format: GLenum, 536 | ty: GLenum, 537 | opt_data: Option<&[u8]>, 538 | ) { 539 | match opt_data { 540 | Some(data) => unsafe { 541 | self.ffi_gl_.TexImage2D( 542 | target, 543 | level, 544 | internal_format, 545 | width, 546 | height, 547 | border, 548 | format, 549 | ty, 550 | data.as_ptr() as *const GLvoid, 551 | ); 552 | }, 553 | None => unsafe { 554 | self.ffi_gl_.TexImage2D( 555 | target, 556 | level, 557 | internal_format, 558 | width, 559 | height, 560 | border, 561 | format, 562 | ty, 563 | ptr::null(), 564 | ); 565 | }, 566 | } 567 | } 568 | 569 | fn compressed_tex_image_2d( 570 | &self, 571 | target: GLenum, 572 | level: GLint, 573 | internal_format: GLenum, 574 | width: GLsizei, 575 | height: GLsizei, 576 | border: GLint, 577 | data: &[u8], 578 | ) { 579 | unsafe { 580 | self.ffi_gl_.CompressedTexImage2D( 581 | target, 582 | level, 583 | internal_format, 584 | width, 585 | height, 586 | border, 587 | data.len() as GLsizei, 588 | data.as_ptr() as *const GLvoid, 589 | ); 590 | } 591 | } 592 | 593 | fn compressed_tex_sub_image_2d( 594 | &self, 595 | target: GLenum, 596 | level: GLint, 597 | xoffset: GLint, 598 | yoffset: GLint, 599 | width: GLsizei, 600 | height: GLsizei, 601 | format: GLenum, 602 | data: &[u8], 603 | ) { 604 | unsafe { 605 | self.ffi_gl_.CompressedTexSubImage2D( 606 | target, 607 | level, 608 | xoffset, 609 | yoffset, 610 | width, 611 | height, 612 | format, 613 | data.len() as GLsizei, 614 | data.as_ptr() as *const GLvoid, 615 | ); 616 | } 617 | } 618 | 619 | // FIXME: Does not verify buffer size -- unsafe! 620 | fn tex_image_3d( 621 | &self, 622 | target: GLenum, 623 | level: GLint, 624 | internal_format: GLint, 625 | width: GLsizei, 626 | height: GLsizei, 627 | depth: GLsizei, 628 | border: GLint, 629 | format: GLenum, 630 | ty: GLenum, 631 | opt_data: Option<&[u8]>, 632 | ) { 633 | unsafe { 634 | let pdata = match opt_data { 635 | Some(data) => mem::transmute(data.as_ptr()), 636 | None => ptr::null(), 637 | }; 638 | self.ffi_gl_.TexImage3D( 639 | target, 640 | level, 641 | internal_format, 642 | width, 643 | height, 644 | depth, 645 | border, 646 | format, 647 | ty, 648 | pdata, 649 | ); 650 | } 651 | } 652 | 653 | fn copy_tex_image_2d( 654 | &self, 655 | target: GLenum, 656 | level: GLint, 657 | internal_format: GLenum, 658 | x: GLint, 659 | y: GLint, 660 | width: GLsizei, 661 | height: GLsizei, 662 | border: GLint, 663 | ) { 664 | unsafe { 665 | self.ffi_gl_.CopyTexImage2D( 666 | target, 667 | level, 668 | internal_format, 669 | x, 670 | y, 671 | width, 672 | height, 673 | border, 674 | ); 675 | } 676 | } 677 | 678 | fn copy_tex_sub_image_2d( 679 | &self, 680 | target: GLenum, 681 | level: GLint, 682 | xoffset: GLint, 683 | yoffset: GLint, 684 | x: GLint, 685 | y: GLint, 686 | width: GLsizei, 687 | height: GLsizei, 688 | ) { 689 | unsafe { 690 | self.ffi_gl_ 691 | .CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); 692 | } 693 | } 694 | 695 | fn copy_tex_sub_image_3d( 696 | &self, 697 | target: GLenum, 698 | level: GLint, 699 | xoffset: GLint, 700 | yoffset: GLint, 701 | zoffset: GLint, 702 | x: GLint, 703 | y: GLint, 704 | width: GLsizei, 705 | height: GLsizei, 706 | ) { 707 | unsafe { 708 | self.ffi_gl_.CopyTexSubImage3D( 709 | target, level, xoffset, yoffset, zoffset, x, y, width, height, 710 | ); 711 | } 712 | } 713 | 714 | fn tex_sub_image_2d( 715 | &self, 716 | target: GLenum, 717 | level: GLint, 718 | xoffset: GLint, 719 | yoffset: GLint, 720 | width: GLsizei, 721 | height: GLsizei, 722 | format: GLenum, 723 | ty: GLenum, 724 | data: &[u8], 725 | ) { 726 | unsafe { 727 | self.ffi_gl_.TexSubImage2D( 728 | target, 729 | level, 730 | xoffset, 731 | yoffset, 732 | width, 733 | height, 734 | format, 735 | ty, 736 | data.as_ptr() as *const c_void, 737 | ); 738 | } 739 | } 740 | 741 | fn tex_sub_image_2d_pbo( 742 | &self, 743 | target: GLenum, 744 | level: GLint, 745 | xoffset: GLint, 746 | yoffset: GLint, 747 | width: GLsizei, 748 | height: GLsizei, 749 | format: GLenum, 750 | ty: GLenum, 751 | offset: usize, 752 | ) { 753 | unsafe { 754 | self.ffi_gl_.TexSubImage2D( 755 | target, 756 | level, 757 | xoffset, 758 | yoffset, 759 | width, 760 | height, 761 | format, 762 | ty, 763 | offset as *const c_void, 764 | ); 765 | } 766 | } 767 | 768 | fn tex_sub_image_3d( 769 | &self, 770 | target: GLenum, 771 | level: GLint, 772 | xoffset: GLint, 773 | yoffset: GLint, 774 | zoffset: GLint, 775 | width: GLsizei, 776 | height: GLsizei, 777 | depth: GLsizei, 778 | format: GLenum, 779 | ty: GLenum, 780 | data: &[u8], 781 | ) { 782 | unsafe { 783 | self.ffi_gl_.TexSubImage3D( 784 | target, 785 | level, 786 | xoffset, 787 | yoffset, 788 | zoffset, 789 | width, 790 | height, 791 | depth, 792 | format, 793 | ty, 794 | data.as_ptr() as *const c_void, 795 | ); 796 | } 797 | } 798 | 799 | fn tex_sub_image_3d_pbo( 800 | &self, 801 | target: GLenum, 802 | level: GLint, 803 | xoffset: GLint, 804 | yoffset: GLint, 805 | zoffset: GLint, 806 | width: GLsizei, 807 | height: GLsizei, 808 | depth: GLsizei, 809 | format: GLenum, 810 | ty: GLenum, 811 | offset: usize, 812 | ) { 813 | unsafe { 814 | self.ffi_gl_.TexSubImage3D( 815 | target, 816 | level, 817 | xoffset, 818 | yoffset, 819 | zoffset, 820 | width, 821 | height, 822 | depth, 823 | format, 824 | ty, 825 | offset as *const c_void, 826 | ); 827 | } 828 | } 829 | 830 | fn tex_storage_2d( 831 | &self, 832 | target: GLenum, 833 | levels: GLint, 834 | internal_format: GLenum, 835 | width: GLsizei, 836 | height: GLsizei, 837 | ) { 838 | if self.ffi_gl_.TexStorage2D.is_loaded() { 839 | unsafe { 840 | self.ffi_gl_ 841 | .TexStorage2D(target, levels, internal_format, width, height); 842 | } 843 | } 844 | } 845 | 846 | fn tex_storage_3d( 847 | &self, 848 | target: GLenum, 849 | levels: GLint, 850 | internal_format: GLenum, 851 | width: GLsizei, 852 | height: GLsizei, 853 | depth: GLsizei, 854 | ) { 855 | if self.ffi_gl_.TexStorage3D.is_loaded() { 856 | unsafe { 857 | self.ffi_gl_ 858 | .TexStorage3D(target, levels, internal_format, width, height, depth); 859 | } 860 | } 861 | } 862 | 863 | fn get_tex_image_into_buffer( 864 | &self, 865 | target: GLenum, 866 | level: GLint, 867 | format: GLenum, 868 | ty: GLenum, 869 | output: &mut [u8], 870 | ) { 871 | unsafe { 872 | self.ffi_gl_ 873 | .GetTexImage(target, level, format, ty, output.as_mut_ptr() as *mut _); 874 | } 875 | } 876 | 877 | unsafe fn copy_image_sub_data( 878 | &self, 879 | src_name: GLuint, 880 | src_target: GLenum, 881 | src_level: GLint, 882 | src_x: GLint, 883 | src_y: GLint, 884 | src_z: GLint, 885 | dst_name: GLuint, 886 | dst_target: GLenum, 887 | dst_level: GLint, 888 | dst_x: GLint, 889 | dst_y: GLint, 890 | dst_z: GLint, 891 | src_width: GLsizei, 892 | src_height: GLsizei, 893 | src_depth: GLsizei, 894 | ) { 895 | self.ffi_gl_.CopyImageSubData( 896 | src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target, dst_level, 897 | dst_x, dst_y, dst_z, src_width, src_height, src_depth, 898 | ); 899 | } 900 | 901 | fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) { 902 | if self.ffi_gl_.InvalidateFramebuffer.is_loaded() { 903 | unsafe { 904 | self.ffi_gl_.InvalidateFramebuffer( 905 | target, 906 | attachments.len() as GLsizei, 907 | attachments.as_ptr(), 908 | ); 909 | } 910 | } 911 | } 912 | 913 | fn invalidate_sub_framebuffer( 914 | &self, 915 | target: GLenum, 916 | attachments: &[GLenum], 917 | xoffset: GLint, 918 | yoffset: GLint, 919 | width: GLsizei, 920 | height: GLsizei, 921 | ) { 922 | if self.ffi_gl_.InvalidateSubFramebuffer.is_loaded() { 923 | unsafe { 924 | self.ffi_gl_.InvalidateSubFramebuffer( 925 | target, 926 | attachments.len() as GLsizei, 927 | attachments.as_ptr(), 928 | xoffset, 929 | yoffset, 930 | width, 931 | height, 932 | ); 933 | } 934 | } 935 | } 936 | 937 | #[inline] 938 | unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) { 939 | assert!(!result.is_empty()); 940 | self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr()); 941 | } 942 | 943 | #[inline] 944 | unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) { 945 | assert!(!result.is_empty()); 946 | self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr()); 947 | } 948 | 949 | #[inline] 950 | unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) { 951 | assert!(!result.is_empty()); 952 | self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr()); 953 | } 954 | 955 | #[inline] 956 | unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) { 957 | assert!(!result.is_empty()); 958 | self.ffi_gl_ 959 | .GetInteger64i_v(name, index, result.as_mut_ptr()); 960 | } 961 | 962 | #[inline] 963 | unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) { 964 | assert!(!result.is_empty()); 965 | self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr()); 966 | } 967 | 968 | #[inline] 969 | unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) { 970 | assert!(!result.is_empty()); 971 | self.ffi_gl_.GetFloatv(name, result.as_mut_ptr()); 972 | } 973 | 974 | fn get_framebuffer_attachment_parameter_iv( 975 | &self, 976 | target: GLenum, 977 | attachment: GLenum, 978 | pname: GLenum, 979 | ) -> GLint { 980 | let mut result: GLint = 0; 981 | unsafe { 982 | self.ffi_gl_.GetFramebufferAttachmentParameteriv( 983 | target, 984 | attachment, 985 | pname, 986 | &mut result, 987 | ); 988 | } 989 | result 990 | } 991 | 992 | fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint { 993 | let mut result: GLint = 0; 994 | unsafe { 995 | self.ffi_gl_ 996 | .GetRenderbufferParameteriv(target, pname, &mut result); 997 | } 998 | result 999 | } 1000 | 1001 | fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint { 1002 | let mut result: GLint = 0; 1003 | unsafe { 1004 | self.ffi_gl_.GetTexParameteriv(target, pname, &mut result); 1005 | } 1006 | result 1007 | } 1008 | 1009 | fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat { 1010 | let mut result: GLfloat = 0.0; 1011 | unsafe { 1012 | self.ffi_gl_.GetTexParameterfv(target, pname, &mut result); 1013 | } 1014 | result 1015 | } 1016 | 1017 | fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) { 1018 | unsafe { 1019 | self.ffi_gl_.TexParameteri(target, pname, param); 1020 | } 1021 | } 1022 | 1023 | fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) { 1024 | unsafe { 1025 | self.ffi_gl_.TexParameterf(target, pname, param); 1026 | } 1027 | } 1028 | 1029 | fn framebuffer_texture_2d( 1030 | &self, 1031 | target: GLenum, 1032 | attachment: GLenum, 1033 | textarget: GLenum, 1034 | texture: GLuint, 1035 | level: GLint, 1036 | ) { 1037 | unsafe { 1038 | self.ffi_gl_ 1039 | .FramebufferTexture2D(target, attachment, textarget, texture, level); 1040 | } 1041 | } 1042 | 1043 | fn framebuffer_texture_layer( 1044 | &self, 1045 | target: GLenum, 1046 | attachment: GLenum, 1047 | texture: GLuint, 1048 | level: GLint, 1049 | layer: GLint, 1050 | ) { 1051 | unsafe { 1052 | self.ffi_gl_ 1053 | .FramebufferTextureLayer(target, attachment, texture, level, layer); 1054 | } 1055 | } 1056 | 1057 | fn blit_framebuffer( 1058 | &self, 1059 | src_x0: GLint, 1060 | src_y0: GLint, 1061 | src_x1: GLint, 1062 | src_y1: GLint, 1063 | dst_x0: GLint, 1064 | dst_y0: GLint, 1065 | dst_x1: GLint, 1066 | dst_y1: GLint, 1067 | mask: GLbitfield, 1068 | filter: GLenum, 1069 | ) { 1070 | unsafe { 1071 | self.ffi_gl_.BlitFramebuffer( 1072 | src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter, 1073 | ); 1074 | } 1075 | } 1076 | 1077 | fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) { 1078 | unsafe { self.ffi_gl_.VertexAttrib4f(index, x, y, z, w) } 1079 | } 1080 | 1081 | fn vertex_attrib_binding(&self, attrib_index: GLuint, binding_index: GLuint) { 1082 | unsafe { self.ffi_gl_.VertexAttribBinding(attrib_index, binding_index) } 1083 | } 1084 | 1085 | fn vertex_attrib_pointer_f32( 1086 | &self, 1087 | index: GLuint, 1088 | size: GLint, 1089 | normalized: bool, 1090 | stride: GLsizei, 1091 | offset: GLuint, 1092 | ) { 1093 | unsafe { 1094 | self.ffi_gl_.VertexAttribPointer( 1095 | index, 1096 | size, 1097 | ffi::FLOAT, 1098 | normalized as GLboolean, 1099 | stride, 1100 | offset as *const GLvoid, 1101 | ) 1102 | } 1103 | } 1104 | 1105 | fn vertex_attrib_pointer( 1106 | &self, 1107 | index: GLuint, 1108 | size: GLint, 1109 | type_: GLenum, 1110 | normalized: bool, 1111 | stride: GLsizei, 1112 | offset: GLuint, 1113 | ) { 1114 | unsafe { 1115 | self.ffi_gl_.VertexAttribPointer( 1116 | index, 1117 | size, 1118 | type_, 1119 | normalized as GLboolean, 1120 | stride, 1121 | offset as *const GLvoid, 1122 | ) 1123 | } 1124 | } 1125 | 1126 | fn vertex_attrib_i_pointer( 1127 | &self, 1128 | index: GLuint, 1129 | size: GLint, 1130 | type_: GLenum, 1131 | stride: GLsizei, 1132 | offset: GLuint, 1133 | ) { 1134 | unsafe { 1135 | self.ffi_gl_ 1136 | .VertexAttribIPointer(index, size, type_, stride, offset as *const GLvoid) 1137 | } 1138 | } 1139 | 1140 | fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) { 1141 | unsafe { self.ffi_gl_.VertexAttribDivisor(index, divisor) } 1142 | } 1143 | 1144 | fn vertex_attrib_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, normalized: bool, relative_offset: GLuint) { 1145 | unsafe { self.ffi_gl_.VertexAttribFormat(attrib_index, size, type_, normalized as GLboolean, relative_offset) } 1146 | } 1147 | 1148 | fn vertex_attrib_i_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, relative_offset: GLuint) { 1149 | unsafe { self.ffi_gl_.VertexAttribIFormat(attrib_index, size, type_, relative_offset) } 1150 | } 1151 | 1152 | fn vertex_binding_divisor(&self, binding_index: GLuint, divisor: GLuint) { 1153 | unsafe { self.ffi_gl_.VertexBindingDivisor(binding_index, divisor) } 1154 | } 1155 | 1156 | fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) { 1157 | unsafe { 1158 | self.ffi_gl_.Viewport(x, y, width, height); 1159 | } 1160 | } 1161 | 1162 | fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) { 1163 | unsafe { 1164 | self.ffi_gl_.Scissor(x, y, width, height); 1165 | } 1166 | } 1167 | 1168 | fn line_width(&self, width: GLfloat) { 1169 | unsafe { 1170 | self.ffi_gl_.LineWidth(width); 1171 | } 1172 | } 1173 | 1174 | fn use_program(&self, program: GLuint) { 1175 | unsafe { 1176 | self.ffi_gl_.UseProgram(program); 1177 | } 1178 | } 1179 | 1180 | fn validate_program(&self, program: GLuint) { 1181 | unsafe { 1182 | self.ffi_gl_.ValidateProgram(program); 1183 | } 1184 | } 1185 | 1186 | fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) { 1187 | unsafe { 1188 | return self.ffi_gl_.DrawArrays(mode, first, count); 1189 | } 1190 | } 1191 | 1192 | fn draw_arrays_instanced( 1193 | &self, 1194 | mode: GLenum, 1195 | first: GLint, 1196 | count: GLsizei, 1197 | primcount: GLsizei, 1198 | ) { 1199 | unsafe { 1200 | return self 1201 | .ffi_gl_ 1202 | .DrawArraysInstanced(mode, first, count, primcount); 1203 | } 1204 | } 1205 | 1206 | fn draw_elements( 1207 | &self, 1208 | mode: GLenum, 1209 | count: GLsizei, 1210 | element_type: GLenum, 1211 | indices_offset: GLuint, 1212 | ) { 1213 | unsafe { 1214 | return self.ffi_gl_.DrawElements( 1215 | mode, 1216 | count, 1217 | element_type, 1218 | indices_offset as *const c_void, 1219 | ); 1220 | } 1221 | } 1222 | 1223 | fn draw_elements_instanced( 1224 | &self, 1225 | mode: GLenum, 1226 | count: GLsizei, 1227 | element_type: GLenum, 1228 | indices_offset: GLuint, 1229 | primcount: GLsizei, 1230 | ) { 1231 | unsafe { 1232 | return self.ffi_gl_.DrawElementsInstanced( 1233 | mode, 1234 | count, 1235 | element_type, 1236 | indices_offset as *const c_void, 1237 | primcount, 1238 | ); 1239 | } 1240 | } 1241 | 1242 | fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) { 1243 | unsafe { 1244 | self.ffi_gl_.BlendColor(r, g, b, a); 1245 | } 1246 | } 1247 | 1248 | fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) { 1249 | unsafe { 1250 | self.ffi_gl_.BlendFunc(sfactor, dfactor); 1251 | } 1252 | } 1253 | 1254 | fn blend_func_separate( 1255 | &self, 1256 | src_rgb: GLenum, 1257 | dest_rgb: GLenum, 1258 | src_alpha: GLenum, 1259 | dest_alpha: GLenum, 1260 | ) { 1261 | unsafe { 1262 | self.ffi_gl_ 1263 | .BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha); 1264 | } 1265 | } 1266 | 1267 | fn blend_equation(&self, mode: GLenum) { 1268 | unsafe { 1269 | self.ffi_gl_.BlendEquation(mode); 1270 | } 1271 | } 1272 | 1273 | fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) { 1274 | unsafe { 1275 | self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha); 1276 | } 1277 | } 1278 | 1279 | fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) { 1280 | unsafe { 1281 | self.ffi_gl_.ColorMask( 1282 | r as GLboolean, 1283 | g as GLboolean, 1284 | b as GLboolean, 1285 | a as GLboolean, 1286 | ); 1287 | } 1288 | } 1289 | 1290 | fn cull_face(&self, mode: GLenum) { 1291 | unsafe { 1292 | self.ffi_gl_.CullFace(mode); 1293 | } 1294 | } 1295 | 1296 | fn front_face(&self, mode: GLenum) { 1297 | unsafe { 1298 | self.ffi_gl_.FrontFace(mode); 1299 | } 1300 | } 1301 | 1302 | fn enable(&self, cap: GLenum) { 1303 | unsafe { 1304 | self.ffi_gl_.Enable(cap); 1305 | } 1306 | } 1307 | 1308 | fn disable(&self, cap: GLenum) { 1309 | unsafe { 1310 | self.ffi_gl_.Disable(cap); 1311 | } 1312 | } 1313 | 1314 | fn hint(&self, param_name: GLenum, param_val: GLenum) { 1315 | unsafe { 1316 | self.ffi_gl_.Hint(param_name, param_val); 1317 | } 1318 | } 1319 | 1320 | fn is_enabled(&self, cap: GLenum) -> GLboolean { 1321 | unsafe { self.ffi_gl_.IsEnabled(cap) } 1322 | } 1323 | 1324 | fn is_shader(&self, shader: GLuint) -> GLboolean { 1325 | unsafe { self.ffi_gl_.IsShader(shader) } 1326 | } 1327 | 1328 | fn is_texture(&self, texture: GLenum) -> GLboolean { 1329 | unsafe { self.ffi_gl_.IsTexture(texture) } 1330 | } 1331 | 1332 | fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean { 1333 | unsafe { self.ffi_gl_.IsFramebuffer(framebuffer) } 1334 | } 1335 | 1336 | fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean { 1337 | unsafe { self.ffi_gl_.IsRenderbuffer(renderbuffer) } 1338 | } 1339 | 1340 | fn check_frame_buffer_status(&self, target: GLenum) -> GLenum { 1341 | unsafe { self.ffi_gl_.CheckFramebufferStatus(target) } 1342 | } 1343 | 1344 | fn enable_vertex_attrib_array(&self, index: GLuint) { 1345 | unsafe { 1346 | self.ffi_gl_.EnableVertexAttribArray(index); 1347 | } 1348 | } 1349 | 1350 | fn disable_vertex_attrib_array(&self, index: GLuint) { 1351 | unsafe { 1352 | self.ffi_gl_.DisableVertexAttribArray(index); 1353 | } 1354 | } 1355 | 1356 | fn uniform_1f(&self, location: GLint, v0: GLfloat) { 1357 | unsafe { 1358 | self.ffi_gl_.Uniform1f(location, v0); 1359 | } 1360 | } 1361 | 1362 | fn uniform_1fv(&self, location: GLint, values: &[f32]) { 1363 | unsafe { 1364 | self.ffi_gl_ 1365 | .Uniform1fv(location, values.len() as GLsizei, values.as_ptr()); 1366 | } 1367 | } 1368 | 1369 | fn uniform_1i(&self, location: GLint, v0: GLint) { 1370 | unsafe { 1371 | self.ffi_gl_.Uniform1i(location, v0); 1372 | } 1373 | } 1374 | 1375 | fn uniform_1iv(&self, location: GLint, values: &[i32]) { 1376 | unsafe { 1377 | self.ffi_gl_ 1378 | .Uniform1iv(location, values.len() as GLsizei, values.as_ptr()); 1379 | } 1380 | } 1381 | 1382 | fn uniform_1ui(&self, location: GLint, v0: GLuint) { 1383 | unsafe { 1384 | self.ffi_gl_.Uniform1ui(location, v0); 1385 | } 1386 | } 1387 | 1388 | fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) { 1389 | unsafe { 1390 | self.ffi_gl_.Uniform2f(location, v0, v1); 1391 | } 1392 | } 1393 | 1394 | fn uniform_2fv(&self, location: GLint, values: &[f32]) { 1395 | unsafe { 1396 | self.ffi_gl_ 1397 | .Uniform2fv(location, (values.len() / 2) as GLsizei, values.as_ptr()); 1398 | } 1399 | } 1400 | 1401 | fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) { 1402 | unsafe { 1403 | self.ffi_gl_.Uniform2i(location, v0, v1); 1404 | } 1405 | } 1406 | 1407 | fn uniform_2iv(&self, location: GLint, values: &[i32]) { 1408 | unsafe { 1409 | self.ffi_gl_ 1410 | .Uniform2iv(location, (values.len() / 2) as GLsizei, values.as_ptr()); 1411 | } 1412 | } 1413 | 1414 | fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) { 1415 | unsafe { 1416 | self.ffi_gl_.Uniform2ui(location, v0, v1); 1417 | } 1418 | } 1419 | 1420 | fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) { 1421 | unsafe { 1422 | self.ffi_gl_.Uniform3f(location, v0, v1, v2); 1423 | } 1424 | } 1425 | 1426 | fn uniform_3fv(&self, location: GLint, values: &[f32]) { 1427 | unsafe { 1428 | self.ffi_gl_ 1429 | .Uniform3fv(location, (values.len() / 3) as GLsizei, values.as_ptr()); 1430 | } 1431 | } 1432 | 1433 | fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) { 1434 | unsafe { 1435 | self.ffi_gl_.Uniform3i(location, v0, v1, v2); 1436 | } 1437 | } 1438 | 1439 | fn uniform_3iv(&self, location: GLint, values: &[i32]) { 1440 | unsafe { 1441 | self.ffi_gl_ 1442 | .Uniform3iv(location, (values.len() / 3) as GLsizei, values.as_ptr()); 1443 | } 1444 | } 1445 | 1446 | fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) { 1447 | unsafe { 1448 | self.ffi_gl_.Uniform3ui(location, v0, v1, v2); 1449 | } 1450 | } 1451 | 1452 | fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) { 1453 | unsafe { 1454 | self.ffi_gl_.Uniform4f(location, x, y, z, w); 1455 | } 1456 | } 1457 | 1458 | fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) { 1459 | unsafe { 1460 | self.ffi_gl_.Uniform4i(location, x, y, z, w); 1461 | } 1462 | } 1463 | 1464 | fn uniform_4iv(&self, location: GLint, values: &[i32]) { 1465 | unsafe { 1466 | self.ffi_gl_ 1467 | .Uniform4iv(location, (values.len() / 4) as GLsizei, values.as_ptr()); 1468 | } 1469 | } 1470 | 1471 | fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) { 1472 | unsafe { 1473 | self.ffi_gl_.Uniform4ui(location, x, y, z, w); 1474 | } 1475 | } 1476 | 1477 | fn uniform_4fv(&self, location: GLint, values: &[f32]) { 1478 | unsafe { 1479 | self.ffi_gl_ 1480 | .Uniform4fv(location, (values.len() / 4) as GLsizei, values.as_ptr()); 1481 | } 1482 | } 1483 | 1484 | fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1485 | unsafe { 1486 | self.ffi_gl_.UniformMatrix2fv( 1487 | location, 1488 | (value.len() / 4) as GLsizei, 1489 | transpose as GLboolean, 1490 | value.as_ptr(), 1491 | ); 1492 | } 1493 | } 1494 | 1495 | fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1496 | unsafe { 1497 | self.ffi_gl_.UniformMatrix3fv( 1498 | location, 1499 | (value.len() / 9) as GLsizei, 1500 | transpose as GLboolean, 1501 | value.as_ptr(), 1502 | ); 1503 | } 1504 | } 1505 | 1506 | fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1507 | unsafe { 1508 | self.ffi_gl_.UniformMatrix4fv( 1509 | location, 1510 | (value.len() / 16) as GLsizei, 1511 | transpose as GLboolean, 1512 | value.as_ptr(), 1513 | ); 1514 | } 1515 | } 1516 | 1517 | fn depth_mask(&self, flag: bool) { 1518 | unsafe { 1519 | self.ffi_gl_.DepthMask(flag as GLboolean); 1520 | } 1521 | } 1522 | 1523 | fn depth_range(&self, near: f64, far: f64) { 1524 | unsafe { 1525 | self.ffi_gl_.DepthRange(near as GLclampd, far as GLclampd); 1526 | } 1527 | } 1528 | 1529 | fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) { 1530 | let mut buf_size = [0]; 1531 | unsafe { 1532 | self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size); 1533 | } 1534 | let mut name = vec![0u8; buf_size[0] as usize]; 1535 | let mut length = 0 as GLsizei; 1536 | let mut size = 0 as i32; 1537 | let mut type_ = 0 as u32; 1538 | unsafe { 1539 | self.ffi_gl_.GetActiveAttrib( 1540 | program, 1541 | index, 1542 | buf_size[0], 1543 | &mut length, 1544 | &mut size, 1545 | &mut type_, 1546 | name.as_mut_ptr() as *mut GLchar, 1547 | ); 1548 | } 1549 | name.truncate(if length > 0 { length as usize } else { 0 }); 1550 | (size, type_, String::from_utf8(name).unwrap()) 1551 | } 1552 | 1553 | fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) { 1554 | let mut buf_size = [0]; 1555 | unsafe { 1556 | self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size); 1557 | } 1558 | let mut name = vec![0 as u8; buf_size[0] as usize]; 1559 | let mut length: GLsizei = 0; 1560 | let mut size: i32 = 0; 1561 | let mut type_: u32 = 0; 1562 | 1563 | unsafe { 1564 | self.ffi_gl_.GetActiveUniform( 1565 | program, 1566 | index, 1567 | buf_size[0], 1568 | &mut length, 1569 | &mut size, 1570 | &mut type_, 1571 | name.as_mut_ptr() as *mut GLchar, 1572 | ); 1573 | } 1574 | 1575 | name.truncate(if length > 0 { length as usize } else { 0 }); 1576 | 1577 | (size, type_, String::from_utf8(name).unwrap()) 1578 | } 1579 | 1580 | fn get_active_uniforms_iv( 1581 | &self, 1582 | program: GLuint, 1583 | indices: Vec, 1584 | pname: GLenum, 1585 | ) -> Vec { 1586 | let mut result = Vec::with_capacity(indices.len()); 1587 | unsafe { 1588 | result.set_len(indices.len()); 1589 | self.ffi_gl_.GetActiveUniformsiv( 1590 | program, 1591 | indices.len() as GLsizei, 1592 | indices.as_ptr(), 1593 | pname, 1594 | result.as_mut_ptr(), 1595 | ); 1596 | } 1597 | result 1598 | } 1599 | 1600 | fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint { 1601 | let mut result = 0; 1602 | unsafe { 1603 | self.ffi_gl_ 1604 | .GetActiveUniformBlockiv(program, index, pname, &mut result); 1605 | } 1606 | result 1607 | } 1608 | 1609 | fn get_active_uniform_block_iv( 1610 | &self, 1611 | program: GLuint, 1612 | index: GLuint, 1613 | pname: GLenum, 1614 | ) -> Vec { 1615 | let count = 1616 | self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS); 1617 | let mut result = Vec::with_capacity(count as usize); 1618 | unsafe { 1619 | result.set_len(count as usize); 1620 | self.ffi_gl_ 1621 | .GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr()); 1622 | } 1623 | result 1624 | } 1625 | 1626 | fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String { 1627 | let buf_size = 1628 | self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH); 1629 | let mut name = vec![0 as u8; buf_size as usize]; 1630 | let mut length: GLsizei = 0; 1631 | unsafe { 1632 | self.ffi_gl_.GetActiveUniformBlockName( 1633 | program, 1634 | index, 1635 | buf_size, 1636 | &mut length, 1637 | name.as_mut_ptr() as *mut GLchar, 1638 | ); 1639 | } 1640 | name.truncate(if length > 0 { length as usize } else { 0 }); 1641 | 1642 | String::from_utf8(name).unwrap() 1643 | } 1644 | 1645 | fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int { 1646 | let name = CString::new(name).unwrap(); 1647 | unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) } 1648 | } 1649 | 1650 | fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int { 1651 | let name = CString::new(name).unwrap(); 1652 | unsafe { self.ffi_gl_.GetFragDataLocation(program, name.as_ptr()) } 1653 | } 1654 | 1655 | fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int { 1656 | let name = CString::new(name).unwrap(); 1657 | unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) } 1658 | } 1659 | 1660 | fn get_program_info_log(&self, program: GLuint) -> String { 1661 | let mut max_len = [0]; 1662 | unsafe { 1663 | self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len); 1664 | } 1665 | if max_len[0] == 0 { 1666 | return String::new(); 1667 | } 1668 | let mut result = vec![0u8; max_len[0] as usize]; 1669 | let mut result_len = 0 as GLsizei; 1670 | unsafe { 1671 | self.ffi_gl_.GetProgramInfoLog( 1672 | program, 1673 | max_len[0] as GLsizei, 1674 | &mut result_len, 1675 | result.as_mut_ptr() as *mut GLchar, 1676 | ); 1677 | } 1678 | result.truncate(if result_len > 0 { 1679 | result_len as usize 1680 | } else { 1681 | 0 1682 | }); 1683 | String::from_utf8(result).unwrap() 1684 | } 1685 | 1686 | #[inline] 1687 | unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) { 1688 | assert!(!result.is_empty()); 1689 | self.ffi_gl_ 1690 | .GetProgramiv(program, pname, result.as_mut_ptr()); 1691 | } 1692 | 1693 | fn get_program_binary(&self, program: GLuint) -> (Vec, GLenum) { 1694 | if !self.ffi_gl_.GetProgramBinary.is_loaded() { 1695 | return (Vec::new(), NONE); 1696 | } 1697 | let mut len = [0]; 1698 | unsafe { 1699 | self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len); 1700 | } 1701 | if len[0] <= 0 { 1702 | return (Vec::new(), NONE); 1703 | } 1704 | let mut binary: Vec = Vec::with_capacity(len[0] as usize); 1705 | let mut format = NONE; 1706 | let mut out_len = 0; 1707 | unsafe { 1708 | binary.set_len(len[0] as usize); 1709 | self.ffi_gl_.GetProgramBinary( 1710 | program, 1711 | len[0], 1712 | &mut out_len as *mut GLsizei, 1713 | &mut format, 1714 | binary.as_mut_ptr() as *mut c_void, 1715 | ); 1716 | } 1717 | if len[0] != out_len { 1718 | return (Vec::new(), NONE); 1719 | } 1720 | 1721 | (binary, format) 1722 | } 1723 | 1724 | fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) { 1725 | if !self.ffi_gl_.ProgramBinary.is_loaded() { 1726 | return; 1727 | } 1728 | unsafe { 1729 | self.ffi_gl_.ProgramBinary( 1730 | program, 1731 | format, 1732 | binary.as_ptr() as *const c_void, 1733 | binary.len() as GLsizei, 1734 | ); 1735 | } 1736 | } 1737 | 1738 | fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) { 1739 | if !self.ffi_gl_.ProgramParameteri.is_loaded() { 1740 | return; 1741 | } 1742 | unsafe { 1743 | self.ffi_gl_.ProgramParameteri(program, pname, value); 1744 | } 1745 | } 1746 | 1747 | #[inline] 1748 | unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) { 1749 | assert!(!result.is_empty()); 1750 | self.ffi_gl_ 1751 | .GetVertexAttribiv(index, pname, result.as_mut_ptr()); 1752 | } 1753 | 1754 | #[inline] 1755 | unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) { 1756 | assert!(!result.is_empty()); 1757 | self.ffi_gl_ 1758 | .GetVertexAttribfv(index, pname, result.as_mut_ptr()); 1759 | } 1760 | 1761 | fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr { 1762 | let mut result = 0 as *mut GLvoid; 1763 | unsafe { 1764 | self.ffi_gl_ 1765 | .GetVertexAttribPointerv(index, pname, &mut result) 1766 | } 1767 | result as GLsizeiptr 1768 | } 1769 | 1770 | fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint { 1771 | let mut result = 0 as GLint; 1772 | unsafe { 1773 | self.ffi_gl_ 1774 | .GetBufferParameteriv(target, pname, &mut result); 1775 | } 1776 | result 1777 | } 1778 | 1779 | fn get_shader_info_log(&self, shader: GLuint) -> String { 1780 | let mut max_len = [0]; 1781 | unsafe { 1782 | self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len); 1783 | } 1784 | if max_len[0] == 0 { 1785 | return String::new(); 1786 | } 1787 | let mut result = vec![0u8; max_len[0] as usize]; 1788 | let mut result_len = 0 as GLsizei; 1789 | unsafe { 1790 | self.ffi_gl_.GetShaderInfoLog( 1791 | shader, 1792 | max_len[0] as GLsizei, 1793 | &mut result_len, 1794 | result.as_mut_ptr() as *mut GLchar, 1795 | ); 1796 | } 1797 | result.truncate(if result_len > 0 { 1798 | result_len as usize 1799 | } else { 1800 | 0 1801 | }); 1802 | String::from_utf8(result).unwrap() 1803 | } 1804 | 1805 | fn get_string(&self, which: GLenum) -> String { 1806 | unsafe { 1807 | let llstr = self.ffi_gl_.GetString(which); 1808 | if !llstr.is_null() { 1809 | return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) 1810 | .to_string(); 1811 | } else { 1812 | return "".to_string(); 1813 | } 1814 | } 1815 | } 1816 | 1817 | fn get_string_i(&self, which: GLenum, index: GLuint) -> String { 1818 | unsafe { 1819 | let llstr = self.ffi_gl_.GetStringi(which, index); 1820 | if !llstr.is_null() { 1821 | str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) 1822 | .to_string() 1823 | } else { 1824 | "".to_string() 1825 | } 1826 | } 1827 | } 1828 | 1829 | unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) { 1830 | assert!(!result.is_empty()); 1831 | self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr()); 1832 | } 1833 | 1834 | fn get_shader_precision_format( 1835 | &self, 1836 | _shader_type: GLuint, 1837 | precision_type: GLuint, 1838 | ) -> (GLint, GLint, GLint) { 1839 | // gl.GetShaderPrecisionFormat is not available until OpenGL 4.1. 1840 | // Fallback to OpenGL standard precissions that most desktop hardware support. 1841 | match precision_type { 1842 | ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => { 1843 | // Fallback to IEEE 754 single precision 1844 | // Range: from -2^127 to 2^127 1845 | // Significand precision: 23 bits 1846 | (127, 127, 23) 1847 | } 1848 | ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => { 1849 | // Fallback to single precision integer 1850 | // Range: from -2^24 to 2^24 1851 | // Precision: For integer formats this value is always 0 1852 | (24, 24, 0) 1853 | } 1854 | _ => (0, 0, 0), 1855 | } 1856 | } 1857 | 1858 | fn compile_shader(&self, shader: GLuint) { 1859 | unsafe { 1860 | self.ffi_gl_.CompileShader(shader); 1861 | } 1862 | } 1863 | 1864 | fn create_program(&self) -> GLuint { 1865 | unsafe { 1866 | return self.ffi_gl_.CreateProgram(); 1867 | } 1868 | } 1869 | 1870 | fn delete_program(&self, program: GLuint) { 1871 | unsafe { 1872 | self.ffi_gl_.DeleteProgram(program); 1873 | } 1874 | } 1875 | 1876 | fn create_shader(&self, shader_type: GLenum) -> GLuint { 1877 | unsafe { 1878 | return self.ffi_gl_.CreateShader(shader_type); 1879 | } 1880 | } 1881 | 1882 | fn delete_shader(&self, shader: GLuint) { 1883 | unsafe { 1884 | self.ffi_gl_.DeleteShader(shader); 1885 | } 1886 | } 1887 | 1888 | fn detach_shader(&self, program: GLuint, shader: GLuint) { 1889 | unsafe { 1890 | self.ffi_gl_.DetachShader(program, shader); 1891 | } 1892 | } 1893 | 1894 | fn link_program(&self, program: GLuint) { 1895 | unsafe { 1896 | return self.ffi_gl_.LinkProgram(program); 1897 | } 1898 | } 1899 | 1900 | fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) { 1901 | unsafe { 1902 | self.ffi_gl_.ClearColor(r, g, b, a); 1903 | } 1904 | } 1905 | 1906 | fn clear(&self, buffer_mask: GLbitfield) { 1907 | unsafe { 1908 | self.ffi_gl_.Clear(buffer_mask); 1909 | } 1910 | } 1911 | 1912 | fn clear_depth(&self, depth: f64) { 1913 | unsafe { 1914 | self.ffi_gl_.ClearDepth(depth as GLclampd); 1915 | } 1916 | } 1917 | 1918 | fn clear_stencil(&self, s: GLint) { 1919 | unsafe { 1920 | self.ffi_gl_.ClearStencil(s); 1921 | } 1922 | } 1923 | 1924 | fn flush(&self) { 1925 | unsafe { 1926 | self.ffi_gl_.Flush(); 1927 | } 1928 | } 1929 | 1930 | fn finish(&self) { 1931 | unsafe { 1932 | self.ffi_gl_.Finish(); 1933 | } 1934 | } 1935 | 1936 | fn get_error(&self) -> GLenum { 1937 | unsafe { self.ffi_gl_.GetError() } 1938 | } 1939 | 1940 | fn stencil_mask(&self, mask: GLuint) { 1941 | unsafe { self.ffi_gl_.StencilMask(mask) } 1942 | } 1943 | 1944 | fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) { 1945 | unsafe { self.ffi_gl_.StencilMaskSeparate(face, mask) } 1946 | } 1947 | 1948 | fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) { 1949 | unsafe { self.ffi_gl_.StencilFunc(func, ref_, mask) } 1950 | } 1951 | 1952 | fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) { 1953 | unsafe { self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask) } 1954 | } 1955 | 1956 | fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) { 1957 | unsafe { self.ffi_gl_.StencilOp(sfail, dpfail, dppass) } 1958 | } 1959 | 1960 | fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) { 1961 | unsafe { self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass) } 1962 | } 1963 | 1964 | #[allow(unused_variables)] 1965 | fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) { 1966 | panic!("not supported") 1967 | } 1968 | 1969 | #[allow(unused_variables)] 1970 | fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES) { 1971 | panic!("not supported") 1972 | } 1973 | 1974 | fn generate_mipmap(&self, target: GLenum) { 1975 | unsafe { self.ffi_gl_.GenerateMipmap(target) } 1976 | } 1977 | 1978 | fn insert_event_marker_ext(&self, message: &str) { 1979 | if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() { 1980 | unsafe { 1981 | self.ffi_gl_ 1982 | .InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _); 1983 | } 1984 | } 1985 | } 1986 | 1987 | fn push_group_marker_ext(&self, message: &str) { 1988 | if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() { 1989 | unsafe { 1990 | self.ffi_gl_ 1991 | .PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _); 1992 | } 1993 | } 1994 | } 1995 | 1996 | fn pop_group_marker_ext(&self) { 1997 | if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() { 1998 | unsafe { 1999 | self.ffi_gl_.PopGroupMarkerEXT(); 2000 | } 2001 | } 2002 | } 2003 | 2004 | fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) { 2005 | if self.ffi_gl_.DebugMessageInsertKHR.is_loaded() { 2006 | unsafe { 2007 | self.ffi_gl_ 2008 | .DebugMessageInsertKHR(source, type_, id, severity, message.len() as GLsizei, message.as_ptr() as *const _); 2009 | } 2010 | } 2011 | } 2012 | 2013 | fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) { 2014 | if self.ffi_gl_.PushDebugGroupKHR.is_loaded() { 2015 | unsafe { 2016 | self.ffi_gl_ 2017 | .PushDebugGroupKHR(source, id, message.len() as GLsizei, message.as_ptr() as *const _); 2018 | } 2019 | } 2020 | } 2021 | 2022 | fn pop_debug_group_khr(&self) { 2023 | if self.ffi_gl_.PopDebugGroupKHR.is_loaded() { 2024 | unsafe { 2025 | self.ffi_gl_.PopDebugGroupKHR(); 2026 | } 2027 | } 2028 | } 2029 | 2030 | fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync { 2031 | unsafe { self.ffi_gl_.FenceSync(condition, flags) as *const _ } 2032 | } 2033 | 2034 | fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum { 2035 | unsafe { 2036 | self.ffi_gl_ 2037 | .ClientWaitSync(sync as *const _, flags, timeout) 2038 | } 2039 | } 2040 | 2041 | fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) { 2042 | unsafe { 2043 | self.ffi_gl_.WaitSync(sync as *const _, flags, timeout); 2044 | } 2045 | } 2046 | 2047 | fn texture_range_apple(&self, target: GLenum, data: &[u8]) { 2048 | unsafe { 2049 | self.ffi_gl_.TextureRangeAPPLE( 2050 | target, 2051 | data.len() as GLsizei, 2052 | data.as_ptr() as *const c_void, 2053 | ); 2054 | } 2055 | } 2056 | 2057 | fn delete_sync(&self, sync: GLsync) { 2058 | unsafe { 2059 | self.ffi_gl_.DeleteSync(sync as *const _); 2060 | } 2061 | } 2062 | 2063 | fn gen_fences_apple(&self, n: GLsizei) -> Vec { 2064 | let mut result = vec![0 as GLuint; n as usize]; 2065 | unsafe { 2066 | self.ffi_gl_.GenFencesAPPLE(n, result.as_mut_ptr()); 2067 | } 2068 | result 2069 | } 2070 | 2071 | fn delete_fences_apple(&self, fences: &[GLuint]) { 2072 | unsafe { 2073 | self.ffi_gl_ 2074 | .DeleteFencesAPPLE(fences.len() as GLsizei, fences.as_ptr()); 2075 | } 2076 | } 2077 | 2078 | fn set_fence_apple(&self, fence: GLuint) { 2079 | unsafe { 2080 | self.ffi_gl_.SetFenceAPPLE(fence); 2081 | } 2082 | } 2083 | 2084 | fn finish_fence_apple(&self, fence: GLuint) { 2085 | unsafe { 2086 | self.ffi_gl_.FinishFenceAPPLE(fence); 2087 | } 2088 | } 2089 | 2090 | fn test_fence_apple(&self, fence: GLuint) { 2091 | unsafe { 2092 | self.ffi_gl_.TestFenceAPPLE(fence); 2093 | } 2094 | } 2095 | 2096 | fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean { 2097 | unsafe { 2098 | self.ffi_gl_.TestObjectAPPLE(object, name) 2099 | } 2100 | } 2101 | 2102 | fn finish_object_apple(&self, object: GLenum, name: GLuint) { 2103 | unsafe { 2104 | // the spec has a typo for name as GLint instead of GLuint 2105 | self.ffi_gl_.FinishObjectAPPLE(object, name as GLint); 2106 | } 2107 | } 2108 | 2109 | // GL_ARB_blend_func_extended 2110 | fn bind_frag_data_location_indexed( 2111 | &self, 2112 | program: GLuint, 2113 | color_number: GLuint, 2114 | index: GLuint, 2115 | name: &str, 2116 | ) { 2117 | if !self.ffi_gl_.BindFragDataLocationIndexed.is_loaded() { 2118 | return; 2119 | } 2120 | 2121 | let c_string = CString::new(name).unwrap(); 2122 | 2123 | unsafe { 2124 | self.ffi_gl_.BindFragDataLocationIndexed( 2125 | program, 2126 | color_number, 2127 | index, 2128 | c_string.as_ptr(), 2129 | ) 2130 | } 2131 | } 2132 | 2133 | fn get_frag_data_index(&self, program: GLuint, name: &str) -> GLint { 2134 | if !self.ffi_gl_.GetFragDataIndex.is_loaded() { 2135 | return -1; 2136 | } 2137 | 2138 | let c_string = CString::new(name).unwrap(); 2139 | 2140 | unsafe { self.ffi_gl_.GetFragDataIndex(program, c_string.as_ptr()) } 2141 | } 2142 | 2143 | // GL_KHR_debug 2144 | fn get_debug_messages(&self) -> Vec { 2145 | if !self.ffi_gl_.GetDebugMessageLog.is_loaded() { 2146 | return Vec::new(); 2147 | } 2148 | 2149 | let mut max_message_len = 0; 2150 | unsafe { 2151 | self.ffi_gl_ 2152 | .GetIntegerv(ffi::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_len) 2153 | } 2154 | 2155 | let mut output = Vec::new(); 2156 | const CAPACITY: usize = 5; 2157 | 2158 | let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize]; 2159 | let mut sources = [0 as GLenum; CAPACITY]; 2160 | let mut types = [0 as GLenum; CAPACITY]; 2161 | let mut severities = [0 as GLenum; CAPACITY]; 2162 | let mut ids = [0 as GLuint; CAPACITY]; 2163 | let mut lengths = [0 as GLsizei; CAPACITY]; 2164 | 2165 | loop { 2166 | let count = unsafe { 2167 | // ANGLE can return one more message than the count argument specifies, 2168 | // so we deliberately request one less than the capacity of our buffers. 2169 | // https://issues.angleproject.org/issues/425579207 2170 | self.ffi_gl_.GetDebugMessageLog( 2171 | (CAPACITY - 1) as _, 2172 | msg_data.len() as _, 2173 | sources.as_mut_ptr(), 2174 | types.as_mut_ptr(), 2175 | ids.as_mut_ptr(), 2176 | severities.as_mut_ptr(), 2177 | lengths.as_mut_ptr(), 2178 | msg_data.as_mut_ptr() as *mut _, 2179 | ) 2180 | }; 2181 | let count = CAPACITY.min(count as usize); 2182 | 2183 | let mut offset = 0; 2184 | output.extend((0..count).map(|i| { 2185 | let len = lengths[i] as usize; 2186 | let slice = &msg_data[offset..offset + len]; 2187 | offset += len; 2188 | DebugMessage { 2189 | message: String::from_utf8_lossy(slice).to_string(), 2190 | source: sources[i], 2191 | ty: types[i], 2192 | id: ids[i], 2193 | severity: severities[i], 2194 | } 2195 | })); 2196 | 2197 | if (count as usize) < CAPACITY { 2198 | return output; 2199 | } 2200 | } 2201 | } 2202 | 2203 | fn provoking_vertex_angle(&self, _mode: GLenum) { 2204 | unimplemented!("This extension is GLES only"); 2205 | } 2206 | 2207 | // GL_KHR_blend_equation_advanced 2208 | fn blend_barrier_khr(&self) { 2209 | if self.ffi_gl_.BlendBarrierKHR.is_loaded() { 2210 | unsafe { 2211 | self.ffi_gl_.BlendBarrierKHR(); 2212 | } 2213 | } 2214 | } 2215 | 2216 | // GL_CHROMIUM_copy_texture 2217 | fn copy_texture_chromium(&self, 2218 | _source_id: GLuint, _source_level: GLint, 2219 | _dest_target: GLenum, _dest_id: GLuint, _dest_level: GLint, 2220 | _internal_format: GLint, _dest_type: GLenum, 2221 | _unpack_flip_y: GLboolean, _unpack_premultiply_alpha: GLboolean, _unpack_unmultiply_alpha: GLboolean) 2222 | { 2223 | unimplemented!("This extension is GLES only"); 2224 | } 2225 | fn copy_sub_texture_chromium(&self, 2226 | _source_id: GLuint, _source_level: GLint, 2227 | _dest_target: GLenum, _dest_id: GLuint, _dest_level: GLint, 2228 | _x_offset: GLint, _y_offset: GLint, _x: GLint, _y: GLint, _width: GLsizei, _height: GLsizei, 2229 | _unpack_flip_y: GLboolean, _unpack_premultiply_alpha: GLboolean, _unpack_unmultiply_alpha: GLboolean) 2230 | { 2231 | unimplemented!("This extension is GLES only"); 2232 | } 2233 | 2234 | // GL_ANGLE_copy_texture_3d 2235 | fn copy_texture_3d_angle( 2236 | &self, 2237 | _source_id: GLuint, 2238 | _source_level: GLint, 2239 | _dest_target: GLenum, 2240 | _dest_id: GLuint, 2241 | _dest_level: GLint, 2242 | _internal_format: GLint, 2243 | _dest_type: GLenum, 2244 | _unpack_flip_y: GLboolean, 2245 | _unpack_premultiply_alpha: GLboolean, 2246 | _unpack_unmultiply_alpha: GLboolean, 2247 | ) { 2248 | unimplemented!("This extension is ANGLE only"); 2249 | } 2250 | 2251 | fn copy_sub_texture_3d_angle( 2252 | &self, 2253 | _source_id: GLuint, 2254 | _source_level: GLint, 2255 | _dest_target: GLenum, 2256 | _dest_id: GLuint, 2257 | _dest_level: GLint, 2258 | _x_offset: GLint, 2259 | _y_offset: GLint, 2260 | _z_offset: GLint, 2261 | _x: GLint, 2262 | _y: GLint, 2263 | _z: GLint, 2264 | _width: GLsizei, 2265 | _height: GLsizei, 2266 | _depth: GLsizei, 2267 | _unpack_flip_y: GLboolean, 2268 | _unpack_premultiply_alpha: GLboolean, 2269 | _unpack_unmultiply_alpha: GLboolean, 2270 | ) { 2271 | unimplemented!("This extension is ANGLE only"); 2272 | } 2273 | 2274 | fn buffer_storage( 2275 | &self, 2276 | target: GLenum, 2277 | size: GLsizeiptr, 2278 | data: *const GLvoid, 2279 | flags: GLbitfield, 2280 | ) { 2281 | unsafe { 2282 | self.ffi_gl_.BufferStorage(target, size, data, flags); 2283 | } 2284 | } 2285 | 2286 | fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) { 2287 | unsafe { 2288 | self.ffi_gl_.FlushMappedBufferRange(target, offset, length); 2289 | } 2290 | } 2291 | 2292 | fn start_tiling_qcom(&self, _x: GLuint, _y: GLuint, _width: GLuint, _height: GLuint, _preserve_mask: GLbitfield) { 2293 | } 2294 | 2295 | fn end_tiling_qcom(&self, _preserve_mask: GLbitfield) { 2296 | } 2297 | } 2298 | -------------------------------------------------------------------------------- /src/gles_fns.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | pub struct GlesFns { 11 | ffi_gl_: GlesFfi, 12 | } 13 | 14 | impl GlesFns { 15 | pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc 16 | where 17 | F: FnMut(&str) -> *const c_void, 18 | { 19 | let ffi_gl_ = GlesFfi::load_with(loadfn); 20 | Rc::new(GlesFns { ffi_gl_: ffi_gl_ }) as Rc 21 | } 22 | } 23 | 24 | impl Gl for GlesFns { 25 | fn get_type(&self) -> GlType { 26 | GlType::Gles 27 | } 28 | 29 | fn buffer_data_untyped( 30 | &self, 31 | target: GLenum, 32 | size: GLsizeiptr, 33 | data: *const GLvoid, 34 | usage: GLenum, 35 | ) { 36 | unsafe { 37 | self.ffi_gl_.BufferData(target, size, data, usage); 38 | } 39 | } 40 | 41 | fn tex_buffer(&self, _target: GLenum, _internal_format: GLenum, _buffer: GLuint) { 42 | panic!("not supported") 43 | } 44 | 45 | fn buffer_sub_data_untyped( 46 | &self, 47 | target: GLenum, 48 | offset: isize, 49 | size: GLsizeiptr, 50 | data: *const GLvoid, 51 | ) { 52 | unsafe { 53 | self.ffi_gl_.BufferSubData(target, offset, size, data); 54 | } 55 | } 56 | 57 | fn map_buffer(&self, 58 | _target: GLenum, 59 | _access: GLbitfield) -> *mut c_void { 60 | panic!("not supported") 61 | } 62 | 63 | fn map_buffer_range(&self, 64 | target: GLenum, 65 | offset: GLintptr, 66 | length: GLsizeiptr, 67 | access: GLbitfield) -> *mut c_void { 68 | unsafe { 69 | return self.ffi_gl_.MapBufferRange(target, offset, length, access); 70 | } 71 | } 72 | 73 | fn unmap_buffer(&self, target: GLenum) -> GLboolean { 74 | unsafe { 75 | return self.ffi_gl_.UnmapBuffer(target); 76 | } 77 | } 78 | 79 | fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) { 80 | let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect(); 81 | let lengths: Vec = strings.iter().map(|string| string.len() as GLint).collect(); 82 | unsafe { 83 | self.ffi_gl_.ShaderSource( 84 | shader, 85 | pointers.len() as GLsizei, 86 | pointers.as_ptr() as *const *const GLchar, 87 | lengths.as_ptr(), 88 | ); 89 | } 90 | drop(lengths); 91 | drop(pointers); 92 | } 93 | 94 | #[allow(unused_variables)] 95 | fn read_buffer(&self, mode: GLenum) { 96 | panic!("not supported") 97 | } 98 | 99 | fn read_pixels_into_buffer( 100 | &self, 101 | x: GLint, 102 | y: GLint, 103 | width: GLsizei, 104 | height: GLsizei, 105 | format: GLenum, 106 | pixel_type: GLenum, 107 | dst_buffer: &mut [u8], 108 | ) { 109 | // Assumes that the user properly allocated the size for dst_buffer. 110 | let mut row_length = 0; 111 | unsafe { 112 | self.ffi_gl_.GetIntegerv(ffi::PACK_ROW_LENGTH, &mut row_length as _); 113 | } 114 | if row_length == 0 { 115 | row_length = width; 116 | } else { 117 | assert!(row_length >= width); 118 | } 119 | assert_eq!(calculate_length(row_length, height, format, pixel_type), dst_buffer.len()); 120 | 121 | unsafe { 122 | // We don't want any alignment padding on pixel rows. 123 | self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1); 124 | self.ffi_gl_.ReadPixels( 125 | x, 126 | y, 127 | width, 128 | height, 129 | format, 130 | pixel_type, 131 | dst_buffer.as_mut_ptr() as *mut c_void, 132 | ); 133 | } 134 | } 135 | 136 | fn read_pixels( 137 | &self, 138 | x: GLint, 139 | y: GLint, 140 | width: GLsizei, 141 | height: GLsizei, 142 | format: GLenum, 143 | pixel_type: GLenum, 144 | ) -> Vec { 145 | let len = calculate_length(width, height, format, pixel_type); 146 | let mut pixels: Vec = Vec::new(); 147 | pixels.reserve(len); 148 | unsafe { 149 | pixels.set_len(len); 150 | } 151 | 152 | self.read_pixels_into_buffer( 153 | x, 154 | y, 155 | width, 156 | height, 157 | format, 158 | pixel_type, 159 | pixels.as_mut_slice(), 160 | ); 161 | 162 | pixels 163 | } 164 | 165 | unsafe fn read_pixels_into_pbo(&self, 166 | x: GLint, 167 | y: GLint, 168 | width: GLsizei, 169 | height: GLsizei, 170 | format: GLenum, 171 | pixel_type: GLenum) { 172 | self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, ptr::null_mut()); 173 | } 174 | 175 | fn sample_coverage(&self, value: GLclampf, invert: bool) { 176 | unsafe { 177 | self.ffi_gl_.SampleCoverage(value, invert as GLboolean); 178 | } 179 | } 180 | 181 | fn polygon_offset(&self, factor: GLfloat, units: GLfloat) { 182 | unsafe { 183 | self.ffi_gl_.PolygonOffset(factor, units); 184 | } 185 | } 186 | 187 | fn pixel_store_i(&self, name: GLenum, param: GLint) { 188 | unsafe { 189 | self.ffi_gl_.PixelStorei(name, param); 190 | } 191 | } 192 | 193 | fn gen_buffers(&self, n: GLsizei) -> Vec { 194 | let mut result = vec![0 as GLuint; n as usize]; 195 | unsafe { 196 | self.ffi_gl_.GenBuffers(n, result.as_mut_ptr()); 197 | } 198 | result 199 | } 200 | 201 | fn gen_renderbuffers(&self, n: GLsizei) -> Vec { 202 | let mut result = vec![0 as GLuint; n as usize]; 203 | unsafe { 204 | self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr()); 205 | } 206 | result 207 | } 208 | 209 | fn gen_framebuffers(&self, n: GLsizei) -> Vec { 210 | let mut result = vec![0 as GLuint; n as usize]; 211 | unsafe { 212 | self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr()); 213 | } 214 | result 215 | } 216 | 217 | fn gen_textures(&self, n: GLsizei) -> Vec { 218 | let mut result = vec![0 as GLuint; n as usize]; 219 | unsafe { 220 | self.ffi_gl_.GenTextures(n, result.as_mut_ptr()); 221 | } 222 | result 223 | } 224 | 225 | fn gen_vertex_arrays(&self, n: GLsizei) -> Vec { 226 | let mut result = vec![0 as GLuint; n as usize]; 227 | unsafe { 228 | self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr()); 229 | } 230 | result 231 | } 232 | 233 | fn gen_vertex_arrays_apple(&self, _n: GLsizei) -> Vec { 234 | panic!("not supported") 235 | } 236 | 237 | fn gen_queries(&self, n: GLsizei) -> Vec { 238 | if !self.ffi_gl_.GenQueriesEXT.is_loaded() { 239 | return Vec::new(); 240 | } 241 | let mut result = vec![0 as GLuint; n as usize]; 242 | unsafe { 243 | self.ffi_gl_.GenQueriesEXT(n, result.as_mut_ptr()); 244 | } 245 | result 246 | } 247 | 248 | fn begin_query(&self, target: GLenum, id: GLuint) { 249 | if !self.ffi_gl_.BeginQueryEXT.is_loaded() { 250 | return; 251 | } 252 | unsafe { 253 | self.ffi_gl_.BeginQueryEXT(target, id); 254 | } 255 | } 256 | 257 | fn end_query(&self, target: GLenum) { 258 | if !self.ffi_gl_.EndQueryEXT.is_loaded() { 259 | return; 260 | } 261 | unsafe { 262 | self.ffi_gl_.EndQueryEXT(target); 263 | } 264 | } 265 | 266 | fn query_counter(&self, id: GLuint, target: GLenum) { 267 | if !self.ffi_gl_.QueryCounterEXT.is_loaded() { 268 | return; 269 | } 270 | unsafe { 271 | self.ffi_gl_.QueryCounterEXT(id, target); 272 | } 273 | } 274 | 275 | fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 { 276 | if !self.ffi_gl_.GetQueryObjectivEXT.is_loaded() { 277 | return 0; 278 | } 279 | let mut result = 0; 280 | unsafe { 281 | self.ffi_gl_.GetQueryObjectivEXT(id, pname, &mut result); 282 | } 283 | result 284 | } 285 | 286 | fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 { 287 | if !self.ffi_gl_.GetQueryObjectuivEXT.is_loaded() { 288 | return 0; 289 | } 290 | let mut result = 0; 291 | unsafe { 292 | self.ffi_gl_.GetQueryObjectuivEXT(id, pname, &mut result); 293 | } 294 | result 295 | } 296 | 297 | fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 { 298 | if !self.ffi_gl_.GetQueryObjecti64vEXT.is_loaded() { 299 | return 0; 300 | } 301 | let mut result = 0; 302 | unsafe { 303 | self.ffi_gl_.GetQueryObjecti64vEXT(id, pname, &mut result); 304 | } 305 | result 306 | } 307 | 308 | fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 { 309 | if !self.ffi_gl_.GetQueryObjectui64vEXT.is_loaded() { 310 | return 0; 311 | } 312 | let mut result = 0; 313 | unsafe { 314 | self.ffi_gl_.GetQueryObjectui64vEXT(id, pname, &mut result); 315 | } 316 | result 317 | } 318 | 319 | fn delete_queries(&self, queries: &[GLuint]) { 320 | if !self.ffi_gl_.DeleteQueriesEXT.is_loaded() { 321 | return; 322 | } 323 | unsafe { 324 | self.ffi_gl_ 325 | .DeleteQueriesEXT(queries.len() as GLsizei, queries.as_ptr()); 326 | } 327 | } 328 | 329 | fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) { 330 | unsafe { 331 | self.ffi_gl_ 332 | .DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr()); 333 | } 334 | } 335 | 336 | fn delete_vertex_arrays_apple(&self, _vertex_arrays: &[GLuint]) { 337 | panic!("not supported") 338 | } 339 | 340 | fn delete_buffers(&self, buffers: &[GLuint]) { 341 | unsafe { 342 | self.ffi_gl_ 343 | .DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr()); 344 | } 345 | } 346 | 347 | fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) { 348 | unsafe { 349 | self.ffi_gl_ 350 | .DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr()); 351 | } 352 | } 353 | 354 | fn delete_framebuffers(&self, framebuffers: &[GLuint]) { 355 | unsafe { 356 | self.ffi_gl_ 357 | .DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr()); 358 | } 359 | } 360 | 361 | fn delete_textures(&self, textures: &[GLuint]) { 362 | unsafe { 363 | self.ffi_gl_ 364 | .DeleteTextures(textures.len() as GLsizei, textures.as_ptr()); 365 | } 366 | } 367 | 368 | fn framebuffer_renderbuffer( 369 | &self, 370 | target: GLenum, 371 | attachment: GLenum, 372 | renderbuffertarget: GLenum, 373 | renderbuffer: GLuint, 374 | ) { 375 | unsafe { 376 | self.ffi_gl_.FramebufferRenderbuffer( 377 | target, 378 | attachment, 379 | renderbuffertarget, 380 | renderbuffer, 381 | ); 382 | } 383 | } 384 | 385 | fn renderbuffer_storage( 386 | &self, 387 | target: GLenum, 388 | internalformat: GLenum, 389 | width: GLsizei, 390 | height: GLsizei, 391 | ) { 392 | unsafe { 393 | self.ffi_gl_ 394 | .RenderbufferStorage(target, internalformat, width, height); 395 | } 396 | } 397 | 398 | fn depth_func(&self, func: GLenum) { 399 | unsafe { 400 | self.ffi_gl_.DepthFunc(func); 401 | } 402 | } 403 | 404 | fn active_texture(&self, texture: GLenum) { 405 | unsafe { 406 | self.ffi_gl_.ActiveTexture(texture); 407 | } 408 | } 409 | 410 | fn attach_shader(&self, program: GLuint, shader: GLuint) { 411 | unsafe { 412 | self.ffi_gl_.AttachShader(program, shader); 413 | } 414 | } 415 | 416 | fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) { 417 | let c_string = CString::new(name).unwrap(); 418 | unsafe { 419 | self.ffi_gl_ 420 | .BindAttribLocation(program, index, c_string.as_ptr()) 421 | } 422 | } 423 | 424 | // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml 425 | unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) { 426 | assert!(!result.is_empty()); 427 | self.ffi_gl_ 428 | .GetUniformiv(program, location, result.as_mut_ptr()); 429 | } 430 | 431 | // https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetUniform.xml 432 | unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) { 433 | assert!(!result.is_empty()); 434 | self.ffi_gl_ 435 | .GetUniformfv(program, location, result.as_mut_ptr()); 436 | } 437 | 438 | fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { 439 | let c_string = CString::new(name).unwrap(); 440 | unsafe { 441 | self.ffi_gl_ 442 | .GetUniformBlockIndex(program, c_string.as_ptr()) 443 | } 444 | } 445 | 446 | fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec { 447 | let c_strings: Vec = names.iter().map(|n| CString::new(*n).unwrap()).collect(); 448 | let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect(); 449 | let mut result = Vec::with_capacity(c_strings.len()); 450 | unsafe { 451 | result.set_len(c_strings.len()); 452 | self.ffi_gl_.GetUniformIndices( 453 | program, 454 | pointers.len() as GLsizei, 455 | pointers.as_ptr(), 456 | result.as_mut_ptr(), 457 | ); 458 | } 459 | result 460 | } 461 | 462 | fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) { 463 | unsafe { 464 | self.ffi_gl_.BindBufferBase(target, index, buffer); 465 | } 466 | } 467 | 468 | fn bind_buffer_range( 469 | &self, 470 | target: GLenum, 471 | index: GLuint, 472 | buffer: GLuint, 473 | offset: GLintptr, 474 | size: GLsizeiptr, 475 | ) { 476 | unsafe { 477 | self.ffi_gl_ 478 | .BindBufferRange(target, index, buffer, offset, size); 479 | } 480 | } 481 | 482 | fn uniform_block_binding( 483 | &self, 484 | program: GLuint, 485 | uniform_block_index: GLuint, 486 | uniform_block_binding: GLuint, 487 | ) { 488 | unsafe { 489 | self.ffi_gl_ 490 | .UniformBlockBinding(program, uniform_block_index, uniform_block_binding); 491 | } 492 | } 493 | 494 | fn bind_buffer(&self, target: GLenum, buffer: GLuint) { 495 | unsafe { 496 | self.ffi_gl_.BindBuffer(target, buffer); 497 | } 498 | } 499 | 500 | fn bind_vertex_array(&self, vao: GLuint) { 501 | unsafe { 502 | self.ffi_gl_.BindVertexArray(vao); 503 | } 504 | } 505 | 506 | fn bind_vertex_array_apple(&self, _vao: GLuint) { 507 | panic!("not supported") 508 | } 509 | 510 | fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) { 511 | unsafe { 512 | self.ffi_gl_.BindRenderbuffer(target, renderbuffer); 513 | } 514 | } 515 | 516 | fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) { 517 | unsafe { 518 | self.ffi_gl_.BindFramebuffer(target, framebuffer); 519 | } 520 | } 521 | 522 | fn bind_texture(&self, target: GLenum, texture: GLuint) { 523 | unsafe { 524 | self.ffi_gl_.BindTexture(target, texture); 525 | } 526 | } 527 | 528 | fn bind_vertex_buffer(&self, binding_index: GLuint, buffer: GLuint, offset: GLintptr, stride: GLint) { 529 | unsafe { self.ffi_gl_.BindVertexBuffer(binding_index, buffer, offset, stride) } 530 | } 531 | 532 | fn draw_buffers(&self, bufs: &[GLenum]) { 533 | unsafe { 534 | self.ffi_gl_ 535 | .DrawBuffers(bufs.len() as GLsizei, bufs.as_ptr()); 536 | } 537 | } 538 | 539 | // FIXME: Does not verify buffer size -- unsafe! 540 | fn tex_image_2d( 541 | &self, 542 | target: GLenum, 543 | level: GLint, 544 | internal_format: GLint, 545 | width: GLsizei, 546 | height: GLsizei, 547 | border: GLint, 548 | format: GLenum, 549 | ty: GLenum, 550 | opt_data: Option<&[u8]>, 551 | ) { 552 | match opt_data { 553 | Some(data) => unsafe { 554 | self.ffi_gl_.TexImage2D( 555 | target, 556 | level, 557 | internal_format, 558 | width, 559 | height, 560 | border, 561 | format, 562 | ty, 563 | data.as_ptr() as *const GLvoid, 564 | ); 565 | }, 566 | None => unsafe { 567 | self.ffi_gl_.TexImage2D( 568 | target, 569 | level, 570 | internal_format, 571 | width, 572 | height, 573 | border, 574 | format, 575 | ty, 576 | ptr::null(), 577 | ); 578 | }, 579 | } 580 | } 581 | 582 | fn compressed_tex_image_2d( 583 | &self, 584 | target: GLenum, 585 | level: GLint, 586 | internal_format: GLenum, 587 | width: GLsizei, 588 | height: GLsizei, 589 | border: GLint, 590 | data: &[u8], 591 | ) { 592 | unsafe { 593 | self.ffi_gl_.CompressedTexImage2D( 594 | target, 595 | level, 596 | internal_format, 597 | width, 598 | height, 599 | border, 600 | data.len() as GLsizei, 601 | data.as_ptr() as *const GLvoid, 602 | ); 603 | } 604 | } 605 | 606 | fn compressed_tex_sub_image_2d( 607 | &self, 608 | target: GLenum, 609 | level: GLint, 610 | xoffset: GLint, 611 | yoffset: GLint, 612 | width: GLsizei, 613 | height: GLsizei, 614 | format: GLenum, 615 | data: &[u8], 616 | ) { 617 | unsafe { 618 | self.ffi_gl_.CompressedTexSubImage2D( 619 | target, 620 | level, 621 | xoffset, 622 | yoffset, 623 | width, 624 | height, 625 | format, 626 | data.len() as GLsizei, 627 | data.as_ptr() as *const GLvoid, 628 | ); 629 | } 630 | } 631 | 632 | // FIXME: Does not verify buffer size -- unsafe! 633 | fn tex_image_3d( 634 | &self, 635 | target: GLenum, 636 | level: GLint, 637 | internal_format: GLint, 638 | width: GLsizei, 639 | height: GLsizei, 640 | depth: GLsizei, 641 | border: GLint, 642 | format: GLenum, 643 | ty: GLenum, 644 | opt_data: Option<&[u8]>, 645 | ) { 646 | unsafe { 647 | let pdata = match opt_data { 648 | Some(data) => mem::transmute(data.as_ptr()), 649 | None => ptr::null(), 650 | }; 651 | self.ffi_gl_.TexImage3D( 652 | target, 653 | level, 654 | internal_format, 655 | width, 656 | height, 657 | depth, 658 | border, 659 | format, 660 | ty, 661 | pdata, 662 | ); 663 | } 664 | } 665 | 666 | fn copy_tex_image_2d( 667 | &self, 668 | target: GLenum, 669 | level: GLint, 670 | internal_format: GLenum, 671 | x: GLint, 672 | y: GLint, 673 | width: GLsizei, 674 | height: GLsizei, 675 | border: GLint, 676 | ) { 677 | unsafe { 678 | self.ffi_gl_.CopyTexImage2D( 679 | target, 680 | level, 681 | internal_format, 682 | x, 683 | y, 684 | width, 685 | height, 686 | border, 687 | ); 688 | } 689 | } 690 | 691 | fn copy_tex_sub_image_2d( 692 | &self, 693 | target: GLenum, 694 | level: GLint, 695 | xoffset: GLint, 696 | yoffset: GLint, 697 | x: GLint, 698 | y: GLint, 699 | width: GLsizei, 700 | height: GLsizei, 701 | ) { 702 | unsafe { 703 | self.ffi_gl_ 704 | .CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); 705 | } 706 | } 707 | 708 | fn copy_tex_sub_image_3d( 709 | &self, 710 | target: GLenum, 711 | level: GLint, 712 | xoffset: GLint, 713 | yoffset: GLint, 714 | zoffset: GLint, 715 | x: GLint, 716 | y: GLint, 717 | width: GLsizei, 718 | height: GLsizei, 719 | ) { 720 | unsafe { 721 | self.ffi_gl_.CopyTexSubImage3D( 722 | target, level, xoffset, yoffset, zoffset, x, y, width, height, 723 | ); 724 | } 725 | } 726 | 727 | fn tex_sub_image_2d( 728 | &self, 729 | target: GLenum, 730 | level: GLint, 731 | xoffset: GLint, 732 | yoffset: GLint, 733 | width: GLsizei, 734 | height: GLsizei, 735 | format: GLenum, 736 | ty: GLenum, 737 | data: &[u8], 738 | ) { 739 | unsafe { 740 | self.ffi_gl_.TexSubImage2D( 741 | target, 742 | level, 743 | xoffset, 744 | yoffset, 745 | width, 746 | height, 747 | format, 748 | ty, 749 | data.as_ptr() as *const c_void, 750 | ); 751 | } 752 | } 753 | 754 | fn tex_sub_image_2d_pbo( 755 | &self, 756 | target: GLenum, 757 | level: GLint, 758 | xoffset: GLint, 759 | yoffset: GLint, 760 | width: GLsizei, 761 | height: GLsizei, 762 | format: GLenum, 763 | ty: GLenum, 764 | offset: usize, 765 | ) { 766 | unsafe { 767 | self.ffi_gl_.TexSubImage2D( 768 | target, 769 | level, 770 | xoffset, 771 | yoffset, 772 | width, 773 | height, 774 | format, 775 | ty, 776 | offset as *const c_void, 777 | ); 778 | } 779 | } 780 | 781 | fn tex_sub_image_3d( 782 | &self, 783 | target: GLenum, 784 | level: GLint, 785 | xoffset: GLint, 786 | yoffset: GLint, 787 | zoffset: GLint, 788 | width: GLsizei, 789 | height: GLsizei, 790 | depth: GLsizei, 791 | format: GLenum, 792 | ty: GLenum, 793 | data: &[u8], 794 | ) { 795 | unsafe { 796 | self.ffi_gl_.TexSubImage3D( 797 | target, 798 | level, 799 | xoffset, 800 | yoffset, 801 | zoffset, 802 | width, 803 | height, 804 | depth, 805 | format, 806 | ty, 807 | data.as_ptr() as *const c_void, 808 | ); 809 | } 810 | } 811 | 812 | fn tex_sub_image_3d_pbo( 813 | &self, 814 | target: GLenum, 815 | level: GLint, 816 | xoffset: GLint, 817 | yoffset: GLint, 818 | zoffset: GLint, 819 | width: GLsizei, 820 | height: GLsizei, 821 | depth: GLsizei, 822 | format: GLenum, 823 | ty: GLenum, 824 | offset: usize, 825 | ) { 826 | unsafe { 827 | self.ffi_gl_.TexSubImage3D( 828 | target, 829 | level, 830 | xoffset, 831 | yoffset, 832 | zoffset, 833 | width, 834 | height, 835 | depth, 836 | format, 837 | ty, 838 | offset as *const c_void, 839 | ); 840 | } 841 | } 842 | 843 | fn tex_storage_2d( 844 | &self, 845 | target: GLenum, 846 | levels: GLint, 847 | internal_format: GLenum, 848 | width: GLsizei, 849 | height: GLsizei, 850 | ) { 851 | unsafe { 852 | self.ffi_gl_ 853 | .TexStorage2D(target, levels, internal_format, width, height); 854 | } 855 | } 856 | 857 | fn tex_storage_3d( 858 | &self, 859 | target: GLenum, 860 | levels: GLint, 861 | internal_format: GLenum, 862 | width: GLsizei, 863 | height: GLsizei, 864 | depth: GLsizei, 865 | ) { 866 | unsafe { 867 | self.ffi_gl_ 868 | .TexStorage3D(target, levels, internal_format, width, height, depth); 869 | } 870 | } 871 | 872 | #[allow(unused_variables)] 873 | fn get_tex_image_into_buffer( 874 | &self, 875 | target: GLenum, 876 | level: GLint, 877 | format: GLenum, 878 | ty: GLenum, 879 | output: &mut [u8], 880 | ) { 881 | panic!("not supported"); 882 | } 883 | 884 | unsafe fn copy_image_sub_data( 885 | &self, 886 | src_name: GLuint, 887 | src_target: GLenum, 888 | src_level: GLint, 889 | src_x: GLint, 890 | src_y: GLint, 891 | src_z: GLint, 892 | dst_name: GLuint, 893 | dst_target: GLenum, 894 | dst_level: GLint, 895 | dst_x: GLint, 896 | dst_y: GLint, 897 | dst_z: GLint, 898 | src_width: GLsizei, 899 | src_height: GLsizei, 900 | src_depth: GLsizei, 901 | ) { 902 | self.ffi_gl_.CopyImageSubDataEXT( 903 | src_name, src_target, src_level, src_x, src_y, src_z, dst_name, dst_target, dst_level, 904 | dst_x, dst_y, dst_z, src_width, src_height, src_depth, 905 | ); 906 | } 907 | 908 | fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) { 909 | unsafe { 910 | self.ffi_gl_.InvalidateFramebuffer( 911 | target, 912 | attachments.len() as GLsizei, 913 | attachments.as_ptr(), 914 | ); 915 | } 916 | } 917 | 918 | fn invalidate_sub_framebuffer( 919 | &self, 920 | target: GLenum, 921 | attachments: &[GLenum], 922 | xoffset: GLint, 923 | yoffset: GLint, 924 | width: GLsizei, 925 | height: GLsizei, 926 | ) { 927 | unsafe { 928 | self.ffi_gl_.InvalidateSubFramebuffer( 929 | target, 930 | attachments.len() as GLsizei, 931 | attachments.as_ptr(), 932 | xoffset, 933 | yoffset, 934 | width, 935 | height, 936 | ); 937 | } 938 | } 939 | 940 | #[inline] 941 | unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) { 942 | assert!(!result.is_empty()); 943 | self.ffi_gl_.GetIntegerv(name, result.as_mut_ptr()); 944 | } 945 | 946 | #[inline] 947 | unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) { 948 | assert!(!result.is_empty()); 949 | self.ffi_gl_.GetInteger64v(name, result.as_mut_ptr()); 950 | } 951 | 952 | #[inline] 953 | unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) { 954 | assert!(!result.is_empty()); 955 | self.ffi_gl_.GetIntegeri_v(name, index, result.as_mut_ptr()); 956 | } 957 | 958 | #[inline] 959 | unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) { 960 | assert!(!result.is_empty()); 961 | self.ffi_gl_ 962 | .GetInteger64i_v(name, index, result.as_mut_ptr()); 963 | } 964 | 965 | #[inline] 966 | unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) { 967 | assert!(!result.is_empty()); 968 | self.ffi_gl_.GetBooleanv(name, result.as_mut_ptr()); 969 | } 970 | 971 | #[inline] 972 | unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) { 973 | assert!(!result.is_empty()); 974 | self.ffi_gl_.GetFloatv(name, result.as_mut_ptr()); 975 | } 976 | 977 | fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint { 978 | let mut result: GLint = 0; 979 | unsafe { 980 | self.ffi_gl_ 981 | .GetRenderbufferParameteriv(target, pname, &mut result); 982 | } 983 | result 984 | } 985 | 986 | fn get_framebuffer_attachment_parameter_iv( 987 | &self, 988 | target: GLenum, 989 | attachment: GLenum, 990 | pname: GLenum, 991 | ) -> GLint { 992 | let mut result: GLint = 0; 993 | unsafe { 994 | self.ffi_gl_.GetFramebufferAttachmentParameteriv( 995 | target, 996 | attachment, 997 | pname, 998 | &mut result, 999 | ); 1000 | } 1001 | result 1002 | } 1003 | 1004 | fn get_tex_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint { 1005 | let mut result: GLint = 0; 1006 | unsafe { 1007 | self.ffi_gl_.GetTexParameteriv(target, pname, &mut result); 1008 | } 1009 | result 1010 | } 1011 | 1012 | fn get_tex_parameter_fv(&self, target: GLenum, pname: GLenum) -> GLfloat { 1013 | let mut result: GLfloat = 0.0; 1014 | unsafe { 1015 | self.ffi_gl_.GetTexParameterfv(target, pname, &mut result); 1016 | } 1017 | result 1018 | } 1019 | 1020 | fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) { 1021 | unsafe { 1022 | self.ffi_gl_.TexParameteri(target, pname, param); 1023 | } 1024 | } 1025 | 1026 | fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) { 1027 | unsafe { 1028 | self.ffi_gl_.TexParameterf(target, pname, param); 1029 | } 1030 | } 1031 | 1032 | fn framebuffer_texture_2d( 1033 | &self, 1034 | target: GLenum, 1035 | attachment: GLenum, 1036 | textarget: GLenum, 1037 | texture: GLuint, 1038 | level: GLint, 1039 | ) { 1040 | unsafe { 1041 | self.ffi_gl_ 1042 | .FramebufferTexture2D(target, attachment, textarget, texture, level); 1043 | } 1044 | } 1045 | 1046 | fn framebuffer_texture_layer( 1047 | &self, 1048 | target: GLenum, 1049 | attachment: GLenum, 1050 | texture: GLuint, 1051 | level: GLint, 1052 | layer: GLint, 1053 | ) { 1054 | unsafe { 1055 | self.ffi_gl_ 1056 | .FramebufferTextureLayer(target, attachment, texture, level, layer); 1057 | } 1058 | } 1059 | 1060 | fn blit_framebuffer( 1061 | &self, 1062 | src_x0: GLint, 1063 | src_y0: GLint, 1064 | src_x1: GLint, 1065 | src_y1: GLint, 1066 | dst_x0: GLint, 1067 | dst_y0: GLint, 1068 | dst_x1: GLint, 1069 | dst_y1: GLint, 1070 | mask: GLbitfield, 1071 | filter: GLenum, 1072 | ) { 1073 | unsafe { 1074 | self.ffi_gl_.BlitFramebuffer( 1075 | src_x0, src_y0, src_x1, src_y1, dst_x0, dst_y0, dst_x1, dst_y1, mask, filter, 1076 | ); 1077 | } 1078 | } 1079 | 1080 | fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) { 1081 | unsafe { self.ffi_gl_.VertexAttrib4f(index, x, y, z, w) } 1082 | } 1083 | 1084 | fn vertex_attrib_binding(&self, attrib_index: GLuint, binding_index: GLuint) { 1085 | unsafe { self.ffi_gl_.VertexAttribBinding(attrib_index, binding_index) } 1086 | } 1087 | 1088 | fn vertex_attrib_pointer_f32( 1089 | &self, 1090 | index: GLuint, 1091 | size: GLint, 1092 | normalized: bool, 1093 | stride: GLsizei, 1094 | offset: GLuint, 1095 | ) { 1096 | unsafe { 1097 | self.ffi_gl_.VertexAttribPointer( 1098 | index, 1099 | size, 1100 | ffi::FLOAT, 1101 | normalized as GLboolean, 1102 | stride, 1103 | offset as *const GLvoid, 1104 | ) 1105 | } 1106 | } 1107 | 1108 | fn vertex_attrib_pointer( 1109 | &self, 1110 | index: GLuint, 1111 | size: GLint, 1112 | type_: GLenum, 1113 | normalized: bool, 1114 | stride: GLsizei, 1115 | offset: GLuint, 1116 | ) { 1117 | unsafe { 1118 | self.ffi_gl_.VertexAttribPointer( 1119 | index, 1120 | size, 1121 | type_, 1122 | normalized as GLboolean, 1123 | stride, 1124 | offset as *const GLvoid, 1125 | ) 1126 | } 1127 | } 1128 | 1129 | fn vertex_attrib_i_pointer( 1130 | &self, 1131 | index: GLuint, 1132 | size: GLint, 1133 | type_: GLenum, 1134 | stride: GLsizei, 1135 | offset: GLuint, 1136 | ) { 1137 | unsafe { 1138 | self.ffi_gl_ 1139 | .VertexAttribIPointer(index, size, type_, stride, offset as *const GLvoid) 1140 | } 1141 | } 1142 | 1143 | fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) { 1144 | unsafe { self.ffi_gl_.VertexAttribDivisor(index, divisor) } 1145 | } 1146 | 1147 | fn vertex_attrib_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, normalized: bool, relative_offset: GLuint) { 1148 | unsafe { self.ffi_gl_.VertexAttribFormat(attrib_index, size, type_, normalized as GLboolean, relative_offset) } 1149 | } 1150 | 1151 | fn vertex_attrib_i_format(&self, attrib_index: GLuint, size: GLint, type_: GLenum, relative_offset: GLuint) { 1152 | unsafe { self.ffi_gl_.VertexAttribIFormat(attrib_index, size, type_, relative_offset) } 1153 | } 1154 | 1155 | fn vertex_binding_divisor(&self, binding_index: GLuint, divisor: GLuint) { 1156 | unsafe { self.ffi_gl_.VertexBindingDivisor(binding_index, divisor) } 1157 | } 1158 | 1159 | fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) { 1160 | unsafe { 1161 | self.ffi_gl_.Viewport(x, y, width, height); 1162 | } 1163 | } 1164 | 1165 | fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) { 1166 | unsafe { 1167 | self.ffi_gl_.Scissor(x, y, width, height); 1168 | } 1169 | } 1170 | 1171 | fn line_width(&self, width: GLfloat) { 1172 | unsafe { 1173 | self.ffi_gl_.LineWidth(width); 1174 | } 1175 | } 1176 | 1177 | fn use_program(&self, program: GLuint) { 1178 | unsafe { 1179 | self.ffi_gl_.UseProgram(program); 1180 | } 1181 | } 1182 | 1183 | fn validate_program(&self, program: GLuint) { 1184 | unsafe { 1185 | self.ffi_gl_.ValidateProgram(program); 1186 | } 1187 | } 1188 | 1189 | fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) { 1190 | unsafe { 1191 | return self.ffi_gl_.DrawArrays(mode, first, count); 1192 | } 1193 | } 1194 | 1195 | fn draw_arrays_instanced( 1196 | &self, 1197 | mode: GLenum, 1198 | first: GLint, 1199 | count: GLsizei, 1200 | primcount: GLsizei, 1201 | ) { 1202 | unsafe { 1203 | return self 1204 | .ffi_gl_ 1205 | .DrawArraysInstanced(mode, first, count, primcount); 1206 | } 1207 | } 1208 | 1209 | fn draw_elements( 1210 | &self, 1211 | mode: GLenum, 1212 | count: GLsizei, 1213 | element_type: GLenum, 1214 | indices_offset: GLuint, 1215 | ) { 1216 | unsafe { 1217 | return self.ffi_gl_.DrawElements( 1218 | mode, 1219 | count, 1220 | element_type, 1221 | indices_offset as *const c_void, 1222 | ); 1223 | } 1224 | } 1225 | 1226 | fn draw_elements_instanced( 1227 | &self, 1228 | mode: GLenum, 1229 | count: GLsizei, 1230 | element_type: GLenum, 1231 | indices_offset: GLuint, 1232 | primcount: GLsizei, 1233 | ) { 1234 | unsafe { 1235 | return self.ffi_gl_.DrawElementsInstanced( 1236 | mode, 1237 | count, 1238 | element_type, 1239 | indices_offset as *const c_void, 1240 | primcount, 1241 | ); 1242 | } 1243 | } 1244 | 1245 | fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) { 1246 | unsafe { 1247 | self.ffi_gl_.BlendColor(r, g, b, a); 1248 | } 1249 | } 1250 | 1251 | fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) { 1252 | unsafe { 1253 | self.ffi_gl_.BlendFunc(sfactor, dfactor); 1254 | } 1255 | } 1256 | 1257 | fn blend_func_separate( 1258 | &self, 1259 | src_rgb: GLenum, 1260 | dest_rgb: GLenum, 1261 | src_alpha: GLenum, 1262 | dest_alpha: GLenum, 1263 | ) { 1264 | unsafe { 1265 | self.ffi_gl_ 1266 | .BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha); 1267 | } 1268 | } 1269 | 1270 | fn blend_equation(&self, mode: GLenum) { 1271 | unsafe { 1272 | self.ffi_gl_.BlendEquation(mode); 1273 | } 1274 | } 1275 | 1276 | fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) { 1277 | unsafe { 1278 | self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha); 1279 | } 1280 | } 1281 | 1282 | fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) { 1283 | unsafe { 1284 | self.ffi_gl_.ColorMask( 1285 | r as GLboolean, 1286 | g as GLboolean, 1287 | b as GLboolean, 1288 | a as GLboolean, 1289 | ); 1290 | } 1291 | } 1292 | 1293 | fn cull_face(&self, mode: GLenum) { 1294 | unsafe { 1295 | self.ffi_gl_.CullFace(mode); 1296 | } 1297 | } 1298 | 1299 | fn front_face(&self, mode: GLenum) { 1300 | unsafe { 1301 | self.ffi_gl_.FrontFace(mode); 1302 | } 1303 | } 1304 | 1305 | fn enable(&self, cap: GLenum) { 1306 | unsafe { 1307 | self.ffi_gl_.Enable(cap); 1308 | } 1309 | } 1310 | 1311 | fn disable(&self, cap: GLenum) { 1312 | unsafe { 1313 | self.ffi_gl_.Disable(cap); 1314 | } 1315 | } 1316 | 1317 | fn hint(&self, param_name: GLenum, param_val: GLenum) { 1318 | unsafe { 1319 | self.ffi_gl_.Hint(param_name, param_val); 1320 | } 1321 | } 1322 | 1323 | fn is_enabled(&self, cap: GLenum) -> GLboolean { 1324 | unsafe { self.ffi_gl_.IsEnabled(cap) } 1325 | } 1326 | 1327 | fn is_shader(&self, shader: GLuint) -> GLboolean { 1328 | unsafe { self.ffi_gl_.IsShader(shader) } 1329 | } 1330 | 1331 | fn is_texture(&self, texture: GLenum) -> GLboolean { 1332 | unsafe { self.ffi_gl_.IsTexture(texture) } 1333 | } 1334 | 1335 | fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean { 1336 | unsafe { self.ffi_gl_.IsFramebuffer(framebuffer) } 1337 | } 1338 | 1339 | fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean { 1340 | unsafe { self.ffi_gl_.IsRenderbuffer(renderbuffer) } 1341 | } 1342 | 1343 | fn check_frame_buffer_status(&self, target: GLenum) -> GLenum { 1344 | unsafe { self.ffi_gl_.CheckFramebufferStatus(target) } 1345 | } 1346 | 1347 | fn enable_vertex_attrib_array(&self, index: GLuint) { 1348 | unsafe { 1349 | self.ffi_gl_.EnableVertexAttribArray(index); 1350 | } 1351 | } 1352 | 1353 | fn disable_vertex_attrib_array(&self, index: GLuint) { 1354 | unsafe { 1355 | self.ffi_gl_.DisableVertexAttribArray(index); 1356 | } 1357 | } 1358 | 1359 | fn uniform_1f(&self, location: GLint, v0: GLfloat) { 1360 | unsafe { 1361 | self.ffi_gl_.Uniform1f(location, v0); 1362 | } 1363 | } 1364 | 1365 | fn uniform_1fv(&self, location: GLint, values: &[f32]) { 1366 | unsafe { 1367 | self.ffi_gl_ 1368 | .Uniform1fv(location, values.len() as GLsizei, values.as_ptr()); 1369 | } 1370 | } 1371 | 1372 | fn uniform_1i(&self, location: GLint, v0: GLint) { 1373 | unsafe { 1374 | self.ffi_gl_.Uniform1i(location, v0); 1375 | } 1376 | } 1377 | 1378 | fn uniform_1iv(&self, location: GLint, values: &[i32]) { 1379 | unsafe { 1380 | self.ffi_gl_ 1381 | .Uniform1iv(location, values.len() as GLsizei, values.as_ptr()); 1382 | } 1383 | } 1384 | 1385 | #[allow(unused_variables)] 1386 | fn uniform_1ui(&self, location: GLint, v0: GLuint) { 1387 | panic!("not supported") 1388 | } 1389 | 1390 | fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) { 1391 | unsafe { 1392 | self.ffi_gl_.Uniform2f(location, v0, v1); 1393 | } 1394 | } 1395 | 1396 | fn uniform_2fv(&self, location: GLint, values: &[f32]) { 1397 | unsafe { 1398 | self.ffi_gl_ 1399 | .Uniform2fv(location, (values.len() / 2) as GLsizei, values.as_ptr()); 1400 | } 1401 | } 1402 | 1403 | fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) { 1404 | unsafe { 1405 | self.ffi_gl_.Uniform2i(location, v0, v1); 1406 | } 1407 | } 1408 | 1409 | fn uniform_2iv(&self, location: GLint, values: &[i32]) { 1410 | unsafe { 1411 | self.ffi_gl_ 1412 | .Uniform2iv(location, (values.len() / 2) as GLsizei, values.as_ptr()); 1413 | } 1414 | } 1415 | 1416 | #[allow(unused_variables)] 1417 | fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) { 1418 | panic!("not supported") 1419 | } 1420 | 1421 | fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) { 1422 | unsafe { 1423 | self.ffi_gl_.Uniform3f(location, v0, v1, v2); 1424 | } 1425 | } 1426 | 1427 | fn uniform_3fv(&self, location: GLint, values: &[f32]) { 1428 | unsafe { 1429 | self.ffi_gl_ 1430 | .Uniform3fv(location, (values.len() / 3) as GLsizei, values.as_ptr()); 1431 | } 1432 | } 1433 | 1434 | fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) { 1435 | unsafe { 1436 | self.ffi_gl_.Uniform3i(location, v0, v1, v2); 1437 | } 1438 | } 1439 | 1440 | fn uniform_3iv(&self, location: GLint, values: &[i32]) { 1441 | unsafe { 1442 | self.ffi_gl_ 1443 | .Uniform3iv(location, (values.len() / 3) as GLsizei, values.as_ptr()); 1444 | } 1445 | } 1446 | 1447 | #[allow(unused_variables)] 1448 | fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) { 1449 | panic!("not supported") 1450 | } 1451 | 1452 | fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) { 1453 | unsafe { 1454 | self.ffi_gl_.Uniform4f(location, x, y, z, w); 1455 | } 1456 | } 1457 | 1458 | fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) { 1459 | unsafe { 1460 | self.ffi_gl_.Uniform4i(location, x, y, z, w); 1461 | } 1462 | } 1463 | 1464 | fn uniform_4iv(&self, location: GLint, values: &[i32]) { 1465 | unsafe { 1466 | self.ffi_gl_ 1467 | .Uniform4iv(location, (values.len() / 4) as GLsizei, values.as_ptr()); 1468 | } 1469 | } 1470 | 1471 | #[allow(unused_variables)] 1472 | fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) { 1473 | panic!("not supported") 1474 | } 1475 | 1476 | fn uniform_4fv(&self, location: GLint, values: &[f32]) { 1477 | unsafe { 1478 | self.ffi_gl_ 1479 | .Uniform4fv(location, (values.len() / 4) as GLsizei, values.as_ptr()); 1480 | } 1481 | } 1482 | 1483 | fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1484 | unsafe { 1485 | self.ffi_gl_.UniformMatrix2fv( 1486 | location, 1487 | (value.len() / 4) as GLsizei, 1488 | transpose as GLboolean, 1489 | value.as_ptr(), 1490 | ); 1491 | } 1492 | } 1493 | 1494 | fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1495 | unsafe { 1496 | self.ffi_gl_.UniformMatrix3fv( 1497 | location, 1498 | (value.len() / 9) as GLsizei, 1499 | transpose as GLboolean, 1500 | value.as_ptr(), 1501 | ); 1502 | } 1503 | } 1504 | 1505 | fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) { 1506 | unsafe { 1507 | self.ffi_gl_.UniformMatrix4fv( 1508 | location, 1509 | (value.len() / 16) as GLsizei, 1510 | transpose as GLboolean, 1511 | value.as_ptr(), 1512 | ); 1513 | } 1514 | } 1515 | 1516 | fn depth_mask(&self, flag: bool) { 1517 | unsafe { 1518 | self.ffi_gl_.DepthMask(flag as GLboolean); 1519 | } 1520 | } 1521 | 1522 | fn depth_range(&self, near: f64, far: f64) { 1523 | unsafe { 1524 | self.ffi_gl_.DepthRangef(near as GLclampf, far as GLclampf); 1525 | } 1526 | } 1527 | 1528 | fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) { 1529 | let mut buf_size = [0]; 1530 | unsafe { 1531 | self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH, &mut buf_size); 1532 | } 1533 | let mut name = vec![0u8; buf_size[0] as usize]; 1534 | let mut length = 0 as GLsizei; 1535 | let mut size = 0 as i32; 1536 | let mut type_ = 0 as u32; 1537 | unsafe { 1538 | self.ffi_gl_.GetActiveAttrib( 1539 | program, 1540 | index, 1541 | buf_size[0], 1542 | &mut length, 1543 | &mut size, 1544 | &mut type_, 1545 | name.as_mut_ptr() as *mut GLchar, 1546 | ); 1547 | } 1548 | name.truncate(if length > 0 { length as usize } else { 0 }); 1549 | (size, type_, String::from_utf8(name).unwrap()) 1550 | } 1551 | 1552 | fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) { 1553 | let mut buf_size = [0]; 1554 | unsafe { 1555 | self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH, &mut buf_size); 1556 | } 1557 | let mut name = vec![0 as u8; buf_size[0] as usize]; 1558 | let mut length: GLsizei = 0; 1559 | let mut size: i32 = 0; 1560 | let mut type_: u32 = 0; 1561 | 1562 | unsafe { 1563 | self.ffi_gl_.GetActiveUniform( 1564 | program, 1565 | index, 1566 | buf_size[0], 1567 | &mut length, 1568 | &mut size, 1569 | &mut type_, 1570 | name.as_mut_ptr() as *mut GLchar, 1571 | ); 1572 | } 1573 | 1574 | name.truncate(if length > 0 { length as usize } else { 0 }); 1575 | 1576 | (size, type_, String::from_utf8(name).unwrap()) 1577 | } 1578 | 1579 | fn get_active_uniforms_iv( 1580 | &self, 1581 | program: GLuint, 1582 | indices: Vec, 1583 | pname: GLenum, 1584 | ) -> Vec { 1585 | let mut result = Vec::with_capacity(indices.len()); 1586 | unsafe { 1587 | result.set_len(indices.len()); 1588 | self.ffi_gl_.GetActiveUniformsiv( 1589 | program, 1590 | indices.len() as GLsizei, 1591 | indices.as_ptr(), 1592 | pname, 1593 | result.as_mut_ptr(), 1594 | ); 1595 | } 1596 | result 1597 | } 1598 | 1599 | fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint { 1600 | let mut result = 0 as GLint; 1601 | unsafe { 1602 | self.ffi_gl_ 1603 | .GetActiveUniformBlockiv(program, index, pname, &mut result); 1604 | } 1605 | result 1606 | } 1607 | 1608 | fn get_active_uniform_block_iv( 1609 | &self, 1610 | program: GLuint, 1611 | index: GLuint, 1612 | pname: GLenum, 1613 | ) -> Vec { 1614 | let count = 1615 | self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_ACTIVE_UNIFORMS); 1616 | let mut result = Vec::with_capacity(count as usize); 1617 | unsafe { 1618 | result.set_len(count as usize); 1619 | self.ffi_gl_ 1620 | .GetActiveUniformBlockiv(program, index, pname, result.as_mut_ptr()); 1621 | } 1622 | result 1623 | } 1624 | 1625 | fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String { 1626 | let buf_size = 1627 | self.get_active_uniform_block_i(program, index, ffi::UNIFORM_BLOCK_NAME_LENGTH); 1628 | let mut name = vec![0 as u8; buf_size as usize]; 1629 | let mut length: GLsizei = 0; 1630 | unsafe { 1631 | self.ffi_gl_.GetActiveUniformBlockName( 1632 | program, 1633 | index, 1634 | buf_size, 1635 | &mut length, 1636 | name.as_mut_ptr() as *mut GLchar, 1637 | ); 1638 | } 1639 | name.truncate(if length > 0 { length as usize } else { 0 }); 1640 | 1641 | String::from_utf8(name).unwrap() 1642 | } 1643 | 1644 | fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int { 1645 | let name = CString::new(name).unwrap(); 1646 | unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) } 1647 | } 1648 | 1649 | #[allow(unused_variables)] 1650 | fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int { 1651 | panic!("not supported") 1652 | } 1653 | 1654 | fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int { 1655 | let name = CString::new(name).unwrap(); 1656 | unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) } 1657 | } 1658 | 1659 | fn get_program_info_log(&self, program: GLuint) -> String { 1660 | let mut max_len = [0]; 1661 | unsafe { 1662 | self.get_program_iv(program, ffi::INFO_LOG_LENGTH, &mut max_len); 1663 | } 1664 | if max_len[0] == 0 { 1665 | return String::new(); 1666 | } 1667 | let mut result = vec![0u8; max_len[0] as usize]; 1668 | let mut result_len = 0 as GLsizei; 1669 | unsafe { 1670 | self.ffi_gl_.GetProgramInfoLog( 1671 | program, 1672 | max_len[0] as GLsizei, 1673 | &mut result_len, 1674 | result.as_mut_ptr() as *mut GLchar, 1675 | ); 1676 | } 1677 | result.truncate(if result_len > 0 { 1678 | result_len as usize 1679 | } else { 1680 | 0 1681 | }); 1682 | String::from_utf8(result).unwrap() 1683 | } 1684 | 1685 | #[inline] 1686 | unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) { 1687 | assert!(!result.is_empty()); 1688 | self.ffi_gl_ 1689 | .GetProgramiv(program, pname, result.as_mut_ptr()); 1690 | } 1691 | 1692 | fn get_program_binary(&self, program: GLuint) -> (Vec, GLenum) { 1693 | let mut len = [0]; 1694 | unsafe { 1695 | self.get_program_iv(program, ffi::PROGRAM_BINARY_LENGTH, &mut len); 1696 | } 1697 | if len[0] <= 0 { 1698 | return (Vec::new(), NONE); 1699 | } 1700 | let mut binary: Vec = Vec::with_capacity(len[0] as usize); 1701 | let mut format = NONE; 1702 | let mut out_len = 0; 1703 | unsafe { 1704 | binary.set_len(len[0] as usize); 1705 | self.ffi_gl_.GetProgramBinary( 1706 | program, 1707 | len[0], 1708 | &mut out_len as *mut GLsizei, 1709 | &mut format, 1710 | binary.as_mut_ptr() as *mut c_void, 1711 | ); 1712 | } 1713 | if len[0] != out_len { 1714 | return (Vec::new(), NONE); 1715 | } 1716 | 1717 | (binary, format) 1718 | } 1719 | 1720 | fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) { 1721 | unsafe { 1722 | self.ffi_gl_.ProgramBinary( 1723 | program, 1724 | format, 1725 | binary.as_ptr() as *const c_void, 1726 | binary.len() as GLsizei, 1727 | ); 1728 | } 1729 | } 1730 | 1731 | fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) { 1732 | unsafe { 1733 | self.ffi_gl_.ProgramParameteri(program, pname, value); 1734 | } 1735 | } 1736 | 1737 | #[inline] 1738 | unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) { 1739 | assert!(!result.is_empty()); 1740 | self.ffi_gl_ 1741 | .GetVertexAttribiv(index, pname, result.as_mut_ptr()); 1742 | } 1743 | 1744 | #[inline] 1745 | unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) { 1746 | assert!(!result.is_empty()); 1747 | self.ffi_gl_ 1748 | .GetVertexAttribfv(index, pname, result.as_mut_ptr()); 1749 | } 1750 | 1751 | fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr { 1752 | let mut result = 0 as *mut GLvoid; 1753 | unsafe { 1754 | self.ffi_gl_ 1755 | .GetVertexAttribPointerv(index, pname, &mut result) 1756 | } 1757 | result as GLsizeiptr 1758 | } 1759 | 1760 | fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint { 1761 | let mut result = 0 as GLint; 1762 | unsafe { 1763 | self.ffi_gl_ 1764 | .GetBufferParameteriv(target, pname, &mut result); 1765 | } 1766 | result 1767 | } 1768 | 1769 | fn get_shader_info_log(&self, shader: GLuint) -> String { 1770 | let mut max_len = [0]; 1771 | unsafe { 1772 | self.get_shader_iv(shader, ffi::INFO_LOG_LENGTH, &mut max_len); 1773 | } 1774 | if max_len[0] == 0 { 1775 | return String::new(); 1776 | } 1777 | let mut result = vec![0u8; max_len[0] as usize]; 1778 | let mut result_len = 0 as GLsizei; 1779 | unsafe { 1780 | self.ffi_gl_.GetShaderInfoLog( 1781 | shader, 1782 | max_len[0] as GLsizei, 1783 | &mut result_len, 1784 | result.as_mut_ptr() as *mut GLchar, 1785 | ); 1786 | } 1787 | result.truncate(if result_len > 0 { 1788 | result_len as usize 1789 | } else { 1790 | 0 1791 | }); 1792 | String::from_utf8(result).unwrap() 1793 | } 1794 | 1795 | fn get_string(&self, which: GLenum) -> String { 1796 | unsafe { 1797 | let llstr = self.ffi_gl_.GetString(which); 1798 | if !llstr.is_null() { 1799 | return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) 1800 | .to_string(); 1801 | } else { 1802 | return "".to_string(); 1803 | } 1804 | } 1805 | } 1806 | 1807 | fn get_string_i(&self, which: GLenum, index: GLuint) -> String { 1808 | unsafe { 1809 | let llstr = self.ffi_gl_.GetStringi(which, index); 1810 | if !llstr.is_null() { 1811 | str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) 1812 | .to_string() 1813 | } else { 1814 | "".to_string() 1815 | } 1816 | } 1817 | } 1818 | 1819 | unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) { 1820 | assert!(!result.is_empty()); 1821 | self.ffi_gl_.GetShaderiv(shader, pname, result.as_mut_ptr()); 1822 | } 1823 | 1824 | fn get_shader_precision_format( 1825 | &self, 1826 | shader_type: GLuint, 1827 | precision_type: GLuint, 1828 | ) -> (GLint, GLint, GLint) { 1829 | let (mut range, mut precision) = match precision_type { 1830 | // These values are for a 32-bit twos-complement integer format. 1831 | ffi::LOW_INT | ffi::MEDIUM_INT | ffi::HIGH_INT => ([31, 30], 0), 1832 | 1833 | // These values are for an IEEE single-precision floating-point format. 1834 | ffi::LOW_FLOAT | ffi::MEDIUM_FLOAT | ffi::HIGH_FLOAT => ([127, 127], 23), 1835 | 1836 | _ => unreachable!("invalid precision"), 1837 | }; 1838 | // This function is sometimes defined even though it's really just 1839 | // a stub, so we need to set range and precision as if it weren't 1840 | // defined before calling it. Suppress any error that might occur. 1841 | unsafe { 1842 | self.ffi_gl_.GetShaderPrecisionFormat( 1843 | shader_type, 1844 | precision_type, 1845 | range.as_mut_ptr(), 1846 | &mut precision, 1847 | ); 1848 | let _ = self.ffi_gl_.GetError(); 1849 | } 1850 | 1851 | (range[0], range[1], precision) 1852 | } 1853 | 1854 | fn compile_shader(&self, shader: GLuint) { 1855 | unsafe { 1856 | self.ffi_gl_.CompileShader(shader); 1857 | } 1858 | } 1859 | 1860 | fn create_program(&self) -> GLuint { 1861 | unsafe { 1862 | return self.ffi_gl_.CreateProgram(); 1863 | } 1864 | } 1865 | 1866 | fn delete_program(&self, program: GLuint) { 1867 | unsafe { 1868 | self.ffi_gl_.DeleteProgram(program); 1869 | } 1870 | } 1871 | 1872 | fn create_shader(&self, shader_type: GLenum) -> GLuint { 1873 | unsafe { 1874 | return self.ffi_gl_.CreateShader(shader_type); 1875 | } 1876 | } 1877 | 1878 | fn delete_shader(&self, shader: GLuint) { 1879 | unsafe { 1880 | self.ffi_gl_.DeleteShader(shader); 1881 | } 1882 | } 1883 | 1884 | fn detach_shader(&self, program: GLuint, shader: GLuint) { 1885 | unsafe { 1886 | self.ffi_gl_.DetachShader(program, shader); 1887 | } 1888 | } 1889 | 1890 | fn link_program(&self, program: GLuint) { 1891 | unsafe { 1892 | return self.ffi_gl_.LinkProgram(program); 1893 | } 1894 | } 1895 | 1896 | fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) { 1897 | unsafe { 1898 | self.ffi_gl_.ClearColor(r, g, b, a); 1899 | } 1900 | } 1901 | 1902 | fn clear(&self, buffer_mask: GLbitfield) { 1903 | unsafe { 1904 | self.ffi_gl_.Clear(buffer_mask); 1905 | } 1906 | } 1907 | 1908 | fn clear_depth(&self, depth: f64) { 1909 | unsafe { 1910 | self.ffi_gl_.ClearDepthf(depth as GLclampf); 1911 | } 1912 | } 1913 | 1914 | fn clear_stencil(&self, s: GLint) { 1915 | unsafe { 1916 | self.ffi_gl_.ClearStencil(s); 1917 | } 1918 | } 1919 | 1920 | fn flush(&self) { 1921 | unsafe { 1922 | self.ffi_gl_.Flush(); 1923 | } 1924 | } 1925 | 1926 | fn finish(&self) { 1927 | unsafe { 1928 | self.ffi_gl_.Finish(); 1929 | } 1930 | } 1931 | 1932 | fn get_error(&self) -> GLenum { 1933 | unsafe { self.ffi_gl_.GetError() } 1934 | } 1935 | 1936 | fn stencil_mask(&self, mask: GLuint) { 1937 | unsafe { self.ffi_gl_.StencilMask(mask) } 1938 | } 1939 | 1940 | fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) { 1941 | unsafe { self.ffi_gl_.StencilMaskSeparate(face, mask) } 1942 | } 1943 | 1944 | fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) { 1945 | unsafe { self.ffi_gl_.StencilFunc(func, ref_, mask) } 1946 | } 1947 | 1948 | fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) { 1949 | unsafe { self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask) } 1950 | } 1951 | 1952 | fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) { 1953 | unsafe { self.ffi_gl_.StencilOp(sfail, dpfail, dppass) } 1954 | } 1955 | 1956 | fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) { 1957 | unsafe { self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass) } 1958 | } 1959 | 1960 | fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) { 1961 | unsafe { 1962 | self.ffi_gl_.EGLImageTargetTexture2DOES(target, image); 1963 | } 1964 | } 1965 | 1966 | fn egl_image_target_renderbuffer_storage_oes(&self, target: GLenum, image: GLeglImageOES) { 1967 | unsafe { 1968 | self.ffi_gl_.EGLImageTargetRenderbufferStorageOES(target, image); 1969 | } 1970 | } 1971 | 1972 | fn generate_mipmap(&self, target: GLenum) { 1973 | unsafe { self.ffi_gl_.GenerateMipmap(target) } 1974 | } 1975 | 1976 | fn insert_event_marker_ext(&self, message: &str) { 1977 | if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() { 1978 | unsafe { 1979 | self.ffi_gl_ 1980 | .InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _); 1981 | } 1982 | } 1983 | } 1984 | 1985 | fn push_group_marker_ext(&self, message: &str) { 1986 | if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() { 1987 | unsafe { 1988 | self.ffi_gl_ 1989 | .PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _); 1990 | } 1991 | } 1992 | } 1993 | 1994 | fn pop_group_marker_ext(&self) { 1995 | if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() { 1996 | unsafe { 1997 | self.ffi_gl_.PopGroupMarkerEXT(); 1998 | } 1999 | } 2000 | } 2001 | 2002 | fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) { 2003 | if self.ffi_gl_.DebugMessageInsertKHR.is_loaded() { 2004 | unsafe { 2005 | self.ffi_gl_ 2006 | .DebugMessageInsertKHR(source, type_, id, severity, message.len() as GLsizei, message.as_ptr() as *const _); 2007 | } 2008 | } 2009 | } 2010 | 2011 | fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) { 2012 | if self.ffi_gl_.PushDebugGroupKHR.is_loaded() { 2013 | unsafe { 2014 | self.ffi_gl_ 2015 | .PushDebugGroupKHR(source, id, message.len() as GLsizei, message.as_ptr() as *const _); 2016 | } 2017 | } 2018 | } 2019 | 2020 | fn pop_debug_group_khr(&self) { 2021 | if self.ffi_gl_.PopDebugGroupKHR.is_loaded() { 2022 | unsafe { 2023 | self.ffi_gl_.PopDebugGroupKHR(); 2024 | } 2025 | } 2026 | } 2027 | 2028 | fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync { 2029 | unsafe { self.ffi_gl_.FenceSync(condition, flags) as *const _ } 2030 | } 2031 | 2032 | fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) -> GLenum { 2033 | unsafe { 2034 | self.ffi_gl_ 2035 | .ClientWaitSync(sync as *const _, flags, timeout) 2036 | } 2037 | } 2038 | 2039 | fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) { 2040 | unsafe { 2041 | self.ffi_gl_.WaitSync(sync as *const _, flags, timeout); 2042 | } 2043 | } 2044 | 2045 | fn delete_sync(&self, sync: GLsync) { 2046 | unsafe { 2047 | self.ffi_gl_.DeleteSync(sync as *const _); 2048 | } 2049 | } 2050 | 2051 | fn texture_range_apple(&self, _target: GLenum, _data: &[u8]) { 2052 | panic!("not supported") 2053 | } 2054 | 2055 | fn gen_fences_apple(&self, _n: GLsizei) -> Vec { 2056 | panic!("not supported") 2057 | } 2058 | 2059 | fn delete_fences_apple(&self, _fences: &[GLuint]) { 2060 | panic!("not supported") 2061 | } 2062 | 2063 | fn set_fence_apple(&self, _fence: GLuint) { 2064 | panic!("not supported") 2065 | } 2066 | 2067 | fn finish_fence_apple(&self, _fence: GLuint) { 2068 | panic!("not supported") 2069 | } 2070 | 2071 | fn test_fence_apple(&self, _fence: GLuint) { 2072 | panic!("not supported") 2073 | } 2074 | 2075 | fn test_object_apple(&self, _object: GLenum, _name: GLuint) -> GLboolean { 2076 | panic!("not supported") 2077 | } 2078 | 2079 | fn finish_object_apple(&self, _object: GLenum, _name: GLuint) { 2080 | panic!("not supported") 2081 | } 2082 | 2083 | 2084 | 2085 | // GL_ARB_blend_func_extended 2086 | fn bind_frag_data_location_indexed( 2087 | &self, 2088 | _program: GLuint, 2089 | _color_number: GLuint, 2090 | _index: GLuint, 2091 | _name: &str, 2092 | ) { 2093 | panic!("not supported"); 2094 | } 2095 | 2096 | fn get_frag_data_index(&self, _program: GLuint, _name: &str) -> GLint { 2097 | panic!("not supported"); 2098 | } 2099 | 2100 | // GL_KHR_debug 2101 | fn get_debug_messages(&self) -> Vec { 2102 | if !self.ffi_gl_.GetDebugMessageLog.is_loaded() { 2103 | return Vec::new(); 2104 | } 2105 | 2106 | let mut max_message_len = 0; 2107 | unsafe { 2108 | self.ffi_gl_ 2109 | .GetIntegerv(ffi::MAX_DEBUG_MESSAGE_LENGTH, &mut max_message_len) 2110 | } 2111 | 2112 | let mut output = Vec::new(); 2113 | const CAPACITY: usize = 5; 2114 | 2115 | let mut msg_data = vec![0u8; CAPACITY * max_message_len as usize]; 2116 | let mut sources = [0 as GLenum; CAPACITY]; 2117 | let mut types = [0 as GLenum; CAPACITY]; 2118 | let mut severities = [0 as GLenum; CAPACITY]; 2119 | let mut ids = [0 as GLuint; CAPACITY]; 2120 | let mut lengths = [0 as GLsizei; CAPACITY]; 2121 | 2122 | loop { 2123 | let count = unsafe { 2124 | // ANGLE can return one more message than the count argument specifies, 2125 | // so we deliberately request one less than the capacity of our buffers. 2126 | // https://issues.angleproject.org/issues/425579207 2127 | self.ffi_gl_.GetDebugMessageLog( 2128 | (CAPACITY - 1) as _, 2129 | msg_data.len() as _, 2130 | sources.as_mut_ptr(), 2131 | types.as_mut_ptr(), 2132 | ids.as_mut_ptr(), 2133 | severities.as_mut_ptr(), 2134 | lengths.as_mut_ptr(), 2135 | msg_data.as_mut_ptr() as *mut _, 2136 | ) 2137 | }; 2138 | let count = CAPACITY.min(count as usize); 2139 | 2140 | let mut offset = 0; 2141 | output.extend((0..count).map(|i| { 2142 | let len = lengths[i] as usize; 2143 | let slice = &msg_data[offset..offset + len]; 2144 | offset += len; 2145 | DebugMessage { 2146 | message: String::from_utf8_lossy(slice).to_string(), 2147 | source: sources[i], 2148 | ty: types[i], 2149 | id: ids[i], 2150 | severity: severities[i], 2151 | } 2152 | })); 2153 | 2154 | if (count as usize) < CAPACITY { 2155 | return output; 2156 | } 2157 | } 2158 | } 2159 | 2160 | fn provoking_vertex_angle(&self, mode: GLenum) { 2161 | unsafe { 2162 | self.ffi_gl_.ProvokingVertexANGLE(mode); 2163 | } 2164 | } 2165 | 2166 | // GL_KHR_blend_equation_advanced 2167 | fn blend_barrier_khr(&self) { 2168 | if self.ffi_gl_.BlendBarrierKHR.is_loaded() { 2169 | unsafe { 2170 | self.ffi_gl_.BlendBarrierKHR(); 2171 | } 2172 | } 2173 | } 2174 | 2175 | // GL_CHROMIUM_copy_texture 2176 | fn copy_texture_chromium(&self, 2177 | source_id: GLuint, source_level: GLint, 2178 | dest_target: GLenum, dest_id: GLuint, dest_level: GLint, 2179 | internal_format: GLint, dest_type: GLenum, 2180 | unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean) 2181 | { 2182 | unsafe { 2183 | self.ffi_gl_.CopyTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level, 2184 | internal_format, dest_type, 2185 | unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha, 2186 | ); 2187 | } 2188 | } 2189 | fn copy_sub_texture_chromium(&self, 2190 | source_id: GLuint, source_level: GLint, 2191 | dest_target: GLenum, dest_id: GLuint, dest_level: GLint, 2192 | x_offset: GLint, y_offset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei, 2193 | unpack_flip_y: GLboolean, unpack_premultiply_alpha: GLboolean, unpack_unmultiply_alpha: GLboolean) 2194 | { 2195 | unsafe { 2196 | self.ffi_gl_.CopySubTextureCHROMIUM(source_id, source_level, dest_target, dest_id, dest_level, 2197 | x_offset, y_offset, x, y, width, height, 2198 | unpack_flip_y, unpack_premultiply_alpha, unpack_unmultiply_alpha, 2199 | ); 2200 | } 2201 | } 2202 | 2203 | // GL_ANGLE_copy_texture_3d 2204 | fn copy_texture_3d_angle( 2205 | &self, 2206 | source_id: GLuint, 2207 | source_level: GLint, 2208 | dest_target: GLenum, 2209 | dest_id: GLuint, 2210 | dest_level: GLint, 2211 | internal_format: GLint, 2212 | dest_type: GLenum, 2213 | unpack_flip_y: GLboolean, 2214 | unpack_premultiply_alpha: GLboolean, 2215 | unpack_unmultiply_alpha: GLboolean, 2216 | ) { 2217 | unsafe { 2218 | self.ffi_gl_.CopyTexture3DANGLE( 2219 | source_id, 2220 | source_level, 2221 | dest_target, 2222 | dest_id, 2223 | dest_level, 2224 | internal_format, 2225 | dest_type, 2226 | unpack_flip_y, 2227 | unpack_premultiply_alpha, 2228 | unpack_unmultiply_alpha, 2229 | ); 2230 | } 2231 | } 2232 | 2233 | fn copy_sub_texture_3d_angle( 2234 | &self, 2235 | source_id: GLuint, 2236 | source_level: GLint, 2237 | dest_target: GLenum, 2238 | dest_id: GLuint, 2239 | dest_level: GLint, 2240 | x_offset: GLint, 2241 | y_offset: GLint, 2242 | z_offset: GLint, 2243 | x: GLint, 2244 | y: GLint, 2245 | z: GLint, 2246 | width: GLsizei, 2247 | height: GLsizei, 2248 | depth: GLsizei, 2249 | unpack_flip_y: GLboolean, 2250 | unpack_premultiply_alpha: GLboolean, 2251 | unpack_unmultiply_alpha: GLboolean, 2252 | ) { 2253 | unsafe { 2254 | self.ffi_gl_.CopySubTexture3DANGLE( 2255 | source_id, 2256 | source_level, 2257 | dest_target, 2258 | dest_id, 2259 | dest_level, 2260 | x_offset, 2261 | y_offset, 2262 | z_offset, 2263 | x, 2264 | y, 2265 | z, 2266 | width, 2267 | height, 2268 | depth, 2269 | unpack_flip_y, 2270 | unpack_premultiply_alpha, 2271 | unpack_unmultiply_alpha, 2272 | ); 2273 | } 2274 | } 2275 | 2276 | fn buffer_storage( 2277 | &self, 2278 | target: GLenum, 2279 | size: GLsizeiptr, 2280 | data: *const GLvoid, 2281 | flags: GLbitfield, 2282 | ) { 2283 | unsafe { 2284 | self.ffi_gl_.BufferStorageEXT(target, size, data, flags); 2285 | } 2286 | } 2287 | 2288 | fn flush_mapped_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr) { 2289 | unsafe { 2290 | self.ffi_gl_.FlushMappedBufferRange(target, offset, length); 2291 | } 2292 | } 2293 | 2294 | fn start_tiling_qcom(&self, x: GLuint, y: GLuint, width: GLuint, height: GLuint, preserve_mask: GLbitfield) { 2295 | unsafe { 2296 | self.ffi_gl_.StartTilingQCOM(x, y, width, height, preserve_mask); 2297 | } 2298 | } 2299 | 2300 | fn end_tiling_qcom(&self, preserve_mask: GLbitfield) { 2301 | unsafe { 2302 | self.ffi_gl_.EndTilingQCOM(preserve_mask); 2303 | } 2304 | } 2305 | } 2306 | --------------------------------------------------------------------------------