--- a/third_party/rust/cgl/.cargo-checksum.json
+++ b/third_party/rust/cgl/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"944bf600c6230664922a011cbca026699969f2f89f6c7ff689835836ccd7b1de",".travis.yml":"ea512c9287deceaab4ee436a1246874c84e7a422a90cd3aa3e8f9d3121824674","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"e651a297d1d1445870a6380de53f1fd33f4ac9c349ff4197d740e24c9a16ca47","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"5b2cad1e1bd53b9f986974a23dbcbd951270a567d6c661f3584707d7ad198e82","src/cgl.rs":"d41fea7f18c07912f485d041baeb99010023084b449af69c6c92dfdcaf1c96e8","src/lib.rs":"8a86ac23aaea868d951a1c51300670d1eda525681d0b144964a6c81737f485e6"},"package":"8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"944bf600c6230664922a011cbca026699969f2f89f6c7ff689835836ccd7b1de",".travis.yml":"ea512c9287deceaab4ee436a1246874c84e7a422a90cd3aa3e8f9d3121824674","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"95753be1a55ae87129e69f594f2dc3f14a4f6df4401296aad9fde35b40177814","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"5b2cad1e1bd53b9f986974a23dbcbd951270a567d6c661f3584707d7ad198e82","src/cgl.rs":"d41fea7f18c07912f485d041baeb99010023084b449af69c6c92dfdcaf1c96e8","src/lib.rs":"8a86ac23aaea868d951a1c51300670d1eda525681d0b144964a6c81737f485e6"},"package":"86765cb42c2a2c497e142af72517c1b4d7ae5bb2f25dfa77a5c69642f2342d89"}
\ No newline at end of file
--- a/third_party/rust/cgl/Cargo.toml
+++ b/third_party/rust/cgl/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "cgl"
license = "MIT / Apache-2.0"
-version = "0.1.5"
+version = "0.2.1"
authors = ["The Servo Project Developers"]
description = "Rust bindings for CGL on Mac"
repository = "https://github.com/servo/cgl-rs"
[dependencies]
libc = "0.2"
-gleam = "0.2"
+gleam = "0.4"
--- a/third_party/rust/gleam/.cargo-checksum.json
+++ b/third_party/rust/gleam/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"46f5e5da873985b56fc97643a27f610feec18724aad8e899379f3b8c84c329ae","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"a1d227749271af1ad64516277ee655b66bfcd53a13006bf94d41380c5dd345db","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"5b2abf3e2b85f4d0bdbbaa5778c8fd7480eb151db3bd699ec63b77fa3afdfd7b","src/gl.rs":"f9acc199591d06018b75924fc1ad881e9deb67f4ad8f0213f028b4aacdffb5ca","src/lib.rs":"ad33ebcb3f4a0edc36e95c837cda6f01a0be8a6ab1bcf485565fb03f70831324"},"package":"9590e0e578d528a080c5abac678e7efbe349a73c7316faafd4073edf5f462d01"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"c1e953ee360e77de57f7b02f1b7880bd6a3dc22d1a69e953c2ac2c52cc52d247",".travis.yml":"29b74b95210896ce634c11a9037638668473b5a1b3b1716c505cb04dbb6341fa","COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"5fd8124cb3073a87b04271d343b8bb73c749f97bfef800d5ccb2b461a1a84354","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"2de24b7458d6b88f20324303a48acf64a4f2bbfb83d2ec4d6ff2b4f4a1fd2275","build.rs":"16a89f28717ffeae75219889d6560aa8b089adff46f821a724e28e20fddafb81","src/gl.rs":"ed01b1c8e5cb31de68dde54a857722f3d5b2bdeb8e30bfb2a95b500e3bf5f98a","src/gl_fns.rs":"d6eb7dd171030fe1b350f1616cd2c2e33d9051f70f5edcdd85f146b2745418a0","src/gles_fns.rs":"91c15619b8fbabe2324358d3c6ada27559acc42b0a21c64cc37ccd3729a9582a","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"2958396a0a358d2de747b31329f5ae2229070602b0f51edd5d682f92c307c332"}
\ No newline at end of file
--- a/third_party/rust/gleam/.travis.yml
+++ b/third_party/rust/gleam/.travis.yml
@@ -1,3 +1,8 @@
language: rust
+rust:
+ - nightly
+ - beta
+ - stable
+
notifications:
webhooks: http://build.servo.org:54856/travis
--- a/third_party/rust/gleam/Cargo.toml
+++ b/third_party/rust/gleam/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "gleam"
-version = "0.2.32"
+version = "0.4.1"
license = "Apache-2.0/MIT"
authors = ["The Servo Project Developers"]
build = "build.rs"
documentation = "http://doc.servo.org/gleam/"
repository = "https://github.com/servo/gleam"
description = "Generated OpenGL bindings and wrapper for Servo."
[build-dependencies]
--- a/third_party/rust/gleam/build.rs
+++ b/third_party/rust/gleam/build.rs
@@ -3,38 +3,29 @@ extern crate pkg_config;
use std::env;
use std::fs::File;
use std::path::Path;
use gl_generator::{Registry, Api, Profile, Fallbacks};
fn main() {
let dest = env::var("OUT_DIR").unwrap();
- let mut file = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap();
-
- let target = env::var("TARGET").unwrap();
+ let mut file_gl_and_gles = File::create(&Path::new(&dest).join("gl_and_gles_bindings.rs")).unwrap();
+ let mut file_gl = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap();
+ let mut file_gles = File::create(&Path::new(&dest).join("gles_bindings.rs")).unwrap();
- if target.contains("android") {
- let extensions = ["GL_EXT_texture_format_BGRA8888"];
- // GLES 2.0 bindings for Android
- Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, extensions)
- .write_bindings(gl_generator::StaticGenerator, &mut file)
+ // OpenGL 3.3 bindings
+ let gl_extensions = ["GL_ARB_texture_rectangle", "GL_EXT_debug_marker"];
+ let gl_reg = Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, gl_extensions);
+ gl_reg.write_bindings(gl_generator::StructGenerator, &mut file_gl)
+ .unwrap();
+
+ // GLES 2.0 bindings
+ let gles_extensions = ["GL_EXT_texture_format_BGRA8888"];
+ let gles_reg = Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, gles_extensions);
+ gles_reg.write_bindings(gl_generator::StructGenerator, &mut file_gles)
.unwrap();
- println!("cargo:rustc-link-lib=GLESv3");
- } else {
- let extensions = ["GL_ARB_texture_rectangle", "GL_EXT_debug_marker"];
- // OpenGL 3.3 bindings for Linux/Mac/Windows
- Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, extensions)
- .write_bindings(gl_generator::GlobalGenerator, &mut file)
- .unwrap();
-
- if target.contains("darwin") {
- println!("cargo:rustc-link-lib=framework=OpenGL");
- } else if target.contains("windows") {
- println!("cargo:rustc-link-lib=opengl32");
- } else {
- if let Err(_) = pkg_config::probe_library("gl") {
- println!("cargo:rustc-link-lib=GL");
- }
- }
- }
+ // OpenGL 3.3 + GLES 2.0 bindings. Used to get all enums
+ let gl_reg = gl_reg + gles_reg;
+ gl_reg.write_bindings(gl_generator::StructGenerator, &mut file_gl_and_gles)
+ .unwrap();
}
--- a/third_party/rust/gleam/src/gl.rs
+++ b/third_party/rust/gleam/src/gl.rs
@@ -6,1533 +6,407 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::mem;
use std::mem::size_of;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
-use std::str::{self};
+use std::rc::Rc;
+use std::str;
use std::iter::repeat;
use std::ffi::{CString, CStr};
use ffi;
pub use ffi::types::*;
pub use ffi::*;
+pub use ffi_gl::Gl as GlFfi;
+pub use ffi_gles::Gles2 as GlesFfi;
+
#[derive(Debug, Eq, PartialEq)]
pub enum GlType {
Gl,
Gles,
}
impl Default for GlType {
- #[cfg(target_os="android")]
- fn default() -> GlType {
- GlType::Gles
- }
- #[cfg(not(target_os="android"))]
- fn default() -> GlType {
- GlType::Gl
- }
-}
-
-#[inline]
-pub fn buffer_data<T>(target: GLenum, data: &[T], usage: GLenum) {
- unsafe {
- ffi::BufferData(target,
- (data.len() * size_of::<T>()) as GLsizeiptr,
- data.as_ptr() as *const GLvoid,
- usage);
- }
-}
-
-#[inline]
-pub fn buffer_data_raw<T>(target: GLenum, data: &T, usage: GLenum) {
- unsafe {
- ffi::BufferData(target,
- size_of::<T>() as GLsizeiptr,
- data as *const T as *const GLvoid,
- usage);
+ #[cfg(target_os="android")]
+ fn default() -> GlType {
+ GlType::Gles
}
-}
-
-#[inline]
-pub fn buffer_sub_data<T>(target: GLenum, offset: isize, data: &[T]) {
- unsafe {
- ffi::BufferSubData(target,
- offset,
- (data.len() * size_of::<T>()) as GLsizeiptr,
- data.as_ptr() as *const GLvoid);
- }
-}
-
-pub fn shader_source(shader: GLuint, strings: &[&[u8]]) {
- let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect();
- let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
- unsafe {
- ffi::ShaderSource(shader, pointers.len() as GLsizei,
- pointers.as_ptr() as *const *const GLchar, lengths.as_ptr());
- }
- drop(lengths);
- drop(pointers);
-}
-
-#[cfg(not(target_os="android"))]
-pub fn read_buffer(mode: GLenum) {
- unsafe {
- ffi::ReadBuffer(mode);
+ #[cfg(not(target_os="android"))]
+ fn default() -> GlType {
+ GlType::Gl
}
}
fn calculate_length(width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> usize {
let colors = match format {
ffi::RGB => 3,
-#[cfg(not(target_os="android"))]
ffi::BGR => 3,
ffi::RGBA => 4,
-#[cfg(not(target_os="android"))]
ffi::BGRA => 4,
ffi::ALPHA => 1,
-#[cfg(target_os="android")]
ffi::LUMINANCE => 1,
_ => panic!("unsupported format for read_pixels"),
};
let depth = match pixel_type {
ffi::UNSIGNED_BYTE => 1,
_ => panic!("unsupported pixel_type for read_pixels"),
};
return (width * height * colors * depth) as usize;
}
-pub fn read_pixels_into_buffer(x: GLint, y: GLint, width: GLsizei, height: GLsizei,
- format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8]) {
- // Assumes that the user properly allocated the size for dst_buffer.
- assert!(calculate_length(width, height, format, pixel_type) == dst_buffer.len());
-
- unsafe {
- // We don't want any alignment padding on pixel rows.
- ffi::PixelStorei(ffi::PACK_ALIGNMENT, 1);
- ffi::ReadPixels(x, y, width, height, format, pixel_type, dst_buffer.as_mut_ptr() as *mut c_void);
- }
-}
-
-pub fn read_pixels(x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8> {
- let len = calculate_length(width, height, format, pixel_type);
- let mut pixels: Vec<u8> = Vec::new();
- pixels.reserve(len);
- unsafe { pixels.set_len(len); }
-
- read_pixels_into_buffer(x, y, width, height, format, pixel_type, pixels.as_mut_slice());
-
- pixels
-}
-
-#[inline]
-pub fn sample_coverage(value: GLclampf, invert: bool) {
- unsafe {
- ffi::SampleCoverage(value, invert as GLboolean);
- }
-}
-
-#[inline]
-pub fn polygon_offset(factor: GLfloat, units: GLfloat) {
- unsafe {
- ffi::PolygonOffset(factor, units);
- }
-}
-
-#[inline]
-pub fn pixel_store_i(name: GLenum, param: GLint) {
- unsafe {
- ffi::PixelStorei(name, param);
- }
-}
-
-#[inline]
-pub fn gen_buffers(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
- ffi::GenBuffers(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[inline]
-pub fn gen_renderbuffers(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
- ffi::GenRenderbuffers(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[inline]
-pub fn gen_framebuffers(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
- ffi::GenFramebuffers(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[inline]
-pub fn gen_textures(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
- ffi::GenTextures(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[inline]
-pub fn gen_vertex_arrays(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
- ffi::GenVertexArrays(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn gen_queries(n: GLsizei) -> Vec<GLuint> {
- unsafe {
- let mut result = vec![0; n as usize];
- ffi::GenQueries(n, result.as_mut_ptr());
- return result;
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn begin_query(target: GLenum, id: GLuint) {
- unsafe {
- ffi::BeginQuery(target, id);
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn end_query(target: GLenum) {
- unsafe {
- ffi::EndQuery(target);
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn query_counter(id: GLuint, target: GLenum) {
- unsafe {
- ffi::QueryCounter(id, target);
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn get_query_object_iv(id: GLuint, pname: GLenum) -> i32 {
- unsafe {
- let mut result = 0;
- ffi::GetQueryObjectiv(id, pname, &mut result);
- result
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn get_query_object_uiv(id: GLuint, pname: GLenum) -> u32 {
- unsafe {
- let mut result = 0;
- ffi::GetQueryObjectuiv(id, pname, &mut result);
- result
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn get_query_object_i64v(id: GLuint, pname: GLenum) -> i64 {
- unsafe {
- let mut result = 0;
- ffi::GetQueryObjecti64v(id, pname, &mut result);
- result
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn get_query_object_ui64v(id: GLuint, pname: GLenum) -> u64 {
- unsafe {
- let mut result = 0;
- ffi::GetQueryObjectui64v(id, pname, &mut result);
- result
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn delete_queries(queries: &[GLuint]) {
- unsafe {
- ffi::DeleteQueries(queries.len() as GLsizei, queries.as_ptr());
- }
-}
-
-#[inline]
-pub fn delete_vertex_arrays(vertex_arrays: &[GLuint]) {
- unsafe {
- ffi::DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr());
- }
-}
-
-#[inline]
-pub fn delete_buffers(buffers: &[GLuint]) {
- unsafe {
- ffi::DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr());
- }
-}
-
-#[inline]
-pub fn delete_renderbuffers(renderbuffers: &[GLuint]) {
- unsafe {
- ffi::DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr());
- }
-}
-
-#[inline]
-pub fn delete_framebuffers(framebuffers: &[GLuint]) {
- unsafe {
- ffi::DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr());
- }
-}
-
-// NB: The name of this function is wrong, it's here for compatibility reasons,
-// but should be removed.
-#[inline]
-pub fn delete_frame_buffers(framebuffers: &[GLuint]) {
- delete_framebuffers(framebuffers);
-}
-
-#[inline]
-pub fn delete_textures(textures: &[GLuint]) {
- unsafe {
- ffi::DeleteTextures(textures.len() as GLsizei, textures.as_ptr());
- }
-}
-
-#[inline]
-pub fn framebuffer_renderbuffer(target: GLenum,
+pub trait Gl {
+ fn get_type(&self) -> GlType;
+ fn buffer_data_untyped(&self,
+ target: GLenum,
+ size: GLsizeiptr,
+ data: *const GLvoid,
+ usage: GLenum);
+ fn buffer_sub_data_untyped(&self,
+ target: GLenum,
+ offset: isize,
+ size: GLsizeiptr,
+ data: *const GLvoid);
+ fn shader_source(&self, shader: GLuint, strings: &[&[u8]]);
+ fn read_buffer(&self, mode: GLenum);
+ fn read_pixels_into_buffer(&self,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ pixel_type: GLenum,
+ dst_buffer: &mut [u8]);
+ fn read_pixels(&self,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ pixel_type: GLenum)
+ -> Vec<u8>;
+ fn sample_coverage(&self, value: GLclampf, invert: bool);
+ fn polygon_offset(&self, factor: GLfloat, units: GLfloat);
+ fn pixel_store_i(&self, name: GLenum, param: GLint);
+ fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint>;
+ fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint>;
+ fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint>;
+ fn gen_textures(&self, n: GLsizei) -> Vec<GLuint>;
+ fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint>;
+ fn gen_queries(&self, n: GLsizei) -> Vec<GLuint>;
+ fn begin_query(&self, target: GLenum, id: GLuint);
+ fn end_query(&self, target: GLenum);
+ fn query_counter(&self, id: GLuint, target: GLenum);
+ fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32;
+ fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32;
+ fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64;
+ fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64;
+ fn delete_queries(&self, queries: &[GLuint]);
+ fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]);
+ fn delete_buffers(&self, buffers: &[GLuint]);
+ fn delete_renderbuffers(&self, renderbuffers: &[GLuint]);
+ fn delete_framebuffers(&self, framebuffers: &[GLuint]);
+ fn delete_textures(&self, textures: &[GLuint]);
+ fn framebuffer_renderbuffer(&self,
+ target: GLenum,
attachment: GLenum,
renderbuffertarget: GLenum,
- renderbuffer: GLuint) {
- unsafe {
- ffi::FramebufferRenderbuffer(target,
- attachment,
- renderbuffertarget,
- renderbuffer);
- }
-}
-
-#[inline]
-pub fn renderbuffer_storage(target: GLenum,
+ renderbuffer: GLuint);
+ fn renderbuffer_storage(&self,
+ target: GLenum,
internalformat: GLenum,
width: GLsizei,
- height: GLsizei) {
- unsafe {
- ffi::RenderbufferStorage(target,
- internalformat,
- width,
- height);
- }
-}
-
-#[inline]
-pub fn depth_func(func: GLenum) {
- unsafe {
- ffi::DepthFunc(func);
- }
-}
-
-#[inline]
-pub fn active_texture(texture: GLenum) {
- unsafe {
- ffi::ActiveTexture(texture);
- }
-}
-
-#[inline]
-pub fn attach_shader(program: GLuint, shader: GLuint) {
- unsafe {
- ffi::AttachShader(program, shader);
- }
-}
-
-#[inline]
-pub fn bind_attrib_location(program: GLuint, index: GLuint, name: &str) {
- let c_string = CString::new(name).unwrap();
- unsafe {
- ffi::BindAttribLocation(program, index, c_string.as_ptr())
- }
-}
-
-#[inline]
-pub fn get_uniform_block_index(program: GLuint, name: &str) -> GLuint {
- let c_string = CString::new(name).unwrap();
- unsafe {
- ffi::GetUniformBlockIndex(program, c_string.as_ptr())
- }
-}
-
-#[inline]
-pub fn bind_buffer_base(target: GLenum, index: GLuint, buffer: GLuint) {
- unsafe {
- ffi::BindBufferBase(target, index, buffer);
- }
-}
-
-#[inline]
-pub fn uniform_block_binding(program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint) {
- unsafe {
- ffi::UniformBlockBinding(program, uniform_block_index, uniform_block_binding);
- }
-}
-
-#[inline]
-pub fn bind_buffer(target: GLenum, buffer: GLuint) {
- unsafe {
- ffi::BindBuffer(target, buffer);
- }
-}
-
-#[inline]
-pub fn bind_vertex_array(vao: GLuint) {
- unsafe {
- ffi::BindVertexArray(vao);
- }
-}
-
-#[inline]
-pub fn bind_renderbuffer(target: GLenum, renderbuffer: GLuint) {
- unsafe {
- ffi::BindRenderbuffer(target, renderbuffer);
- }
-}
-
-#[inline]
-pub fn bind_framebuffer(target: GLenum, framebuffer: GLuint) {
- unsafe {
- ffi::BindFramebuffer(target, framebuffer);
- }
-}
-
-#[inline]
-pub fn bind_texture(target: GLenum, texture: GLuint) {
- unsafe {
- ffi::BindTexture(target, texture);
- }
-}
-
-// FIXME: Does not verify buffer size -- unsafe!
-pub fn tex_image_2d(target: GLenum,
+ height: GLsizei);
+ fn depth_func(&self, func: GLenum);
+ fn active_texture(&self, texture: GLenum);
+ fn attach_shader(&self, program: GLuint, shader: GLuint);
+ fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str);
+ fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint;
+ fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint);
+ fn uniform_block_binding(&self,
+ program: GLuint,
+ uniform_block_index: GLuint,
+ uniform_block_binding: GLuint);
+ fn bind_buffer(&self, target: GLenum, buffer: GLuint);
+ fn bind_vertex_array(&self, vao: GLuint);
+ fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint);
+ fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint);
+ fn bind_texture(&self, target: GLenum, texture: GLuint);
+ fn tex_image_2d(&self,
+ target: GLenum,
level: GLint,
internal_format: GLint,
width: GLsizei,
height: GLsizei,
border: GLint,
format: GLenum,
ty: GLenum,
- opt_data: Option<&[u8]>) {
- match opt_data {
- Some(data) => {
- unsafe {
- ffi::TexImage2D(target, level, internal_format, width, height, border, format, ty,
- data.as_ptr() as *const GLvoid);
- }
- }
- None => {
- unsafe {
- ffi::TexImage2D(target, level, internal_format, width, height, border, format, ty,
- ptr::null());
- }
- }
- }
-}
-
-pub fn compressed_tex_image_2d(target: GLenum,
+ opt_data: Option<&[u8]>);
+ fn compressed_tex_image_2d(&self,
+ target: GLenum,
level: GLint,
internal_format: GLenum,
width: GLsizei,
height: GLsizei,
border: GLint,
- data: &[u8]) {
- unsafe {
- ffi::CompressedTexImage2D(target, level, internal_format, width, height, border,
- data.len() as GLsizei, data.as_ptr() as *const GLvoid);
- }
-}
-
-pub fn compressed_tex_sub_image_2d(target: GLenum,
+ data: &[u8]);
+ fn compressed_tex_sub_image_2d(&self,
+ target: GLenum,
level: GLint,
xoffset: GLint,
yoffset: GLint,
width: GLsizei,
height: GLsizei,
format: GLenum,
- data: &[u8]) {
- unsafe {
- ffi::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
- data.len() as GLsizei, data.as_ptr() as *const GLvoid);
- }
-}
-
-// FIXME: Does not verify buffer size -- unsafe!
-pub fn tex_image_3d(target: GLenum,
+ data: &[u8]);
+ fn tex_image_3d(&self,
+ target: GLenum,
level: GLint,
internal_format: GLint,
width: GLsizei,
height: GLsizei,
depth: GLsizei,
border: GLint,
format: GLenum,
ty: GLenum,
- opt_data: Option<&[u8]>) {
- unsafe {
- let pdata = match opt_data {
- Some(data) => mem::transmute(data.as_ptr()),
- None => ptr::null(),
- };
- ffi::TexImage3D(target,
- level,
- internal_format,
- width,
- height,
- depth,
- border,
- format,
- ty,
- pdata);
- }
-}
-
-pub fn copy_tex_image_2d(target: GLenum,
+ opt_data: Option<&[u8]>);
+ fn copy_tex_image_2d(&self,
+ target: GLenum,
level: GLint,
internal_format: GLenum,
x: GLint,
y: GLint,
width: GLsizei,
height: GLsizei,
- border: GLint) {
- unsafe {
- ffi::CopyTexImage2D(target,
- level,
- internal_format,
- x,
- y,
- width,
- height,
- border);
- }
-}
-
-pub fn copy_tex_sub_image_2d(target: GLenum,
+ border: GLint);
+ fn copy_tex_sub_image_2d(&self,
+ target: GLenum,
level: GLint,
xoffset: GLint,
yoffset: GLint,
x: GLint,
y: GLint,
width: GLsizei,
- height: GLsizei) {
- unsafe {
- ffi::CopyTexSubImage2D(target,
- level,
- xoffset,
- yoffset,
- x,
- y,
- width,
- height);
- }
-}
-
-#[inline]
-pub fn copy_tex_sub_image_3d(target: GLenum,
+ height: GLsizei);
+ fn copy_tex_sub_image_3d(&self,
+ target: GLenum,
level: GLint,
xoffset: GLint,
yoffset: GLint,
zoffset: GLint,
x: GLint,
y: GLint,
width: GLsizei,
- height: GLsizei) {
- unsafe {
- ffi::CopyTexSubImage3D(target,
- level,
- xoffset,
- yoffset,
- zoffset,
- x,
- y,
- width,
- height);
- }
-}
-
-pub fn tex_sub_image_2d(target: GLenum,
+ height: GLsizei);
+ fn tex_sub_image_2d(&self,
+ target: GLenum,
level: GLint,
xoffset: GLint,
yoffset: GLint,
width: GLsizei,
height: GLsizei,
format: GLenum,
ty: GLenum,
- data: &[u8]) {
- unsafe {
- ffi::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, ty, data.as_ptr() as *const c_void);
- }
-}
-
-pub fn tex_sub_image_3d(target: GLenum,
+ data: &[u8]);
+ fn tex_sub_image_3d(&self,
+ target: GLenum,
level: GLint,
xoffset: GLint,
yoffset: GLint,
zoffset: GLint,
width: GLsizei,
height: GLsizei,
depth: GLsizei,
format: GLenum,
ty: GLenum,
- data: &[u8]) {
- unsafe {
- ffi::TexSubImage3D(target,
- level,
- xoffset,
- yoffset,
- zoffset,
- width,
- height,
- depth,
- format,
- ty,
- data.as_ptr() as *const c_void);
- }
-}
-
-#[inline]
-pub fn get_integer_v(name: GLenum) -> GLint {
- let mut result: GLint = 0 as GLint;
- unsafe {
- ffi::GetIntegerv(name, &mut result);
- }
- result
-}
-
-#[inline]
-pub fn get_boolean_v(name: GLenum) -> GLboolean {
- let mut result: GLboolean = 0 as GLboolean;
- unsafe {
- ffi::GetBooleanv(name, &mut result);
- }
- result
-}
-
-
-#[inline]
-pub fn get_float_v(name: GLenum) -> GLfloat {
- let mut result: GLfloat = 0 as GLfloat;
- unsafe {
- ffi::GetFloatv(name, &mut result);
- }
- result
-}
-
-#[inline]
-pub fn tex_parameter_i(target: GLenum, pname: GLenum, param: GLint) {
- unsafe {
- ffi::TexParameteri(target, pname, param);
- }
-}
-
-#[inline]
-pub fn tex_parameter_f(target: GLenum, pname: GLenum, param: GLfloat) {
- unsafe {
- ffi::TexParameterf(target, pname, param);
- }
-}
-
-#[inline]
-pub fn framebuffer_texture_2d(target: GLenum,
+ data: &[u8]);
+ fn get_integer_v(&self, name: GLenum) -> GLint;
+ fn get_boolean_v(&self, name: GLenum) -> GLboolean;
+ fn get_float_v(&self, name: GLenum) -> GLfloat;
+ fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint);
+ fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat);
+ fn framebuffer_texture_2d(&self,
+ target: GLenum,
attachment: GLenum,
textarget: GLenum,
texture: GLuint,
- level: GLint) {
- unsafe {
- ffi::FramebufferTexture2D(target, attachment, textarget, texture, level);
- }
-}
-
-#[inline]
-pub fn framebuffer_texture_layer(target: GLenum,
+ level: GLint);
+ fn framebuffer_texture_layer(&self,
+ target: GLenum,
attachment: GLenum,
texture: GLuint,
level: GLint,
- layer: GLint) {
- unsafe {
- ffi::FramebufferTextureLayer(target, attachment, texture, level, layer);
- }
-}
-
-#[inline]
-pub fn blit_framebuffer(srcX0: GLint,
- srcY0: GLint,
- srcX1: GLint,
- srcY1: GLint,
- dstX0: GLint,
- dstY0: GLint,
- dstX1: GLint,
- dstY1: GLint,
+ layer: GLint);
+ fn blit_framebuffer(&self,
+ src_x0: GLint,
+ src_y0: GLint,
+ src_x1: GLint,
+ src_y1: GLint,
+ dst_x0: GLint,
+ dst_y0: GLint,
+ dst_x1: GLint,
+ dst_y1: GLint,
mask: GLbitfield,
- filter: GLenum) {
- unsafe {
- ffi::BlitFramebuffer(srcX0,
- srcY0,
- srcX1,
- srcY1,
- dstX0,
- dstY0,
- dstX1,
- dstY1,
- mask,
- filter);
- }
-}
-
-#[inline]
-pub fn vertex_attrib_4f(index: GLuint,
- x: GLfloat,
- y: GLfloat,
- z: GLfloat,
- w: GLfloat) {
- unsafe {
- ffi::VertexAttrib4f(index, x, y, z, w)
- }
-}
-
-#[inline]
-pub fn vertex_attrib_pointer_f32(index: GLuint,
+ filter: GLenum);
+ fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat);
+ fn vertex_attrib_pointer_f32(&self,
+ index: GLuint,
size: GLint,
normalized: bool,
stride: GLsizei,
- offset: GLuint) {
- unsafe {
- ffi::VertexAttribPointer(index,
- size,
- ffi::FLOAT,
- normalized as GLboolean,
- stride,
- offset as *const GLvoid)
- }
-}
-
-#[inline]
-pub fn vertex_attrib_pointer(index: GLuint,
+ offset: GLuint);
+ fn vertex_attrib_pointer(&self,
+ index: GLuint,
size: GLint,
type_: GLenum,
normalized: bool,
stride: GLsizei,
- offset: GLuint) {
- unsafe {
- ffi::VertexAttribPointer(index,
- size,
- type_,
- normalized as GLboolean,
- stride,
- offset as *const GLvoid)
- }
-}
-
-#[inline]
-pub fn vertex_attrib_i_pointer(index: GLuint,
+ offset: GLuint);
+ fn vertex_attrib_i_pointer(&self,
+ index: GLuint,
size: GLint,
type_: GLenum,
stride: GLsizei,
- offset: GLuint) {
- unsafe {
- ffi::VertexAttribIPointer(index,
- size,
- type_,
- stride,
- offset as *const GLvoid)
- }
-}
-
-#[inline]
-pub fn vertex_attrib_divisor(index: GLuint, divisor: GLuint) {
- unsafe {
- ffi::VertexAttribDivisor(index, divisor)
- }
-}
-
-#[inline]
-pub fn viewport(x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
- unsafe {
- ffi::Viewport(x, y, width, height);
- }
-}
-
-#[inline]
-pub fn scissor(x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
- unsafe {
- ffi::Scissor(x, y, width, height);
- }
-}
-
-#[inline]
-pub fn line_width(width: GLfloat) {
- unsafe {
- ffi::LineWidth(width);
- }
-}
-
-#[inline]
-pub fn use_program(program: GLuint) {
- unsafe {
- ffi::UseProgram(program);
- }
-}
-
-#[inline]
-pub fn validate_program(program: GLuint) {
- unsafe {
- ffi::ValidateProgram(program);
- }
-}
-
-#[inline]
-pub fn draw_arrays(mode: GLenum, first: GLint, count: GLsizei) {
- unsafe {
- return ffi::DrawArrays(mode, first, count);
- }
-}
-
-#[inline]
-pub fn draw_arrays_instanced(mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) {
- unsafe {
- return ffi::DrawArraysInstanced(mode, first, count, primcount);
- }
-}
-
-#[inline]
-pub fn draw_elements(mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint) {
- unsafe {
- return ffi::DrawElements(mode, count, element_type, indices_offset as *const c_void)
- }
-}
-
-#[inline]
-pub fn draw_elements_instanced(mode: GLenum,
+ offset: GLuint);
+ fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint);
+ fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei);
+ fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei);
+ fn line_width(&self, width: GLfloat);
+ fn use_program(&self, program: GLuint);
+ fn validate_program(&self, program: GLuint);
+ fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei);
+ fn draw_arrays_instanced(&self,
+ mode: GLenum,
+ first: GLint,
+ count: GLsizei,
+ primcount: GLsizei);
+ fn draw_elements(&self,
+ mode: GLenum,
+ count: GLsizei,
+ element_type: GLenum,
+ indices_offset: GLuint);
+ fn draw_elements_instanced(&self,
+ mode: GLenum,
count: GLsizei,
element_type: GLenum,
indices_offset: GLuint,
- primcount: GLsizei) {
- unsafe {
- return ffi::DrawElementsInstanced(mode,
- count,
- element_type,
- indices_offset as *const c_void,
- primcount)
- }
-}
-
-#[inline]
-pub fn blend_color(r: f32, g: f32, b: f32, a: f32) {
- unsafe {
- ffi::BlendColor(r, g, b, a);
- }
-}
-
-#[inline]
-pub fn blend_func(sfactor: GLenum, dfactor: GLenum) {
- unsafe {
- ffi::BlendFunc(sfactor, dfactor);
- }
-}
-
-#[inline]
-pub fn blend_func_separate(src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum) {
- unsafe {
- ffi::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
- }
-}
-
-#[inline]
-pub fn blend_equation(mode: GLenum) {
- unsafe {
- ffi::BlendEquation(mode);
- }
-}
-
-#[inline]
-pub fn blend_equation_separate(mode_rgb: GLenum, mode_alpha: GLenum) {
- unsafe {
- ffi::BlendEquationSeparate(mode_rgb, mode_alpha);
- }
-}
-
-#[inline]
-pub fn color_mask(r: bool, g: bool, b: bool, a: bool) {
- unsafe {
- ffi::ColorMask(r as GLboolean, g as GLboolean, b as GLboolean, a as GLboolean);
- }
-}
-
-#[inline]
-pub fn cull_face(mode: GLenum) {
- unsafe {
- ffi::CullFace(mode);
- }
-}
-
-#[inline]
-pub fn front_face(mode: GLenum) {
- unsafe {
- ffi::FrontFace(mode);
- }
-}
-
-#[inline]
-pub fn enable(cap: GLenum) {
- unsafe {
- ffi::Enable(cap);
- }
-}
-
-#[inline]
-pub fn disable(cap: GLenum) {
- unsafe {
- ffi::Disable(cap);
- }
-}
-
-#[inline]
-pub fn hint(param_name: GLenum, param_val: GLenum) {
- unsafe {
- ffi::Hint(param_name, param_val);
- }
-}
-
-#[inline]
-pub fn is_enabled(cap: GLenum) -> GLboolean {
- unsafe {
- ffi::IsEnabled(cap)
- }
-}
-
-#[inline]
-pub fn is_shader(shader: GLuint) -> GLboolean {
- unsafe {
- ffi::IsShader(shader)
- }
-}
-
-#[inline]
-pub fn is_texture(texture: GLenum) -> GLboolean {
- unsafe {
- ffi::IsTexture(texture)
- }
-}
-
-#[inline]
-pub fn is_framebuffer(framebuffer: GLenum) -> GLboolean {
- unsafe {
- ffi::IsFramebuffer(framebuffer)
- }
-}
-
-#[inline]
-pub fn is_renderbuffer(renderbuffer: GLenum) -> GLboolean {
- unsafe {
- ffi::IsRenderbuffer(renderbuffer)
- }
-}
-
-#[inline]
-pub fn check_frame_buffer_status(target: GLenum) -> GLenum {
- unsafe {
- ffi::CheckFramebufferStatus(target)
- }
-}
-
-#[inline]
-pub fn enable_vertex_attrib_array(index: GLuint) {
- unsafe {
- ffi::EnableVertexAttribArray(index);
- }
-}
-
-#[inline]
-pub fn disable_vertex_attrib_array(index: GLuint) {
- unsafe {
- ffi::DisableVertexAttribArray(index);
- }
-}
-
-#[inline]
-pub fn uniform_1f(location: GLint, v0: GLfloat) {
- unsafe {
- ffi::Uniform1f(location, v0);
- }
-}
-
-#[inline]
-pub fn uniform_1fv(location: GLint, values: &[f32]) {
- unsafe {
- ffi::Uniform1fv(location,
- values.len() as GLsizei,
- values.as_ptr());
- }
-}
-
-#[inline]
-pub fn uniform_1i(location: GLint, v0: GLint) {
- unsafe {
- ffi::Uniform1i(location, v0);
- }
-}
-
-#[inline]
-pub fn uniform_1iv(location: GLint, values: &[i32]) {
- unsafe {
- ffi::Uniform1iv(location,
- values.len() as GLsizei,
- values.as_ptr());
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn uniform_1ui(location: GLint, v0: GLuint) {
- unsafe {
- ffi::Uniform1ui(location, v0);
- }
-}
-
-#[inline]
-pub fn uniform_2f(location: GLint, v0: GLfloat, v1: GLfloat) {
- unsafe {
- ffi::Uniform2f(location, v0, v1);
- }
-}
-
-#[inline]
-pub fn uniform_2fv(location: GLint, values: &[f32]) {
- unsafe {
- ffi::Uniform2fv(location,
- (values.len() / 2) as GLsizei,
- values.as_ptr());
- }
-}
-
-#[inline]
-pub fn uniform_2i(location: GLint, v0: GLint, v1: GLint) {
- unsafe {
- ffi::Uniform2i(location, v0, v1);
- }
-}
-
-#[inline]
-pub fn uniform_2iv(location: GLint, values: &[i32]) {
- unsafe {
- ffi::Uniform2iv(location,
- (values.len() / 2) as GLsizei,
- values.as_ptr());
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn uniform_2ui(location: GLint, v0: GLuint, v1: GLuint) {
- unsafe {
- ffi::Uniform2ui(location, v0, v1);
- }
-}
-
-#[inline]
-pub fn uniform_3f(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
- unsafe {
- ffi::Uniform3f(location, v0, v1, v2);
- }
-}
-
-#[inline]
-pub fn uniform_3fv(location: GLint, values: &[f32]) {
- unsafe {
- ffi::Uniform3fv(location,
- (values.len() / 3) as GLsizei,
- values.as_ptr());
- }
-}
-
-#[inline]
-pub fn uniform_3i(location: GLint, v0: GLint, v1: GLint, v2: GLint) {
- unsafe {
- ffi::Uniform3i(location, v0, v1, v2);
- }
-}
-
-#[inline]
-pub fn uniform_3iv(location: GLint, values: &[i32]) {
- unsafe {
- ffi::Uniform3iv(location,
- (values.len() / 3) as GLsizei,
- values.as_ptr());
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn uniform_3ui(location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
- unsafe {
- ffi::Uniform3ui(location, v0, v1, v2);
- }
-}
-
-#[inline]
-pub fn uniform_4f(location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
- unsafe {
- ffi::Uniform4f(location, x, y, z, w);
- }
-}
-
-#[inline]
-pub fn uniform_4i(location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
- unsafe {
- ffi::Uniform4i(location, x, y, z, w);
- }
-}
-
-#[inline]
-pub fn uniform_4iv(location: GLint, values: &[i32]) {
- unsafe {
- ffi::Uniform4iv(location,
- (values.len() / 4) as GLsizei,
- values.as_ptr());
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn uniform_4ui(location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
- unsafe {
- ffi::Uniform4ui(location, x, y, z, w);
- }
-}
-
-#[inline]
-pub fn uniform_4fv(location: GLint, values: &[f32]) {
- unsafe {
- ffi::Uniform4fv(location,
- (values.len() / 4) as GLsizei,
- values.as_ptr());
- }
+ primcount: GLsizei);
+ fn blend_color(&self, r: f32, g: f32, b: f32, a: f32);
+ fn blend_func(&self, sfactor: GLenum, dfactor: GLenum);
+ fn blend_func_separate(&self,
+ src_rgb: GLenum,
+ dest_rgb: GLenum,
+ src_alpha: GLenum,
+ dest_alpha: GLenum);
+ fn blend_equation(&self, mode: GLenum);
+ fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum);
+ fn color_mask(&self, r: bool, g: bool, b: bool, a: bool);
+ fn cull_face(&self, mode: GLenum);
+ fn front_face(&self, mode: GLenum);
+ fn enable(&self, cap: GLenum);
+ fn disable(&self, cap: GLenum);
+ fn hint(&self, param_name: GLenum, param_val: GLenum);
+ fn is_enabled(&self, cap: GLenum) -> GLboolean;
+ fn is_shader(&self, shader: GLuint) -> GLboolean;
+ fn is_texture(&self, texture: GLenum) -> GLboolean;
+ fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean;
+ fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean;
+ fn check_frame_buffer_status(&self, target: GLenum) -> GLenum;
+ fn enable_vertex_attrib_array(&self, index: GLuint);
+ fn disable_vertex_attrib_array(&self, index: GLuint);
+ fn uniform_1f(&self, location: GLint, v0: GLfloat);
+ fn uniform_1fv(&self, location: GLint, values: &[f32]);
+ fn uniform_1i(&self, location: GLint, v0: GLint);
+ fn uniform_1iv(&self, location: GLint, values: &[i32]);
+ fn uniform_1ui(&self, location: GLint, v0: GLuint);
+ fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat);
+ fn uniform_2fv(&self, location: GLint, values: &[f32]);
+ fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint);
+ fn uniform_2iv(&self, location: GLint, values: &[i32]);
+ fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint);
+ fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat);
+ fn uniform_3fv(&self, location: GLint, values: &[f32]);
+ fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint);
+ fn uniform_3iv(&self, location: GLint, values: &[i32]);
+ fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint);
+ fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat);
+ fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint);
+ fn uniform_4iv(&self, location: GLint, values: &[i32]);
+ fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint);
+ fn uniform_4fv(&self, location: GLint, values: &[f32]);
+ fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]);
+ fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]);
+ fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]);
+ fn depth_mask(&self, flag: bool);
+ fn depth_range(&self, near: f64, far: f64);
+ fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String);
+ fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String);
+ fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int;
+ fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int;
+ fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int;
+ fn get_program_info_log(&self, program: GLuint) -> String;
+ fn get_program_iv(&self, program: GLuint, pname: GLenum) -> GLint;
+ fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum) -> GLint;
+ fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum) -> Vec<GLfloat>;
+ fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint;
+ fn get_shader_info_log(&self, shader: GLuint) -> String;
+ fn get_string(&self, which: GLenum) -> String;
+ fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint;
+ fn compile_shader(&self, shader: GLuint);
+ fn create_program(&self) -> GLuint;
+ fn delete_program(&self, program: GLuint);
+ fn create_shader(&self, shader_type: GLenum) -> GLuint;
+ fn delete_shader(&self, shader: GLuint);
+ fn detach_shader(&self, program: GLuint, shader: GLuint);
+ fn link_program(&self, program: GLuint);
+ fn clear_color(&self, r: f32, g: f32, b: f32, a: f32);
+ fn clear(&self, buffer_mask: GLbitfield);
+ fn clear_depth(&self, depth: f64);
+ fn clear_stencil(&self, s: GLint);
+ fn flush(&self);
+ fn finish(&self);
+ fn get_error(&self) -> GLenum;
+ fn stencil_mask(&self, mask: GLuint);
+ fn stencil_mask_separate(&self, face: GLenum, mask: GLuint);
+ fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint);
+ fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint);
+ fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum);
+ fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum);
+ fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES);
+ fn generate_mipmap(&self, target: GLenum);
+ fn insert_event_marker_ext(&self, message: &str);
+ fn push_group_marker_ext(&self, message: &str);
+ fn pop_group_marker_ext(&self);
}
#[inline]
-pub fn uniform_matrix_2fv(location: GLint, transpose: bool, value: &[f32]) {
- unsafe {
- ffi::UniformMatrix2fv(location,
- (value.len() / 4) as GLsizei,
- transpose as GLboolean,
- value.as_ptr());
- }
-}
-
-#[inline]
-pub fn uniform_matrix_3fv(location: GLint, transpose: bool, value: &[f32]) {
- unsafe {
- ffi::UniformMatrix3fv(location,
- (value.len() / 9) as GLsizei,
- transpose as GLboolean,
- value.as_ptr());
- }
-}
-
-#[inline]
-pub fn uniform_matrix_4fv(location: GLint, transpose: bool, value: &[f32]) {
- unsafe {
- ffi::UniformMatrix4fv(location,
- (value.len() / 16) as GLsizei,
- transpose as GLboolean,
- value.as_ptr());
- }
-}
-
-#[inline]
-pub fn depth_mask(flag: bool) {
- unsafe {
- ffi::DepthMask(flag as GLboolean);
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn depth_range(near: f64, far: f64) {
- unsafe {
- ffi::DepthRange(near as GLclampd, far as GLclampd);
- }
-}
-
-#[cfg(target_os="android")]
-#[inline]
-pub fn depth_range(near: f64, far: f64) {
- unsafe {
- ffi::DepthRangef(near as GLclampf, far as GLclampf);
- }
-}
-
-#[inline]
-pub fn get_active_attrib(program: GLuint, index: GLuint) -> (i32, u32, String) {
- let buf_size = get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH);
- let mut name = vec![0u8; buf_size as usize];
- let mut length = 0 as GLsizei;
- let mut size = 0 as i32;
- let mut type_ = 0 as u32;
- unsafe {
- ffi::GetActiveAttrib(program, index, buf_size, &mut length, &mut size, &mut type_, name.as_mut_ptr() as *mut GLchar);
- }
- name.truncate(if length > 0 {length as usize} else {0});
- (size, type_, String::from_utf8(name).unwrap())
-}
-
-#[inline]
-pub fn get_active_uniform(program: GLuint, index: GLuint) -> (i32, u32, String) {
- let buf_size = get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH);
- let mut name = vec![0 as u8; buf_size as usize];
- let mut length: GLsizei = 0;
- let mut size: i32 = 0;
- let mut type_: u32 = 0;
-
- unsafe {
- ffi::GetActiveUniform(program, index, buf_size, &mut length, &mut size,
- &mut type_, name.as_mut_ptr() as *mut GLchar);
- }
-
- name.truncate(if length > 0 { length as usize } else { 0 });
-
- (size, type_, String::from_utf8(name).unwrap())
-}
-
-#[inline]
-pub fn get_attrib_location(program: GLuint, name: &str) -> c_int {
- let name = CString::new(name).unwrap();
- unsafe {
- ffi::GetAttribLocation(program, name.as_ptr())
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn get_frag_data_location(program: GLuint, name: &str) -> c_int {
- let name = CString::new(name).unwrap();
- unsafe {
- ffi::GetFragDataLocation(program, name.as_ptr())
- }
-}
-
-#[inline]
-pub fn get_uniform_location(program: GLuint, name: &str) -> c_int {
- let name = CString::new(name).unwrap();
- unsafe {
- ffi::GetUniformLocation(program, name.as_ptr())
- }
-}
-
-pub fn get_program_info_log(program: GLuint) -> String {
- unsafe {
- let mut result = vec![0u8; 1024];
- let mut result_len: GLsizei = 0 as GLsizei;
- ffi::GetProgramInfoLog(program,
- 1024 as GLsizei,
- &mut result_len,
- result.as_mut_ptr() as *mut GLchar);
- result.truncate(if result_len > 0 {result_len as usize} else {0});
- String::from_utf8(result).unwrap()
- }
-}
-
-#[inline]
-pub fn get_program_iv(program: GLuint, pname: GLenum) -> GLint {
- unsafe {
- let mut result: GLint = 0 as GLint;
- ffi::GetProgramiv(program, pname, &mut result);
- return result;
- }
-}
-
-#[inline]
-pub fn get_vertex_attrib_iv(index: GLuint, pname: GLenum) -> GLint {
- unsafe {
- let mut result: GLint = 0 as GLint;
- ffi::GetVertexAttribiv(index, pname, &mut result);
- return result;
- }
-}
-
-#[inline]
-pub fn get_vertex_attrib_fv(index: GLuint, pname: GLenum) -> Vec<GLfloat> {
- unsafe {
- let mut result = vec![0 as GLfloat; 4];
- ffi::GetVertexAttribfv(index, pname, result.as_mut_ptr());
- return result;
- }
-}
-
-#[inline]
-pub fn get_buffer_parameter_iv(target: GLuint, pname: GLenum) -> GLint {
- unsafe {
- let mut result: GLint = 0 as GLint;
- ffi::GetBufferParameteriv(target, pname, &mut result);
- return result;
- }
-}
-
-pub fn get_shader_info_log(shader: GLuint) -> String {
- unsafe {
- let mut result = vec![0u8; 1024];
- let mut result_len: GLsizei = 0 as GLsizei;
- ffi::GetShaderInfoLog(shader,
- 1024 as GLsizei,
- &mut result_len,
- result.as_mut_ptr() as *mut GLchar);
- result.truncate(if result_len > 0 {result_len as usize} else {0});
- String::from_utf8(result).unwrap()
- }
-}
-
-#[inline]
-pub fn get_string(which: GLenum) -> String {
- unsafe {
- let llstr = ffi::GetString(which);
- if !llstr.is_null() {
- return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()).to_string();
- } else {
- return "".to_string();
- }
- }
-}
-
-#[inline]
-pub fn get_shader_iv(shader: GLuint, pname: GLenum) -> GLint {
- unsafe {
- let mut result: GLint = 0 as GLint;
- ffi::GetShaderiv(shader, pname, &mut result);
- return result;
- }
-}
-
-#[inline]
-pub fn compile_shader(shader: GLuint) {
- unsafe {
- ffi::CompileShader(shader);
- }
+pub fn buffer_data<T>(gl_: &Gl, target: GLenum, data: &[T], usage: GLenum) {
+ gl_.buffer_data_untyped(target,
+ (data.len() * size_of::<T>()) as GLsizeiptr,
+ data.as_ptr() as *const GLvoid,
+ usage)
}
#[inline]
-pub fn create_program() -> GLuint {
- unsafe {
- return ffi::CreateProgram();
- }
-}
-
-#[inline]
-pub fn delete_program(program: GLuint) {
- unsafe {
- ffi::DeleteProgram(program);
- }
-}
-
-#[inline]
-pub fn create_shader(shader_type: GLenum) -> GLuint {
- unsafe {
- return ffi::CreateShader(shader_type);
- }
-}
-
-#[inline]
-pub fn delete_shader(shader: GLuint) {
- unsafe {
- ffi::DeleteShader(shader);
- }
-}
-
-#[inline]
-pub fn detach_shader(program: GLuint, shader: GLuint) {
- unsafe {
- ffi::DetachShader(program, shader);
- }
-}
-
-#[inline]
-pub fn link_program(program: GLuint) {
- unsafe {
- return ffi::LinkProgram(program);
- }
-}
-
-#[inline]
-pub fn clear_color(r: f32, g: f32, b: f32, a: f32) {
- unsafe {
- ffi::ClearColor(r, g, b, a);
- }
-}
-
-#[inline]
-pub fn clear(buffer_mask: GLbitfield) {
- unsafe {
- ffi::Clear(buffer_mask);
- }
-}
-
-#[cfg(not(target_os="android"))]
-#[inline]
-pub fn clear_depth(depth: f64) {
- unsafe {
- ffi::ClearDepth(depth as GLclampd);
- }
-}
-
-#[cfg(target_os="android")]
-#[inline]
-pub fn clear_depth(depth: f64) {
- unsafe {
- ffi::ClearDepthf(depth as GLclampf);
- }
-}
-
-#[inline]
-pub fn clear_stencil(s: GLint) {
- unsafe {
- ffi::ClearStencil(s);
- }
-}
-
-#[inline]
-pub fn flush() {
- unsafe {
- ffi::Flush();
- }
-}
-
-#[inline]
-pub fn finish() {
- unsafe {
- ffi::Finish();
- }
-}
-
-#[inline]
-pub fn get_error() -> GLenum {
- unsafe {
- ffi::GetError()
- }
+pub fn buffer_data_raw<T>(gl_: &Gl, target: GLenum, data: &T, usage: GLenum) {
+ gl_.buffer_data_untyped(target,
+ size_of::<T>() as GLsizeiptr,
+ data as *const T as *const GLvoid,
+ usage)
}
#[inline]
-pub fn stencil_mask(mask: GLuint) {
- unsafe {
- ffi::StencilMask(mask)
- }
-}
-
-#[inline]
-pub fn stencil_mask_separate(face: GLenum, mask: GLuint) {
- unsafe {
- ffi::StencilMaskSeparate(face, mask)
- }
-}
-
-#[inline]
-pub fn stencil_func(func: GLenum,
- ref_: GLint,
- mask: GLuint) {
- unsafe {
- ffi::StencilFunc(func, ref_, mask)
- }
-}
-
-#[inline]
-pub fn stencil_func_separate(face: GLenum,
- func: GLenum,
- ref_: GLint,
- mask: GLuint) {
- unsafe {
- ffi::StencilFuncSeparate(face, func, ref_, mask)
- }
-}
-
-#[inline]
-pub fn stencil_op(sfail: GLenum,
- dpfail: GLenum,
- dppass: GLenum) {
- unsafe {
- ffi::StencilOp(sfail, dpfail, dppass)
- }
+pub fn buffer_sub_data<T>(gl_: &Gl, target: GLenum, offset: isize, data: &[T]) {
+ gl_.buffer_sub_data_untyped(target,
+ offset,
+ (data.len() * size_of::<T>()) as GLsizeiptr,
+ data.as_ptr() as *const GLvoid);
}
-#[inline]
-pub fn stencil_op_separate(face: GLenum,
- sfail: GLenum,
- dpfail: GLenum,
- dppass: GLenum) {
- unsafe {
- ffi::StencilOpSeparate(face, sfail, dpfail, dppass)
- }
-}
-
-#[cfg(target_os="android")]
-extern {
- pub fn glEGLImageTargetTexture2DOES(target: GLenum, image: GLeglImageOES);
-}
-
-#[cfg(target_os="android")]
-pub fn egl_image_target_texture2d_oes(target: GLenum, image: GLeglImageOES) {
- unsafe {
- glEGLImageTargetTexture2DOES(target, image);
- }
-}
-
-#[inline]
-pub fn generate_mipmap(target: GLenum) {
- unsafe {
- ffi::GenerateMipmap(target)
- }
-}
-
-#[inline]
-#[cfg(not(target_os="android"))]
-pub fn insert_event_marker_ext(message: &str) {
- if ffi::InsertEventMarkerEXT::is_loaded() {
- unsafe {
- ffi::InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
- }
- }
-}
-
-#[inline]
-#[cfg(not(target_os="android"))]
-pub fn push_group_marker_ext(message: &str) {
- if ffi::PushGroupMarkerEXT::is_loaded() {
- unsafe {
- ffi::PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
- }
- }
-}
-
-#[inline]
-#[cfg(not(target_os="android"))]
-pub fn pop_group_marker_ext() {
- if ffi::PopGroupMarkerEXT::is_loaded() {
- unsafe {
- ffi::PopGroupMarkerEXT();
- }
- }
-}
+include!("gl_fns.rs");
+include!("gles_fns.rs");
new file mode 100644
--- /dev/null
+++ b/third_party/rust/gleam/src/gl_fns.rs
@@ -0,0 +1,1329 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct GlFns {
+ ffi_gl_: GlFfi,
+}
+
+impl GlFns
+{
+ pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc<Gl> where F: FnMut(&str) -> *const c_void {
+ let ffi_gl_ = GlFfi::load_with(loadfn);
+ Rc::new(GlFns {
+ ffi_gl_: ffi_gl_,
+ }) as Rc<Gl>
+ }
+}
+
+impl Gl for GlFns {
+ fn get_type(&self) -> GlType {
+ GlType::Gl
+ }
+
+ fn buffer_data_untyped(&self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, usage: GLenum) {
+ unsafe {
+ self.ffi_gl_.BufferData(target,
+ size,
+ data,
+ usage);
+ }
+ }
+
+ fn buffer_sub_data_untyped(&self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid) {
+ unsafe {
+ self.ffi_gl_.BufferSubData(target,
+ offset,
+ size,
+ data);
+ }
+ }
+
+ fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
+ let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect();
+ let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
+ unsafe {
+ self.ffi_gl_.ShaderSource(shader, pointers.len() as GLsizei,
+ pointers.as_ptr() as *const *const GLchar, lengths.as_ptr());
+ }
+ drop(lengths);
+ drop(pointers);
+ }
+
+ fn read_buffer(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.ReadBuffer(mode);
+ }
+ }
+
+ fn read_pixels_into_buffer(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei,
+ format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8]) {
+ // Assumes that the user properly allocated the size for dst_buffer.
+ assert!(calculate_length(width, height, format, pixel_type) == dst_buffer.len());
+
+ unsafe {
+ // We don't want any alignment padding on pixel rows.
+ self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1);
+ self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, dst_buffer.as_mut_ptr() as *mut c_void);
+ }
+ }
+
+ fn read_pixels(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8> {
+ let len = calculate_length(width, height, format, pixel_type);
+ let mut pixels: Vec<u8> = Vec::new();
+ pixels.reserve(len);
+ unsafe { pixels.set_len(len); }
+
+ self.read_pixels_into_buffer(x, y, width, height, format, pixel_type, pixels.as_mut_slice());
+
+ pixels
+ }
+
+ fn sample_coverage(&self, value: GLclampf, invert: bool) {
+ unsafe {
+ self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
+ }
+ }
+
+ fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
+ unsafe {
+ self.ffi_gl_.PolygonOffset(factor, units);
+ }
+ }
+
+ fn pixel_store_i(&self, name: GLenum, param: GLint) {
+ unsafe {
+ self.ffi_gl_.PixelStorei(name, param);
+ }
+ }
+
+ fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenBuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenTextures(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result = vec![0; n as usize];
+ self.ffi_gl_.GenQueries(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn begin_query(&self, target: GLenum, id: GLuint) {
+ unsafe {
+ self.ffi_gl_.BeginQuery(target, id);
+ }
+ }
+
+ fn end_query(&self, target: GLenum) {
+ unsafe {
+ self.ffi_gl_.EndQuery(target);
+ }
+ }
+
+ fn query_counter(&self, id: GLuint, target: GLenum) {
+ unsafe {
+ self.ffi_gl_.QueryCounter(id, target);
+ }
+ }
+
+ fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
+ unsafe {
+ let mut result = 0;
+ self.ffi_gl_.GetQueryObjectiv(id, pname, &mut result);
+ result
+ }
+ }
+
+ fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
+ unsafe {
+ let mut result = 0;
+ self.ffi_gl_.GetQueryObjectuiv(id, pname, &mut result);
+ result
+ }
+ }
+
+ fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
+ unsafe {
+ let mut result = 0;
+ self.ffi_gl_.GetQueryObjecti64v(id, pname, &mut result);
+ result
+ }
+ }
+
+ fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
+ unsafe {
+ let mut result = 0;
+ self.ffi_gl_.GetQueryObjectui64v(id, pname, &mut result);
+ result
+ }
+ }
+
+ fn delete_queries(&self, queries: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteQueries(queries.len() as GLsizei, queries.as_ptr());
+ }
+ }
+
+ fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr());
+ }
+ }
+
+ fn delete_buffers(&self, buffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr());
+ }
+ }
+
+ fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr());
+ }
+ }
+
+ fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr());
+ }
+ }
+
+ fn delete_textures(&self, textures: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteTextures(textures.len() as GLsizei, textures.as_ptr());
+ }
+ }
+
+ fn framebuffer_renderbuffer(&self,
+ target: GLenum,
+ attachment: GLenum,
+ renderbuffertarget: GLenum,
+ renderbuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.FramebufferRenderbuffer(target,
+ attachment,
+ renderbuffertarget,
+ renderbuffer);
+ }
+ }
+
+ fn renderbuffer_storage(&self,
+ target: GLenum,
+ internalformat: GLenum,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.RenderbufferStorage(target,
+ internalformat,
+ width,
+ height);
+ }
+ }
+
+ fn depth_func(&self, func: GLenum) {
+ unsafe {
+ self.ffi_gl_.DepthFunc(func);
+ }
+ }
+
+ fn active_texture(&self, texture: GLenum) {
+ unsafe {
+ self.ffi_gl_.ActiveTexture(texture);
+ }
+ }
+
+ fn attach_shader(&self, program: GLuint, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.AttachShader(program, shader);
+ }
+ }
+
+ fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
+ let c_string = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.BindAttribLocation(program, index, c_string.as_ptr())
+ }
+ }
+
+ fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
+ let c_string = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetUniformBlockIndex(program, c_string.as_ptr())
+ }
+ }
+
+ fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindBufferBase(target, index, buffer);
+ }
+ }
+
+ fn uniform_block_binding(&self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint) {
+ unsafe {
+ self.ffi_gl_.UniformBlockBinding(program, uniform_block_index, uniform_block_binding);
+ }
+ }
+
+ fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindBuffer(target, buffer);
+ }
+ }
+
+ fn bind_vertex_array(&self, vao: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindVertexArray(vao);
+ }
+ }
+
+ fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
+ }
+ }
+
+ fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindFramebuffer(target, framebuffer);
+ }
+ }
+
+ fn bind_texture(&self, target: GLenum, texture: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindTexture(target, texture);
+ }
+ }
+
+ // FIXME: Does not verify buffer size -- unsafe!
+ fn tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint,
+ format: GLenum,
+ ty: GLenum,
+ opt_data: Option<&[u8]>) {
+ match opt_data {
+ Some(data) => {
+ unsafe {
+ self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
+ data.as_ptr() as *const GLvoid);
+ }
+ }
+ None => {
+ unsafe {
+ self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
+ ptr::null());
+ }
+ }
+ }
+ }
+
+ fn compressed_tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLenum,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.CompressedTexImage2D(target, level, internal_format, width, height, border,
+ data.len() as GLsizei, data.as_ptr() as *const GLvoid);
+ }
+ }
+
+ fn compressed_tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ data.len() as GLsizei, data.as_ptr() as *const GLvoid);
+ }
+ }
+
+ // FIXME: Does not verify buffer size -- unsafe!
+ fn tex_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ depth: GLsizei,
+ border: GLint,
+ format: GLenum,
+ ty: GLenum,
+ opt_data: Option<&[u8]>) {
+ unsafe {
+ let pdata = match opt_data {
+ Some(data) => mem::transmute(data.as_ptr()),
+ None => ptr::null(),
+ };
+ self.ffi_gl_.TexImage3D(target,
+ level,
+ internal_format,
+ width,
+ height,
+ depth,
+ border,
+ format,
+ ty,
+ pdata);
+ }
+ }
+
+ fn copy_tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLenum,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint) {
+ unsafe {
+ self.ffi_gl_.CopyTexImage2D(target,
+ level,
+ internal_format,
+ x,
+ y,
+ width,
+ height,
+ border);
+ }
+ }
+
+ fn copy_tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.CopyTexSubImage2D(target,
+ level,
+ xoffset,
+ yoffset,
+ x,
+ y,
+ width,
+ height);
+ }
+ }
+
+ fn copy_tex_sub_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ zoffset: GLint,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.CopyTexSubImage3D(target,
+ level,
+ xoffset,
+ yoffset,
+ zoffset,
+ x,
+ y,
+ width,
+ height);
+ }
+ }
+
+ fn tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ ty: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, ty, data.as_ptr() as *const c_void);
+ }
+ }
+
+ fn tex_sub_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ zoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ depth: GLsizei,
+ format: GLenum,
+ ty: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.TexSubImage3D(target,
+ level,
+ xoffset,
+ yoffset,
+ zoffset,
+ width,
+ height,
+ depth,
+ format,
+ ty,
+ data.as_ptr() as *const c_void);
+ }
+ }
+
+ fn get_integer_v(&self, name: GLenum) -> GLint {
+ let mut result: GLint = 0 as GLint;
+ unsafe {
+ self.ffi_gl_.GetIntegerv(name, &mut result);
+ }
+ result
+ }
+
+ fn get_boolean_v(&self, name: GLenum) -> GLboolean {
+ let mut result: GLboolean = 0 as GLboolean;
+ unsafe {
+ self.ffi_gl_.GetBooleanv(name, &mut result);
+ }
+ result
+ }
+
+ fn get_float_v(&self, name: GLenum) -> GLfloat {
+ let mut result: GLfloat = 0 as GLfloat;
+ unsafe {
+ self.ffi_gl_.GetFloatv(name, &mut result);
+ }
+ result
+ }
+
+ fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
+ unsafe {
+ self.ffi_gl_.TexParameteri(target, pname, param);
+ }
+ }
+
+ fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
+ unsafe {
+ self.ffi_gl_.TexParameterf(target, pname, param);
+ }
+ }
+
+ fn framebuffer_texture_2d(&self,
+ target: GLenum,
+ attachment: GLenum,
+ textarget: GLenum,
+ texture: GLuint,
+ level: GLint) {
+ unsafe {
+ self.ffi_gl_.FramebufferTexture2D(target, attachment, textarget, texture, level);
+ }
+ }
+
+ fn framebuffer_texture_layer(&self,
+ target: GLenum,
+ attachment: GLenum,
+ texture: GLuint,
+ level: GLint,
+ layer: GLint) {
+ unsafe {
+ self.ffi_gl_.FramebufferTextureLayer(target, attachment, texture, level, layer);
+ }
+ }
+
+ fn blit_framebuffer(&self,
+ src_x0: GLint,
+ src_y0: GLint,
+ src_x1: GLint,
+ src_y1: GLint,
+ dst_x0: GLint,
+ dst_y0: GLint,
+ dst_x1: GLint,
+ dst_y1: GLint,
+ mask: GLbitfield,
+ filter: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlitFramebuffer(src_x0,
+ src_y0,
+ src_x1,
+ src_y1,
+ dst_x0,
+ dst_y0,
+ dst_x1,
+ dst_y1,
+ mask,
+ filter);
+ }
+ }
+
+ fn vertex_attrib_4f(&self,
+ index: GLuint,
+ x: GLfloat,
+ y: GLfloat,
+ z: GLfloat,
+ w: GLfloat) {
+ unsafe {
+ self.ffi_gl_.VertexAttrib4f(index, x, y, z, w)
+ }
+ }
+
+ fn vertex_attrib_pointer_f32(&self,
+ index: GLuint,
+ size: GLint,
+ normalized: bool,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribPointer(index,
+ size,
+ ffi::FLOAT,
+ normalized as GLboolean,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_pointer(&self,
+ index: GLuint,
+ size: GLint,
+ type_: GLenum,
+ normalized: bool,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribPointer(index,
+ size,
+ type_,
+ normalized as GLboolean,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_i_pointer(&self,
+ index: GLuint,
+ size: GLint,
+ type_: GLenum,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribIPointer(index,
+ size,
+ type_,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribDivisor(index, divisor)
+ }
+ }
+
+ fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.Viewport(x, y, width, height);
+ }
+ }
+
+ fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.Scissor(x, y, width, height);
+ }
+ }
+
+ fn line_width(&self, width: GLfloat) {
+ unsafe {
+ self.ffi_gl_.LineWidth(width);
+ }
+ }
+
+ fn use_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.UseProgram(program);
+ }
+ }
+
+ fn validate_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.ValidateProgram(program);
+ }
+ }
+
+ fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawArrays(mode, first, count);
+ }
+ }
+
+ fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawArraysInstanced(mode, first, count, primcount);
+ }
+ }
+
+ fn draw_elements(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint) {
+ unsafe {
+ return self.ffi_gl_.DrawElements(mode, count, element_type, indices_offset as *const c_void)
+ }
+ }
+
+ fn draw_elements_instanced(&self,
+ mode: GLenum,
+ count: GLsizei,
+ element_type: GLenum,
+ indices_offset: GLuint,
+ primcount: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawElementsInstanced(mode,
+ count,
+ element_type,
+ indices_offset as *const c_void,
+ primcount)
+ }
+ }
+
+ fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
+ unsafe {
+ self.ffi_gl_.BlendColor(r, g, b, a);
+ }
+ }
+
+ fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendFunc(sfactor, dfactor);
+ }
+ }
+
+ fn blend_func_separate(&self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
+ }
+ }
+
+ fn blend_equation(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendEquation(mode);
+ }
+ }
+
+ fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
+ }
+ }
+
+ fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
+ unsafe {
+ self.ffi_gl_.ColorMask(r as GLboolean, g as GLboolean, b as GLboolean, a as GLboolean);
+ }
+ }
+
+ fn cull_face(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.CullFace(mode);
+ }
+ }
+
+ fn front_face(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.FrontFace(mode);
+ }
+ }
+
+ fn enable(&self, cap: GLenum) {
+ unsafe {
+ self.ffi_gl_.Enable(cap);
+ }
+ }
+
+ fn disable(&self, cap: GLenum) {
+ unsafe {
+ self.ffi_gl_.Disable(cap);
+ }
+ }
+
+ fn hint(&self, param_name: GLenum, param_val: GLenum) {
+ unsafe {
+ self.ffi_gl_.Hint(param_name, param_val);
+ }
+ }
+
+ fn is_enabled(&self, cap: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsEnabled(cap)
+ }
+ }
+
+ fn is_shader(&self, shader: GLuint) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsShader(shader)
+ }
+ }
+
+ fn is_texture(&self, texture: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsTexture(texture)
+ }
+ }
+
+ fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsFramebuffer(framebuffer)
+ }
+ }
+
+ fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsRenderbuffer(renderbuffer)
+ }
+ }
+
+ fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
+ unsafe {
+ self.ffi_gl_.CheckFramebufferStatus(target)
+ }
+ }
+
+ fn enable_vertex_attrib_array(&self, index: GLuint) {
+ unsafe {
+ self.ffi_gl_.EnableVertexAttribArray(index);
+ }
+ }
+
+ fn disable_vertex_attrib_array(&self, index: GLuint) {
+ unsafe {
+ self.ffi_gl_.DisableVertexAttribArray(index);
+ }
+ }
+
+ fn uniform_1f(&self, location: GLint, v0: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform1f(location, v0);
+ }
+ }
+
+ fn uniform_1fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform1fv(location,
+ values.len() as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_1i(&self, location: GLint, v0: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform1i(location, v0);
+ }
+ }
+
+ fn uniform_1iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform1iv(location,
+ values.len() as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_1ui(&self, location: GLint, v0: GLuint) {
+ unsafe {
+ self.ffi_gl_.Uniform1ui(location, v0);
+ }
+ }
+
+ fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform2f(location, v0, v1);
+ }
+ }
+
+ fn uniform_2fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform2fv(location,
+ (values.len() / 2) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform2i(location, v0, v1);
+ }
+ }
+
+ fn uniform_2iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform2iv(location,
+ (values.len() / 2) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
+ unsafe {
+ self.ffi_gl_.Uniform2ui(location, v0, v1);
+ }
+ }
+
+ fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform3f(location, v0, v1, v2);
+ }
+ }
+
+ fn uniform_3fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform3fv(location,
+ (values.len() / 3) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform3i(location, v0, v1, v2);
+ }
+ }
+
+ fn uniform_3iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform3iv(location,
+ (values.len() / 3) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
+ unsafe {
+ self.ffi_gl_.Uniform3ui(location, v0, v1, v2);
+ }
+ }
+
+ fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform4f(location, x, y, z, w);
+ }
+ }
+
+ fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform4i(location, x, y, z, w);
+ }
+ }
+
+ fn uniform_4iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform4iv(location,
+ (values.len() / 4) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
+ unsafe {
+ self.ffi_gl_.Uniform4ui(location, x, y, z, w);
+ }
+ }
+
+ fn uniform_4fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform4fv(location,
+ (values.len() / 4) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix2fv(location,
+ (value.len() / 4) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix3fv(location,
+ (value.len() / 9) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix4fv(location,
+ (value.len() / 16) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn depth_mask(&self, flag: bool) {
+ unsafe {
+ self.ffi_gl_.DepthMask(flag as GLboolean);
+ }
+ }
+
+ fn depth_range(&self, near: f64, far: f64) {
+ unsafe {
+ self.ffi_gl_.DepthRange(near as GLclampd, far as GLclampd);
+ }
+ }
+
+ fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
+ let buf_size = self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH);
+ let mut name = vec![0u8; buf_size as usize];
+ let mut length = 0 as GLsizei;
+ let mut size = 0 as i32;
+ let mut type_ = 0 as u32;
+ unsafe {
+ self.ffi_gl_.GetActiveAttrib(program, index, buf_size, &mut length, &mut size, &mut type_, name.as_mut_ptr() as *mut GLchar);
+ }
+ name.truncate(if length > 0 {length as usize} else {0});
+ (size, type_, String::from_utf8(name).unwrap())
+ }
+
+ fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
+ let buf_size = self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH);
+ let mut name = vec![0 as u8; buf_size as usize];
+ let mut length: GLsizei = 0;
+ let mut size: i32 = 0;
+ let mut type_: u32 = 0;
+
+ unsafe {
+ self.ffi_gl_.GetActiveUniform(program, index, buf_size, &mut length, &mut size,
+ &mut type_, name.as_mut_ptr() as *mut GLchar);
+ }
+
+ name.truncate(if length > 0 { length as usize } else { 0 });
+
+ (size, type_, String::from_utf8(name).unwrap())
+ }
+
+ fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
+ let name = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetAttribLocation(program, name.as_ptr())
+ }
+ }
+
+ fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
+ let name = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetFragDataLocation(program, name.as_ptr())
+ }
+ }
+
+ fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
+ let name = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetUniformLocation(program, name.as_ptr())
+ }
+ }
+
+ fn get_program_info_log(&self, program: GLuint) -> String {
+ unsafe {
+ let mut result = vec![0u8; 1024];
+ let mut result_len: GLsizei = 0 as GLsizei;
+ self.ffi_gl_.GetProgramInfoLog(program,
+ 1024 as GLsizei,
+ &mut result_len,
+ result.as_mut_ptr() as *mut GLchar);
+ result.truncate(if result_len > 0 {result_len as usize} else {0});
+ String::from_utf8(result).unwrap()
+ }
+ }
+
+ fn get_program_iv(&self, program: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetProgramiv(program, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetVertexAttribiv(index, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum) -> Vec<GLfloat> {
+ unsafe {
+ let mut result = vec![0 as GLfloat; 4];
+ self.ffi_gl_.GetVertexAttribfv(index, pname, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetBufferParameteriv(target, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_shader_info_log(&self, shader: GLuint) -> String {
+ unsafe {
+ let mut result = vec![0u8; 1024];
+ let mut result_len: GLsizei = 0 as GLsizei;
+ self.ffi_gl_.GetShaderInfoLog(shader,
+ 1024 as GLsizei,
+ &mut result_len,
+ result.as_mut_ptr() as *mut GLchar);
+ result.truncate(if result_len > 0 {result_len as usize} else {0});
+ String::from_utf8(result).unwrap()
+ }
+ }
+
+ fn get_string(&self, which: GLenum) -> String {
+ unsafe {
+ let llstr = self.ffi_gl_.GetString(which);
+ if !llstr.is_null() {
+ return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()).to_string();
+ } else {
+ return "".to_string();
+ }
+ }
+ }
+
+ fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetShaderiv(shader, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn compile_shader(&self, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.CompileShader(shader);
+ }
+ }
+
+ fn create_program(&self) -> GLuint {
+ unsafe {
+ return self.ffi_gl_.CreateProgram();
+ }
+ }
+
+ fn delete_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.DeleteProgram(program);
+ }
+ }
+
+ fn create_shader(&self, shader_type: GLenum) -> GLuint {
+ unsafe {
+ return self.ffi_gl_.CreateShader(shader_type);
+ }
+ }
+
+ fn delete_shader(&self, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.DeleteShader(shader);
+ }
+ }
+
+ fn detach_shader(&self, program: GLuint, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.DetachShader(program, shader);
+ }
+ }
+
+ fn link_program(&self, program: GLuint) {
+ unsafe {
+ return self.ffi_gl_.LinkProgram(program);
+ }
+ }
+
+ fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
+ unsafe {
+ self.ffi_gl_.ClearColor(r, g, b, a);
+ }
+ }
+
+ fn clear(&self, buffer_mask: GLbitfield) {
+ unsafe {
+ self.ffi_gl_.Clear(buffer_mask);
+ }
+ }
+
+ fn clear_depth(&self, depth: f64) {
+ unsafe {
+ self.ffi_gl_.ClearDepth(depth as GLclampd);
+ }
+ }
+
+ fn clear_stencil(&self, s: GLint) {
+ unsafe {
+ self.ffi_gl_.ClearStencil(s);
+ }
+ }
+
+ fn flush(&self) {
+ unsafe {
+ self.ffi_gl_.Flush();
+ }
+ }
+
+ fn finish(&self) {
+ unsafe {
+ self.ffi_gl_.Finish();
+ }
+ }
+
+ fn get_error(&self) -> GLenum {
+ unsafe {
+ self.ffi_gl_.GetError()
+ }
+ }
+
+ fn stencil_mask(&self, mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilMask(mask)
+ }
+ }
+
+ fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilMaskSeparate(face, mask)
+ }
+ }
+
+ fn stencil_func(&self,
+ func: GLenum,
+ ref_: GLint,
+ mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilFunc(func, ref_, mask)
+ }
+ }
+
+ fn stencil_func_separate(&self,
+ face: GLenum,
+ func: GLenum,
+ ref_: GLint,
+ mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask)
+ }
+ }
+
+ fn stencil_op(&self,
+ sfail: GLenum,
+ dpfail: GLenum,
+ dppass: GLenum) {
+ unsafe {
+ self.ffi_gl_.StencilOp(sfail, dpfail, dppass)
+ }
+ }
+
+ fn stencil_op_separate(&self,
+ face: GLenum,
+ sfail: GLenum,
+ dpfail: GLenum,
+ dppass: GLenum) {
+ unsafe {
+ self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass)
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
+ panic!("not supported")
+ }
+
+ fn generate_mipmap(&self, target: GLenum) {
+ unsafe {
+ self.ffi_gl_.GenerateMipmap(target)
+ }
+ }
+
+ fn insert_event_marker_ext(&self, message: &str) {
+ if self.ffi_gl_.InsertEventMarkerEXT.is_loaded() {
+ unsafe {
+ self.ffi_gl_.InsertEventMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
+ }
+ }
+ }
+
+ fn push_group_marker_ext(&self, message: &str) {
+ if self.ffi_gl_.PushGroupMarkerEXT.is_loaded() {
+ unsafe {
+ self.ffi_gl_.PushGroupMarkerEXT(message.len() as GLsizei, message.as_ptr() as *const _);
+ }
+ }
+ }
+
+ fn pop_group_marker_ext(&self) {
+ if self.ffi_gl_.PopGroupMarkerEXT.is_loaded() {
+ unsafe {
+ self.ffi_gl_.PopGroupMarkerEXT();
+ }
+ }
+ }
+}
+
new file mode 100644
--- /dev/null
+++ b/third_party/rust/gleam/src/gles_fns.rs
@@ -0,0 +1,1304 @@
+// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct GlesFns {
+ ffi_gl_: GlesFfi,
+}
+
+impl GlesFns
+{
+ pub unsafe fn load_with<'a, F>(loadfn: F) -> Rc<Gl> where F: FnMut(&str) -> *const c_void {
+ let ffi_gl_ = GlesFfi::load_with(loadfn);
+ Rc::new(GlesFns {
+ ffi_gl_: ffi_gl_,
+ }) as Rc<Gl>
+ }
+}
+
+#[cfg(target_os="android")]
+extern {
+ fn glEGLImageTargetTexture2DOES(target: GLenum, image: GLeglImageOES);
+}
+
+impl Gl for GlesFns {
+ fn get_type(&self) -> GlType {
+ GlType::Gles
+ }
+
+ fn buffer_data_untyped(&self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, usage: GLenum) {
+ unsafe {
+ self.ffi_gl_.BufferData(target,
+ size,
+ data,
+ usage);
+ }
+ }
+
+ fn buffer_sub_data_untyped(&self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid) {
+ unsafe {
+ self.ffi_gl_.BufferSubData(target,
+ offset,
+ size,
+ data);
+ }
+ }
+
+ fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
+ let pointers: Vec<*const u8> = strings.iter().map(|string| (*string).as_ptr()).collect();
+ let lengths: Vec<GLint> = strings.iter().map(|string| string.len() as GLint).collect();
+ unsafe {
+ self.ffi_gl_.ShaderSource(shader, pointers.len() as GLsizei,
+ pointers.as_ptr() as *const *const GLchar, lengths.as_ptr());
+ }
+ drop(lengths);
+ drop(pointers);
+ }
+
+ #[allow(unused_variables)]
+ fn read_buffer(&self, mode: GLenum) {
+ panic!("not supported")
+ }
+
+ fn read_pixels_into_buffer(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei,
+ format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8]) {
+ // Assumes that the user properly allocated the size for dst_buffer.
+ assert!(calculate_length(width, height, format, pixel_type) == dst_buffer.len());
+
+ unsafe {
+ // We don't want any alignment padding on pixel rows.
+ self.ffi_gl_.PixelStorei(ffi::PACK_ALIGNMENT, 1);
+ self.ffi_gl_.ReadPixels(x, y, width, height, format, pixel_type, dst_buffer.as_mut_ptr() as *mut c_void);
+ }
+ }
+
+ fn read_pixels(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8> {
+ let len = calculate_length(width, height, format, pixel_type);
+ let mut pixels: Vec<u8> = Vec::new();
+ pixels.reserve(len);
+ unsafe { pixels.set_len(len); }
+
+ self.read_pixels_into_buffer(x, y, width, height, format, pixel_type, pixels.as_mut_slice());
+
+ pixels
+ }
+
+ fn sample_coverage(&self, value: GLclampf, invert: bool) {
+ unsafe {
+ self.ffi_gl_.SampleCoverage(value, invert as GLboolean);
+ }
+ }
+
+ fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
+ unsafe {
+ self.ffi_gl_.PolygonOffset(factor, units);
+ }
+ }
+
+ fn pixel_store_i(&self, name: GLenum, param: GLint) {
+ unsafe {
+ self.ffi_gl_.PixelStorei(name, param);
+ }
+ }
+
+ fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenBuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenRenderbuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenFramebuffers(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenTextures(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
+ unsafe {
+ let mut result: Vec<_> = repeat(0 as GLuint).take(n as usize).collect();
+ self.ffi_gl_.GenVertexArrays(n, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn begin_query(&self, target: GLenum, id: GLuint) {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn end_query(&self, target: GLenum) {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn query_counter(&self, id: GLuint, target: GLenum) {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
+ panic!("not supported")
+ }
+
+ #[allow(unused_variables)]
+ fn delete_queries(&self, queries: &[GLuint]) {
+ panic!("not supported")
+ }
+
+ fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteVertexArrays(vertex_arrays.len() as GLsizei, vertex_arrays.as_ptr());
+ }
+ }
+
+ fn delete_buffers(&self, buffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteBuffers(buffers.len() as GLsizei, buffers.as_ptr());
+ }
+ }
+
+ fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteRenderbuffers(renderbuffers.len() as GLsizei, renderbuffers.as_ptr());
+ }
+ }
+
+ fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteFramebuffers(framebuffers.len() as GLsizei, framebuffers.as_ptr());
+ }
+ }
+
+ fn delete_textures(&self, textures: &[GLuint]) {
+ unsafe {
+ self.ffi_gl_.DeleteTextures(textures.len() as GLsizei, textures.as_ptr());
+ }
+ }
+
+ fn framebuffer_renderbuffer(&self,
+ target: GLenum,
+ attachment: GLenum,
+ renderbuffertarget: GLenum,
+ renderbuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.FramebufferRenderbuffer(target,
+ attachment,
+ renderbuffertarget,
+ renderbuffer);
+ }
+ }
+
+ fn renderbuffer_storage(&self,
+ target: GLenum,
+ internalformat: GLenum,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.RenderbufferStorage(target,
+ internalformat,
+ width,
+ height);
+ }
+ }
+
+ fn depth_func(&self, func: GLenum) {
+ unsafe {
+ self.ffi_gl_.DepthFunc(func);
+ }
+ }
+
+ fn active_texture(&self, texture: GLenum) {
+ unsafe {
+ self.ffi_gl_.ActiveTexture(texture);
+ }
+ }
+
+ fn attach_shader(&self, program: GLuint, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.AttachShader(program, shader);
+ }
+ }
+
+ fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
+ let c_string = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.BindAttribLocation(program, index, c_string.as_ptr())
+ }
+ }
+
+ fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
+ let c_string = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetUniformBlockIndex(program, c_string.as_ptr())
+ }
+ }
+
+ fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindBufferBase(target, index, buffer);
+ }
+ }
+
+ fn uniform_block_binding(&self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint) {
+ unsafe {
+ self.ffi_gl_.UniformBlockBinding(program, uniform_block_index, uniform_block_binding);
+ }
+ }
+
+ fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindBuffer(target, buffer);
+ }
+ }
+
+ fn bind_vertex_array(&self, vao: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindVertexArray(vao);
+ }
+ }
+
+ fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindRenderbuffer(target, renderbuffer);
+ }
+ }
+
+ fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindFramebuffer(target, framebuffer);
+ }
+ }
+
+ fn bind_texture(&self, target: GLenum, texture: GLuint) {
+ unsafe {
+ self.ffi_gl_.BindTexture(target, texture);
+ }
+ }
+
+ // FIXME: Does not verify buffer size -- unsafe!
+ fn tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint,
+ format: GLenum,
+ ty: GLenum,
+ opt_data: Option<&[u8]>) {
+ match opt_data {
+ Some(data) => {
+ unsafe {
+ self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
+ data.as_ptr() as *const GLvoid);
+ }
+ }
+ None => {
+ unsafe {
+ self.ffi_gl_.TexImage2D(target, level, internal_format, width, height, border, format, ty,
+ ptr::null());
+ }
+ }
+ }
+ }
+
+ fn compressed_tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLenum,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.CompressedTexImage2D(target, level, internal_format, width, height, border,
+ data.len() as GLsizei, data.as_ptr() as *const GLvoid);
+ }
+ }
+
+ fn compressed_tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ data.len() as GLsizei, data.as_ptr() as *const GLvoid);
+ }
+ }
+
+ // FIXME: Does not verify buffer size -- unsafe!
+ fn tex_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ depth: GLsizei,
+ border: GLint,
+ format: GLenum,
+ ty: GLenum,
+ opt_data: Option<&[u8]>) {
+ unsafe {
+ let pdata = match opt_data {
+ Some(data) => mem::transmute(data.as_ptr()),
+ None => ptr::null(),
+ };
+ self.ffi_gl_.TexImage3D(target,
+ level,
+ internal_format,
+ width,
+ height,
+ depth,
+ border,
+ format,
+ ty,
+ pdata);
+ }
+ }
+
+ fn copy_tex_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ internal_format: GLenum,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ border: GLint) {
+ unsafe {
+ self.ffi_gl_.CopyTexImage2D(target,
+ level,
+ internal_format,
+ x,
+ y,
+ width,
+ height,
+ border);
+ }
+ }
+
+ fn copy_tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.CopyTexSubImage2D(target,
+ level,
+ xoffset,
+ yoffset,
+ x,
+ y,
+ width,
+ height);
+ }
+ }
+
+ fn copy_tex_sub_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ zoffset: GLint,
+ x: GLint,
+ y: GLint,
+ width: GLsizei,
+ height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.CopyTexSubImage3D(target,
+ level,
+ xoffset,
+ yoffset,
+ zoffset,
+ x,
+ y,
+ width,
+ height);
+ }
+ }
+
+ fn tex_sub_image_2d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ format: GLenum,
+ ty: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, ty, data.as_ptr() as *const c_void);
+ }
+ }
+
+ fn tex_sub_image_3d(&self,
+ target: GLenum,
+ level: GLint,
+ xoffset: GLint,
+ yoffset: GLint,
+ zoffset: GLint,
+ width: GLsizei,
+ height: GLsizei,
+ depth: GLsizei,
+ format: GLenum,
+ ty: GLenum,
+ data: &[u8]) {
+ unsafe {
+ self.ffi_gl_.TexSubImage3D(target,
+ level,
+ xoffset,
+ yoffset,
+ zoffset,
+ width,
+ height,
+ depth,
+ format,
+ ty,
+ data.as_ptr() as *const c_void);
+ }
+ }
+
+ fn get_integer_v(&self, name: GLenum) -> GLint {
+ let mut result: GLint = 0 as GLint;
+ unsafe {
+ self.ffi_gl_.GetIntegerv(name, &mut result);
+ }
+ result
+ }
+
+ fn get_boolean_v(&self, name: GLenum) -> GLboolean {
+ let mut result: GLboolean = 0 as GLboolean;
+ unsafe {
+ self.ffi_gl_.GetBooleanv(name, &mut result);
+ }
+ result
+ }
+
+ fn get_float_v(&self, name: GLenum) -> GLfloat {
+ let mut result: GLfloat = 0 as GLfloat;
+ unsafe {
+ self.ffi_gl_.GetFloatv(name, &mut result);
+ }
+ result
+ }
+
+ fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
+ unsafe {
+ self.ffi_gl_.TexParameteri(target, pname, param);
+ }
+ }
+
+ fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
+ unsafe {
+ self.ffi_gl_.TexParameterf(target, pname, param);
+ }
+ }
+
+ fn framebuffer_texture_2d(&self,
+ target: GLenum,
+ attachment: GLenum,
+ textarget: GLenum,
+ texture: GLuint,
+ level: GLint) {
+ unsafe {
+ self.ffi_gl_.FramebufferTexture2D(target, attachment, textarget, texture, level);
+ }
+ }
+
+ fn framebuffer_texture_layer(&self,
+ target: GLenum,
+ attachment: GLenum,
+ texture: GLuint,
+ level: GLint,
+ layer: GLint) {
+ unsafe {
+ self.ffi_gl_.FramebufferTextureLayer(target, attachment, texture, level, layer);
+ }
+ }
+
+ fn blit_framebuffer(&self,
+ src_x0: GLint,
+ src_y0: GLint,
+ src_x1: GLint,
+ src_y1: GLint,
+ dst_x0: GLint,
+ dst_y0: GLint,
+ dst_x1: GLint,
+ dst_y1: GLint,
+ mask: GLbitfield,
+ filter: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlitFramebuffer(src_x0,
+ src_y0,
+ src_x1,
+ src_y1,
+ dst_x0,
+ dst_y0,
+ dst_x1,
+ dst_y1,
+ mask,
+ filter);
+ }
+ }
+
+ fn vertex_attrib_4f(&self,
+ index: GLuint,
+ x: GLfloat,
+ y: GLfloat,
+ z: GLfloat,
+ w: GLfloat) {
+ unsafe {
+ self.ffi_gl_.VertexAttrib4f(index, x, y, z, w)
+ }
+ }
+
+ fn vertex_attrib_pointer_f32(&self,
+ index: GLuint,
+ size: GLint,
+ normalized: bool,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribPointer(index,
+ size,
+ ffi::FLOAT,
+ normalized as GLboolean,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_pointer(&self,
+ index: GLuint,
+ size: GLint,
+ type_: GLenum,
+ normalized: bool,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribPointer(index,
+ size,
+ type_,
+ normalized as GLboolean,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_i_pointer(&self,
+ index: GLuint,
+ size: GLint,
+ type_: GLenum,
+ stride: GLsizei,
+ offset: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribIPointer(index,
+ size,
+ type_,
+ stride,
+ offset as *const GLvoid)
+ }
+ }
+
+ fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
+ unsafe {
+ self.ffi_gl_.VertexAttribDivisor(index, divisor)
+ }
+ }
+
+ fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.Viewport(x, y, width, height);
+ }
+ }
+
+ fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
+ unsafe {
+ self.ffi_gl_.Scissor(x, y, width, height);
+ }
+ }
+
+ fn line_width(&self, width: GLfloat) {
+ unsafe {
+ self.ffi_gl_.LineWidth(width);
+ }
+ }
+
+ fn use_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.UseProgram(program);
+ }
+ }
+
+ fn validate_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.ValidateProgram(program);
+ }
+ }
+
+ fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawArrays(mode, first, count);
+ }
+ }
+
+ fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawArraysInstanced(mode, first, count, primcount);
+ }
+ }
+
+ fn draw_elements(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint) {
+ unsafe {
+ return self.ffi_gl_.DrawElements(mode, count, element_type, indices_offset as *const c_void)
+ }
+ }
+
+ fn draw_elements_instanced(&self,
+ mode: GLenum,
+ count: GLsizei,
+ element_type: GLenum,
+ indices_offset: GLuint,
+ primcount: GLsizei) {
+ unsafe {
+ return self.ffi_gl_.DrawElementsInstanced(mode,
+ count,
+ element_type,
+ indices_offset as *const c_void,
+ primcount)
+ }
+ }
+
+ fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
+ unsafe {
+ self.ffi_gl_.BlendColor(r, g, b, a);
+ }
+ }
+
+ fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendFunc(sfactor, dfactor);
+ }
+ }
+
+ fn blend_func_separate(&self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha);
+ }
+ }
+
+ fn blend_equation(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendEquation(mode);
+ }
+ }
+
+ fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
+ unsafe {
+ self.ffi_gl_.BlendEquationSeparate(mode_rgb, mode_alpha);
+ }
+ }
+
+ fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
+ unsafe {
+ self.ffi_gl_.ColorMask(r as GLboolean, g as GLboolean, b as GLboolean, a as GLboolean);
+ }
+ }
+
+ fn cull_face(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.CullFace(mode);
+ }
+ }
+
+ fn front_face(&self, mode: GLenum) {
+ unsafe {
+ self.ffi_gl_.FrontFace(mode);
+ }
+ }
+
+ fn enable(&self, cap: GLenum) {
+ unsafe {
+ self.ffi_gl_.Enable(cap);
+ }
+ }
+
+ fn disable(&self, cap: GLenum) {
+ unsafe {
+ self.ffi_gl_.Disable(cap);
+ }
+ }
+
+ fn hint(&self, param_name: GLenum, param_val: GLenum) {
+ unsafe {
+ self.ffi_gl_.Hint(param_name, param_val);
+ }
+ }
+
+ fn is_enabled(&self, cap: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsEnabled(cap)
+ }
+ }
+
+ fn is_shader(&self, shader: GLuint) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsShader(shader)
+ }
+ }
+
+ fn is_texture(&self, texture: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsTexture(texture)
+ }
+ }
+
+ fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsFramebuffer(framebuffer)
+ }
+ }
+
+ fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
+ unsafe {
+ self.ffi_gl_.IsRenderbuffer(renderbuffer)
+ }
+ }
+
+ fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
+ unsafe {
+ self.ffi_gl_.CheckFramebufferStatus(target)
+ }
+ }
+
+ fn enable_vertex_attrib_array(&self, index: GLuint) {
+ unsafe {
+ self.ffi_gl_.EnableVertexAttribArray(index);
+ }
+ }
+
+ fn disable_vertex_attrib_array(&self, index: GLuint) {
+ unsafe {
+ self.ffi_gl_.DisableVertexAttribArray(index);
+ }
+ }
+
+ fn uniform_1f(&self, location: GLint, v0: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform1f(location, v0);
+ }
+ }
+
+ fn uniform_1fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform1fv(location,
+ values.len() as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_1i(&self, location: GLint, v0: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform1i(location, v0);
+ }
+ }
+
+ fn uniform_1iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform1iv(location,
+ values.len() as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn uniform_1ui(&self, location: GLint, v0: GLuint) {
+ panic!("not supported")
+ }
+
+ fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform2f(location, v0, v1);
+ }
+ }
+
+ fn uniform_2fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform2fv(location,
+ (values.len() / 2) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform2i(location, v0, v1);
+ }
+ }
+
+ fn uniform_2iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform2iv(location,
+ (values.len() / 2) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
+ panic!("not supported")
+ }
+
+ fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform3f(location, v0, v1, v2);
+ }
+ }
+
+ fn uniform_3fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform3fv(location,
+ (values.len() / 3) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform3i(location, v0, v1, v2);
+ }
+ }
+
+ fn uniform_3iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform3iv(location,
+ (values.len() / 3) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
+ panic!("not supported")
+ }
+
+ fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
+ unsafe {
+ self.ffi_gl_.Uniform4f(location, x, y, z, w);
+ }
+ }
+
+ fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
+ unsafe {
+ self.ffi_gl_.Uniform4i(location, x, y, z, w);
+ }
+ }
+
+ fn uniform_4iv(&self, location: GLint, values: &[i32]) {
+ unsafe {
+ self.ffi_gl_.Uniform4iv(location,
+ (values.len() / 4) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
+ panic!("not supported")
+ }
+
+ fn uniform_4fv(&self, location: GLint, values: &[f32]) {
+ unsafe {
+ self.ffi_gl_.Uniform4fv(location,
+ (values.len() / 4) as GLsizei,
+ values.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix2fv(location,
+ (value.len() / 4) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix3fv(location,
+ (value.len() / 9) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
+ unsafe {
+ self.ffi_gl_.UniformMatrix4fv(location,
+ (value.len() / 16) as GLsizei,
+ transpose as GLboolean,
+ value.as_ptr());
+ }
+ }
+
+ fn depth_mask(&self, flag: bool) {
+ unsafe {
+ self.ffi_gl_.DepthMask(flag as GLboolean);
+ }
+ }
+
+ fn depth_range(&self, near: f64, far: f64) {
+ unsafe {
+ self.ffi_gl_.DepthRangef(near as GLclampf, far as GLclampf);
+ }
+ }
+
+ fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
+ let buf_size = self.get_program_iv(program, ffi::ACTIVE_ATTRIBUTE_MAX_LENGTH);
+ let mut name = vec![0u8; buf_size as usize];
+ let mut length = 0 as GLsizei;
+ let mut size = 0 as i32;
+ let mut type_ = 0 as u32;
+ unsafe {
+ self.ffi_gl_.GetActiveAttrib(program, index, buf_size, &mut length, &mut size, &mut type_, name.as_mut_ptr() as *mut GLchar);
+ }
+ name.truncate(if length > 0 {length as usize} else {0});
+ (size, type_, String::from_utf8(name).unwrap())
+ }
+
+ fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
+ let buf_size = self.get_program_iv(program, ffi::ACTIVE_UNIFORM_MAX_LENGTH);
+ let mut name = vec![0 as u8; buf_size as usize];
+ let mut length: GLsizei = 0;
+ let mut size: i32 = 0;
+ let mut type_: u32 = 0;
+
+ unsafe {
+ self.ffi_gl_.GetActiveUniform(program, index, buf_size, &mut length, &mut size,
+ &mut type_, name.as_mut_ptr() as *mut GLchar);
+ }
+
+ name.truncate(if length > 0 { length as usize } else { 0 });
+
+ (size, type_, String::from_utf8(name).unwrap())
+ }
+
+ fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
+ let name = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetAttribLocation(program, name.as_ptr())
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
+ panic!("not supported")
+ }
+
+ fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
+ let name = CString::new(name).unwrap();
+ unsafe {
+ self.ffi_gl_.GetUniformLocation(program, name.as_ptr())
+ }
+ }
+
+ fn get_program_info_log(&self, program: GLuint) -> String {
+ unsafe {
+ let mut result = vec![0u8; 1024];
+ let mut result_len: GLsizei = 0 as GLsizei;
+ self.ffi_gl_.GetProgramInfoLog(program,
+ 1024 as GLsizei,
+ &mut result_len,
+ result.as_mut_ptr() as *mut GLchar);
+ result.truncate(if result_len > 0 {result_len as usize} else {0});
+ String::from_utf8(result).unwrap()
+ }
+ }
+
+ fn get_program_iv(&self, program: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetProgramiv(program, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetVertexAttribiv(index, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum) -> Vec<GLfloat> {
+ unsafe {
+ let mut result = vec![0 as GLfloat; 4];
+ self.ffi_gl_.GetVertexAttribfv(index, pname, result.as_mut_ptr());
+ return result;
+ }
+ }
+
+ fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetBufferParameteriv(target, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn get_shader_info_log(&self, shader: GLuint) -> String {
+ unsafe {
+ let mut result = vec![0u8; 1024];
+ let mut result_len: GLsizei = 0 as GLsizei;
+ self.ffi_gl_.GetShaderInfoLog(shader,
+ 1024 as GLsizei,
+ &mut result_len,
+ result.as_mut_ptr() as *mut GLchar);
+ result.truncate(if result_len > 0 {result_len as usize} else {0});
+ String::from_utf8(result).unwrap()
+ }
+ }
+
+ fn get_string(&self, which: GLenum) -> String {
+ unsafe {
+ let llstr = self.ffi_gl_.GetString(which);
+ if !llstr.is_null() {
+ return str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()).to_string();
+ } else {
+ return "".to_string();
+ }
+ }
+ }
+
+ fn get_shader_iv(&self, shader: GLuint, pname: GLenum) -> GLint {
+ unsafe {
+ let mut result: GLint = 0 as GLint;
+ self.ffi_gl_.GetShaderiv(shader, pname, &mut result);
+ return result;
+ }
+ }
+
+ fn compile_shader(&self, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.CompileShader(shader);
+ }
+ }
+
+ fn create_program(&self) -> GLuint {
+ unsafe {
+ return self.ffi_gl_.CreateProgram();
+ }
+ }
+
+ fn delete_program(&self, program: GLuint) {
+ unsafe {
+ self.ffi_gl_.DeleteProgram(program);
+ }
+ }
+
+ fn create_shader(&self, shader_type: GLenum) -> GLuint {
+ unsafe {
+ return self.ffi_gl_.CreateShader(shader_type);
+ }
+ }
+
+ fn delete_shader(&self, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.DeleteShader(shader);
+ }
+ }
+
+ fn detach_shader(&self, program: GLuint, shader: GLuint) {
+ unsafe {
+ self.ffi_gl_.DetachShader(program, shader);
+ }
+ }
+
+ fn link_program(&self, program: GLuint) {
+ unsafe {
+ return self.ffi_gl_.LinkProgram(program);
+ }
+ }
+
+ fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
+ unsafe {
+ self.ffi_gl_.ClearColor(r, g, b, a);
+ }
+ }
+
+ fn clear(&self, buffer_mask: GLbitfield) {
+ unsafe {
+ self.ffi_gl_.Clear(buffer_mask);
+ }
+ }
+
+ fn clear_depth(&self, depth: f64) {
+ unsafe {
+ self.ffi_gl_.ClearDepthf(depth as GLclampf);
+ }
+ }
+
+ fn clear_stencil(&self, s: GLint) {
+ unsafe {
+ self.ffi_gl_.ClearStencil(s);
+ }
+ }
+
+ fn flush(&self) {
+ unsafe {
+ self.ffi_gl_.Flush();
+ }
+ }
+
+ fn finish(&self) {
+ unsafe {
+ self.ffi_gl_.Finish();
+ }
+ }
+
+ fn get_error(&self) -> GLenum {
+ unsafe {
+ self.ffi_gl_.GetError()
+ }
+ }
+
+ fn stencil_mask(&self, mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilMask(mask)
+ }
+ }
+
+ fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilMaskSeparate(face, mask)
+ }
+ }
+
+ fn stencil_func(&self,
+ func: GLenum,
+ ref_: GLint,
+ mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilFunc(func, ref_, mask)
+ }
+ }
+
+ fn stencil_func_separate(&self,
+ face: GLenum,
+ func: GLenum,
+ ref_: GLint,
+ mask: GLuint) {
+ unsafe {
+ self.ffi_gl_.StencilFuncSeparate(face, func, ref_, mask)
+ }
+ }
+
+ fn stencil_op(&self,
+ sfail: GLenum,
+ dpfail: GLenum,
+ dppass: GLenum) {
+ unsafe {
+ self.ffi_gl_.StencilOp(sfail, dpfail, dppass)
+ }
+ }
+
+ fn stencil_op_separate(&self,
+ face: GLenum,
+ sfail: GLenum,
+ dpfail: GLenum,
+ dppass: GLenum) {
+ unsafe {
+ self.ffi_gl_.StencilOpSeparate(face, sfail, dpfail, dppass)
+ }
+ }
+
+ #[allow(unused_variables)]
+ #[cfg(not(target_os="android"))]
+ fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
+ panic!("not supported")
+ }
+
+ #[cfg(target_os="android")]
+ fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
+ unsafe {
+ glEGLImageTargetTexture2DOES(target, image);
+ }
+ }
+
+ fn generate_mipmap(&self, target: GLenum) {
+ unsafe {
+ self.ffi_gl_.GenerateMipmap(target)
+ }
+ }
+
+ #[allow(unused_variables)]
+ fn insert_event_marker_ext(&self, message: &str) {
+ }
+
+ #[allow(unused_variables)]
+ fn push_group_marker_ext(&self, message: &str) {
+ }
+
+ #[allow(unused_variables)]
+ fn pop_group_marker_ext(&self) {
+ }
+}
+
--- a/third_party/rust/gleam/src/lib.rs
+++ b/third_party/rust/gleam/src/lib.rs
@@ -8,10 +8,18 @@
// except according to those terms.
#![crate_name = "gleam"]
#![crate_type = "lib"]
pub mod gl;
mod ffi {
+ include!(concat!(env!("OUT_DIR"), "/gl_and_gles_bindings.rs"));
+}
+
+mod ffi_gl {
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}
+
+mod ffi_gles {
+ include!(concat!(env!("OUT_DIR"), "/gles_bindings.rs"));
+}
--- a/third_party/rust/offscreen_gl_context/.cargo-checksum.json
+++ b/third_party/rust/offscreen_gl_context/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"9b8376fc479996f32f8a690e6009fc2f7e9f6dc1b1224e0180a92ad65b0b2183","Cargo.toml":"2377d25abb4a8cd857355e101af61480e9e5718e1d5fcfb12e41993b8ec211c9","Makefile":"85b6d903eecac170ac97f10d9d89b8366cd91f5ea2f7c6212704bc590b64cf50","README.md":"614cf0c6242be3e62e45a3d60ce9a2a1581bdc46b28b25d5f40caba558e4d615","build.rs":"86776b47fac1d9368e3c3c5d57c62731729ed859bb1c4e4db0fe219251812cab","src/draw_buffer.rs":"52bef86972f40e0dd13a6e81f3aa76d4d0c28ea0b63f5f9da9650a34d75488c0","src/gl_context.rs":"28953e3752ea7fd2b19327f98c06fe53f7618efc4d3f0cb2262eba403756df2a","src/gl_context_attributes.rs":"8ddf99864f838ba847783d824e85eb71c8eea7d5dfb9950737dfb1472a33a4f6","src/gl_context_capabilities.rs":"9f665ad04d42d47d15ecbd430639d95da526ec5951f0b7abe2434adc1415c85d","src/gl_feature.rs":"b826884900c0e8d6317a41ebb6c30bdb468601bf1c030c376749bdb2ecd2f15a","src/gl_formats.rs":"d15a8e102ebac82c166be4ba2a6e6702a82d509ac61102157c26a0ae25f54ac7","src/gl_limits.rs":"ccecc941207f1f27d9eaf96f0ffadb03d991ab5e6ad2ef73a5af1b9dbbbd7cad","src/lib.rs":"daaf4e26504dbb97f3803de4337f601d616adf0633e5c4415c2c172fb257ebd6","src/platform/mod.rs":"f6ec310e5b8fb519607b8e4d5ca71a0c07c83737a83c3785b5b44e7902498c8a","src/platform/not_implemented/mod.rs":"d576e9fc3164f9e2a8ff9460a60eaa8ecada44c600de1a4d1bb5513ab93569af","src/platform/not_implemented/native_gl_context.rs":"fe018722b8bebbd59b6fae759dd78b0175d10bf110205b113ff155fd06d0f75d","src/platform/with_cgl/mod.rs":"b05dc146c9ba82d62410d9b0566a8aa70c77e7ec583ad4881c531d7118454543","src/platform/with_cgl/native_gl_context.rs":"c6271cfa96836d8f833f5efbc90352852557d582db41d2c513cc36c3f966ae88","src/platform/with_egl/mod.rs":"c52ac147eb051733070c36b2c62be8c57427f80999507f62a9ce801f4aac284c","src/platform/with_egl/native_gl_context.rs":"3a8342d53de9525a5478cc96b323dbad2b3628aa6655fe5f092834cc72256116","src/platform/with_egl/utils.rs":"508521e2bf3809ffe0dfea4fa4a358903f49c77a33aa42cc6c0e7458d992a2a7","src/platform/with_glx/mod.rs":"0e497f38b2071ed189995c91b27b0b199d31bfcc10836e2d26b55023d7aff503","src/platform/with_glx/native_gl_context.rs":"2c648ae18baac14290b2eca3581d474adfea00a29a7ad47a1100e564e74b9152","src/platform/with_glx/utils.rs":"eb81e0a4c62947fa5099c241cfe2e4dd075376d30b22864e042c0f536ac6be58","src/platform/with_osmesa/mod.rs":"9f6d69878125185f16740f52ba5cdd8a45e8812af1a3561482c9b43edaf4514a","src/platform/with_wgl/mod.rs":"38f9b44b54c8a1bd4d25ae77a4ea6a2e5454a00b816764d7d74152c1f3c1b126","src/platform/with_wgl/native_gl_context.rs":"4aecd40a811cf38607b17db9724f79bb934e056f85c90c987b2aa82d637b7bb4","src/platform/with_wgl/utils.rs":"d9640c000dcb513cf0a13c4a0d35c423366b7d0894deff299affe0202bdeb770","src/platform/with_wgl/wgl_attributes.rs":"73b75da18519e048011e9c303e402cf7961e3652aa8f4d4ebf507b4ab83d06a3","src/tests.rs":"a2e5ceecd6b12def2f66a5c576b4ad8ca0dce1834aebe69ebc8474a5c06ec798"},"package":"4ac875ea951d7d695a1cc8c370777d6a0e2b7355ca49506034683df09b24b1bc"}
\ No newline at end of file
+{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"7150ee9391a955b2ef7e0762fc61c0c1aab167620ca36d88d78062d93b8334ba",".travis.yml":"9b8376fc479996f32f8a690e6009fc2f7e9f6dc1b1224e0180a92ad65b0b2183","Cargo.toml":"c9adde499850222639dec26ff52a2f7c2285a970095a437231856bf3182eb3c6","Makefile":"85b6d903eecac170ac97f10d9d89b8366cd91f5ea2f7c6212704bc590b64cf50","README.md":"614cf0c6242be3e62e45a3d60ce9a2a1581bdc46b28b25d5f40caba558e4d615","build.rs":"95e0820ac2e24e0a4951b92454bbf4eb0967d389a4bc358a844156e5f425bd56","src/draw_buffer.rs":"4b3c61b230e4b4f025ec60b594489570b0ea159e1dada5910d3c0edadbaf6542","src/gl_context.rs":"633392d4b558d89877f70125f799a9c6f1788505d6837456e359198f028884d0","src/gl_context_attributes.rs":"8ddf99864f838ba847783d824e85eb71c8eea7d5dfb9950737dfb1472a33a4f6","src/gl_context_capabilities.rs":"9f665ad04d42d47d15ecbd430639d95da526ec5951f0b7abe2434adc1415c85d","src/gl_feature.rs":"b826884900c0e8d6317a41ebb6c30bdb468601bf1c030c376749bdb2ecd2f15a","src/gl_formats.rs":"d15a8e102ebac82c166be4ba2a6e6702a82d509ac61102157c26a0ae25f54ac7","src/gl_limits.rs":"a7837b11ded456ce454d9beb642359ac1ca755262654ac53bca371dd55b2d172","src/lib.rs":"9d66fc08d6fe533644e2f7dec11e3cdc6f2f237b2fb0bb1fc5996a933c87ab8e","src/platform/mod.rs":"29887128ed1e0c77b5b5dcd1bfc39ef0a53598db5325d76b71f5a772b480789b","src/platform/not_implemented/mod.rs":"d576e9fc3164f9e2a8ff9460a60eaa8ecada44c600de1a4d1bb5513ab93569af","src/platform/not_implemented/native_gl_context.rs":"fe018722b8bebbd59b6fae759dd78b0175d10bf110205b113ff155fd06d0f75d","src/platform/with_cgl/mod.rs":"b05dc146c9ba82d62410d9b0566a8aa70c77e7ec583ad4881c531d7118454543","src/platform/with_cgl/native_gl_context.rs":"c6271cfa96836d8f833f5efbc90352852557d582db41d2c513cc36c3f966ae88","src/platform/with_egl/mod.rs":"c52ac147eb051733070c36b2c62be8c57427f80999507f62a9ce801f4aac284c","src/platform/with_egl/native_gl_context.rs":"3a8342d53de9525a5478cc96b323dbad2b3628aa6655fe5f092834cc72256116","src/platform/with_egl/utils.rs":"508521e2bf3809ffe0dfea4fa4a358903f49c77a33aa42cc6c0e7458d992a2a7","src/platform/with_glx/mod.rs":"0e497f38b2071ed189995c91b27b0b199d31bfcc10836e2d26b55023d7aff503","src/platform/with_glx/native_gl_context.rs":"2c648ae18baac14290b2eca3581d474adfea00a29a7ad47a1100e564e74b9152","src/platform/with_glx/utils.rs":"eb81e0a4c62947fa5099c241cfe2e4dd075376d30b22864e042c0f536ac6be58","src/platform/with_osmesa/mod.rs":"995c1f1af7cb113e51f154796f65e95e145f4b25ea32354756f3380e9a7764b5","src/platform/with_wgl/mod.rs":"38f9b44b54c8a1bd4d25ae77a4ea6a2e5454a00b816764d7d74152c1f3c1b126","src/platform/with_wgl/native_gl_context.rs":"4aecd40a811cf38607b17db9724f79bb934e056f85c90c987b2aa82d637b7bb4","src/platform/with_wgl/utils.rs":"d9640c000dcb513cf0a13c4a0d35c423366b7d0894deff299affe0202bdeb770","src/platform/with_wgl/wgl_attributes.rs":"73b75da18519e048011e9c303e402cf7961e3652aa8f4d4ebf507b4ab83d06a3","src/tests.rs":"c0f7ab2584ee97691a9ab8cc00ebd725a040ef54ef56c285ed0cfbf84a7b0263"},"package":"cebfb377484b8fe608acabed968bc4108d44dcfa22318c2e8614eaffd8c5c5f8"}
\ No newline at end of file
--- a/third_party/rust/offscreen_gl_context/Cargo.toml
+++ b/third_party/rust/offscreen_gl_context/Cargo.toml
@@ -1,39 +1,39 @@
[package]
name = "offscreen_gl_context"
license = "MIT / Apache-2.0"
-version = "0.6.1"
+version = "0.8.2"
authors = ["Emilio Cobos Álvarez <emilio@crisal.io>", "The Servo Project Developers"]
description = "Creation and manipulation of HW accelerated offscreen rendering contexts in multiple platforms. Originally intended for the Servo project's WebGL implementation."
repository = "https://github.com/emilio/rust-offscreen-rendering-context"
build = "build.rs"
[build-dependencies]
gl_generator = "0.5"
[features]
-default = []
+default = ["x11"]
osmesa = ["osmesa-sys"]
# NOTE: Just for testing use, there are no other changes
test_egl_in_linux = []
-test_osmesa = []
[dependencies]
log = "0.3"
-gleam = "0.2.31"
+gleam = "0.4"
euclid = "0.11"
serde = { version = "0.9", optional = true }
osmesa-sys = { version = "0.1", optional = true }
[target.x86_64-apple-darwin.dependencies]
core-foundation = "0.3.0"
-cgl = "0.1"
+cgl = "0.2"
[target.'cfg(target_os = "linux")'.dependencies.x11]
+optional = true
version = "2.3.0"
features = ["xlib"]
[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.2"
gdi32-sys = "0.2"
user32-sys = "0.2"
kernel32-sys = "0.2"
--- a/third_party/rust/offscreen_gl_context/build.rs
+++ b/third_party/rust/offscreen_gl_context/build.rs
@@ -4,20 +4,21 @@ use std::env;
use std::fs::File;
use std::path::PathBuf;
use gl_generator::{Registry, Api, Profile, Fallbacks};
fn main() {
let target = env::var("TARGET").unwrap();
let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());
- if target.contains("linux") {
+ if target.contains("linux") && cfg!(feature = "x11") {
let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap();
Registry::new(Api::Glx, (1, 4), Profile::Core, Fallbacks::All, [])
.write_bindings(gl_generator::StaticGenerator, &mut file).unwrap();
+ println!("cargo:rustc-link-lib=GL");
}
if target.contains("android") || (target.contains("linux") && cfg!(feature = "test_egl_in_linux")) {
let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
Registry::new(Api::Egl, (1, 4), Profile::Core, Fallbacks::All, [])
.write_bindings(gl_generator::StaticGenerator, &mut file).unwrap();
println!("cargo:rustc-link-lib=EGL");
}
@@ -41,11 +42,15 @@ fn main() {
"WGL_ARB_pixel_format_float",
"WGL_EXT_create_context_es2_profile",
"WGL_EXT_extensions_string",
"WGL_EXT_framebuffer_sRGB",
"WGL_EXT_swap_control",
])
.write_bindings(gl_generator::StructGenerator, &mut file).unwrap();
+ println!("cargo:rustc-link-lib=opengl32");
+ }
+ if target.contains("darwin") {
+ println!("cargo:rustc-link-lib=framework=OpenGL");
}
}
--- a/third_party/rust/offscreen_gl_context/src/draw_buffer.rs
+++ b/third_party/rust/offscreen_gl_context/src/draw_buffer.rs
@@ -1,11 +1,12 @@
use euclid::Size2D;
use gleam::gl;
use gleam::gl::types::{GLuint, GLenum, GLint};
+use std::rc::Rc;
use GLContext;
use NativeGLContextMethods;
#[derive(Debug)]
pub enum ColorAttachmentType {
Texture,
Renderbuffer,
@@ -13,76 +14,77 @@ pub enum ColorAttachmentType {
impl Default for ColorAttachmentType {
fn default() -> ColorAttachmentType {
ColorAttachmentType::Renderbuffer
}
}
-/// We either have a color renderbuffer
-/// Or a surface bound to a texture
-/// bound to a framebuffer as a color
-/// attachment
+/// We either have a color renderbuffer, or a surface bound to a texture bound
+/// to a framebuffer as a color attachment.
+///
+/// NB: The draw buffer manages it, and calls its destroy method on drop, this
+/// is just to avoid propagating the GL functions pointer further down.
#[derive(Debug)]
pub enum ColorAttachment {
Renderbuffer(GLuint),
Texture(GLuint),
}
impl ColorAttachment {
pub fn color_attachment_type(&self) -> ColorAttachmentType {
match *self {
ColorAttachment::Renderbuffer(_) => ColorAttachmentType::Renderbuffer,
ColorAttachment::Texture(_) => ColorAttachmentType::Texture,
}
}
-}
-impl Drop for ColorAttachment {
- fn drop(&mut self) {
- match *self {
- ColorAttachment::Renderbuffer(id) => gl::delete_renderbuffers(&[id]),
- ColorAttachment::Texture(tex_id) => gl::delete_textures(&[tex_id]),
+ fn destroy(self, gl: &gl::Gl) {
+ match self {
+ ColorAttachment::Renderbuffer(id) => gl.delete_renderbuffers(&[id]),
+ ColorAttachment::Texture(tex_id) => gl.delete_textures(&[tex_id]),
}
}
}
/// This structure represents an offscreen context
/// draw buffer. It has a framebuffer, with at least
/// color renderbuffer (alpha or not). It may also have
/// a depth or stencil buffer, depending on context
/// requirements.
pub struct DrawBuffer {
+ gl_: Rc<gl::Gl>,
size: Size2D<i32>,
framebuffer: GLuint,
stencil_renderbuffer: GLuint,
depth_renderbuffer: GLuint,
color_attachment: Option<ColorAttachment>
// samples: GLsizei,
}
/// Helper function to create a render buffer
-/// TODO(ecoal95): We'll need to switch between `glRenderbufferStorage` and
-/// `glRenderbufferStorageMultisample` when we support antialising
-fn create_renderbuffer(format: GLenum,
+/// TODO(emilio): We'll need to switch between `glRenderbufferStorage` and
+/// `glRenderbufferStorageMultisample` when we support antialising
+fn create_renderbuffer(gl_: &gl::Gl,
+ format: GLenum,
size: &Size2D<i32>) -> GLuint {
- let ret = gl::gen_renderbuffers(1)[0];
- gl::bind_renderbuffer(gl::RENDERBUFFER, ret);
- gl::renderbuffer_storage(gl::RENDERBUFFER, format, size.width, size.height);
- gl::bind_renderbuffer(gl::RENDERBUFFER, 0);
+ let ret = gl_.gen_renderbuffers(1)[0];
+ gl_.bind_renderbuffer(gl::RENDERBUFFER, ret);
+ gl_.renderbuffer_storage(gl::RENDERBUFFER, format, size.width, size.height);
+ gl_.bind_renderbuffer(gl::RENDERBUFFER, 0);
ret
}
impl DrawBuffer {
pub fn new<T: NativeGLContextMethods>(context: &GLContext<T>,
mut size: Size2D<i32>,
color_attachment_type: ColorAttachmentType)
- -> Result<DrawBuffer, &'static str>
+ -> Result<Self, &'static str>
{
const MIN_DRAWING_BUFFER_SIZE: i32 = 16;
use std::cmp;
let attrs = context.borrow_attributes();
let capabilities = context.borrow_capabilities();
debug!("Creating draw buffer {:?}, {:?}, attrs: {:?}, caps: {:?}",
@@ -96,30 +98,33 @@ impl DrawBuffer {
return Err("preserveDrawingBuffer is not supported yet");
}
// See https://github.com/servo/servo/issues/12320
size.width = cmp::max(MIN_DRAWING_BUFFER_SIZE, size.width);
size.height = cmp::max(MIN_DRAWING_BUFFER_SIZE, size.height);
let mut draw_buffer = DrawBuffer {
+ gl_: context.clone_gl(),
size: size,
framebuffer: 0,
color_attachment: None,
stencil_renderbuffer: 0,
depth_renderbuffer: 0,
// samples: 0,
};
try!(context.make_current());
try!(draw_buffer.init(context, color_attachment_type));
- debug_assert!(gl::check_frame_buffer_status(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE);
- debug_assert!(gl::get_error() == gl::NO_ERROR);
+ debug_assert_eq!(draw_buffer.gl().check_frame_buffer_status(gl::FRAMEBUFFER),
+ gl::FRAMEBUFFER_COMPLETE);
+ debug_assert_eq!(draw_buffer.gl().get_error(),
+ gl::NO_ERROR);
Ok(draw_buffer)
}
#[inline(always)]
pub fn get_framebuffer(&self) -> GLuint {
self.framebuffer
}
@@ -144,132 +149,133 @@ impl DrawBuffer {
}
pub fn get_bound_texture_id(&self) -> Option<GLuint> {
match self.color_attachment.as_ref().unwrap() {
&ColorAttachment::Renderbuffer(_) => None,
&ColorAttachment::Texture(id) => Some(id),
}
}
+
+ fn gl(&self) -> &gl::Gl {
+ &*self.gl_
+ }
+
+
+ fn init<T: NativeGLContextMethods>(&mut self,
+ context: &GLContext<T>,
+ color_attachment_type: ColorAttachmentType)
+ -> Result<(), &'static str> {
+ let attrs = context.borrow_attributes();
+ let formats = context.borrow_formats();
+
+ assert!(self.color_attachment.is_none(),
+ "Would leak color attachment!");
+ self.color_attachment = match color_attachment_type {
+ ColorAttachmentType::Renderbuffer => {
+ let color_renderbuffer =
+ create_renderbuffer(self.gl(), formats.color_renderbuffer, &self.size);
+ debug_assert!(color_renderbuffer != 0);
+
+ Some(ColorAttachment::Renderbuffer(color_renderbuffer))
+ },
+
+ // TODO(ecoal95): Allow more customization of textures
+ ColorAttachmentType::Texture => {
+ let texture = self.gl().gen_textures(1)[0];
+ debug_assert!(texture != 0);
+
+ self.gl().bind_texture(gl::TEXTURE_2D, texture);
+ self.gl().tex_image_2d(gl::TEXTURE_2D, 0,
+ formats.texture_internal as GLint, self.size.width, self.size.height, 0, formats.texture, formats.texture_type, None);
+
+ // Low filtering to allow rendering
+ self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
+ self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
+
+ // TODO(emilio): Check if these two are neccessary, probably not
+ self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
+ self.gl().tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
+
+ self.gl().bind_texture(gl::TEXTURE_2D, 0);
+
+ debug_assert_eq!(self.gl().get_error(), gl::NO_ERROR);
+
+ Some(ColorAttachment::Texture(texture))
+ },
+ };
+
+ // After this we check if we need stencil and depth buffers
+ if attrs.depth {
+ self.depth_renderbuffer = create_renderbuffer(self.gl(), formats.depth, &self.size);
+ debug_assert!(self.depth_renderbuffer != 0);
+ }
+
+ if attrs.stencil {
+ self.stencil_renderbuffer = create_renderbuffer(self.gl(), formats.stencil, &self.size);
+ debug_assert!(self.stencil_renderbuffer != 0);
+ }
+
+ self.framebuffer = self.gl().gen_framebuffers(1)[0];
+ debug_assert!(self.framebuffer != 0);
+
+ // Finally we attach them to the framebuffer
+ self.attach_to_framebuffer()
+ }
+
+ fn attach_to_framebuffer(&mut self) -> Result<(), &'static str> {
+ self.gl().bind_framebuffer(gl::FRAMEBUFFER, self.framebuffer);
+ // NOTE: The assertion fails if the framebuffer is not bound
+ debug_assert_eq!(self.gl().is_framebuffer(self.framebuffer), gl::TRUE);
+
+ match *self.color_attachment.as_ref().unwrap() {
+ ColorAttachment::Renderbuffer(color_renderbuffer) => {
+ self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
+ gl::COLOR_ATTACHMENT0,
+ gl::RENDERBUFFER,
+ color_renderbuffer);
+ debug_assert_eq!(self.gl().is_renderbuffer(color_renderbuffer), gl::TRUE);
+ },
+ ColorAttachment::Texture(texture_id) => {
+ self.gl().framebuffer_texture_2d(gl::FRAMEBUFFER,
+ gl::COLOR_ATTACHMENT0,
+ gl::TEXTURE_2D,
+ texture_id, 0);
+ },
+ }
+
+ if self.depth_renderbuffer != 0 {
+ self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
+ gl::DEPTH_ATTACHMENT,
+ gl::RENDERBUFFER,
+ self.depth_renderbuffer);
+ debug_assert_eq!(self.gl().is_renderbuffer(self.depth_renderbuffer), gl::TRUE);
+ }
+
+ if self.stencil_renderbuffer != 0 {
+ self.gl().framebuffer_renderbuffer(gl::FRAMEBUFFER,
+ gl::STENCIL_ATTACHMENT,
+ gl::RENDERBUFFER,
+ self.stencil_renderbuffer);
+ debug_assert_eq!(self.gl().is_renderbuffer(self.stencil_renderbuffer), gl::TRUE);
+ }
+
+ Ok(())
+ }
}
// NOTE: The initially associated GLContext MUST be the current gl context
// when drop is called. I know this is an important constraint.
// Right now there are no problems, if not, consider using a pointer to a
// parent with Rc<GLContext> and call make_current()
impl Drop for DrawBuffer {
fn drop(&mut self) {
- gl::delete_framebuffers(&[self.framebuffer]);
+ if let Some(att) = self.color_attachment.take() {
+ att.destroy(self.gl());
+ }
+
+ self.gl().delete_framebuffers(&[self.framebuffer]);
// NOTE: Color renderbuffer is destroyed on drop of
// ColorAttachment
- gl::delete_renderbuffers(&[self.stencil_renderbuffer, self.depth_renderbuffer]);
+ self.gl().delete_renderbuffers(&[self.stencil_renderbuffer, self.depth_renderbuffer]);
}
}
-
-trait DrawBufferHelpers {
- fn init<T: NativeGLContextMethods>(&mut self,
- &GLContext<T>,
- color_attachment_type: ColorAttachmentType)
- -> Result<(), &'static str>;
- fn attach_to_framebuffer(&mut self)
- -> Result<(), &'static str>;
-}
-
-impl DrawBufferHelpers for DrawBuffer {
- fn init<T: NativeGLContextMethods>(&mut self,
- context: &GLContext<T>,
- color_attachment_type: ColorAttachmentType)
- -> Result<(), &'static str> {
- let attrs = context.borrow_attributes();
- let formats = context.borrow_formats();
-
- self.color_attachment = match color_attachment_type {
- ColorAttachmentType::Renderbuffer => {
- let color_renderbuffer = create_renderbuffer(formats.color_renderbuffer, &self.size);
- debug_assert!(color_renderbuffer != 0);
-
- Some(ColorAttachment::Renderbuffer(color_renderbuffer))
- },
-
- // TODO(ecoal95): Allow more customization of textures
- ColorAttachmentType::Texture => {
- let texture = gl::gen_textures(1)[0];
- debug_assert!(texture != 0);
-
- gl::bind_texture(gl::TEXTURE_2D, texture);
- gl::tex_image_2d(gl::TEXTURE_2D, 0,
- formats.texture_internal as GLint, self.size.width, self.size.height, 0, formats.texture, formats.texture_type, None);
-
- // Low filtering to allow rendering
- gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
- gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
-
- // TODO(ecoal95): Check if these two are neccessary, probably not
- gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
- gl::tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
-
- gl::bind_texture(gl::TEXTURE_2D, 0);
-
- debug_assert!(gl::get_error() == gl::NO_ERROR);
-
- Some(ColorAttachment::Texture(texture))
- },
- };
-
- // After this we check if we need stencil and depth buffers
- if attrs.depth {
- self.depth_renderbuffer = create_renderbuffer(formats.depth, &self.size);
- debug_assert!(self.depth_renderbuffer != 0);
- }
-
- if attrs.stencil {
- self.stencil_renderbuffer = create_renderbuffer(formats.stencil, &self.size);
- debug_assert!(self.stencil_renderbuffer != 0);
- }
-
- self.framebuffer = gl::gen_framebuffers(1)[0];
- debug_assert!(self.framebuffer != 0);
-
- // Finally we attach them to the framebuffer
- self.attach_to_framebuffer()
- }
-
- fn attach_to_framebuffer(&mut self) -> Result<(), &'static str> {
- gl::bind_framebuffer(gl::FRAMEBUFFER, self.framebuffer);
- // NOTE: The assertion fails if the framebuffer is not bound
- debug_assert!(gl::is_framebuffer(self.framebuffer) == gl::TRUE);
-
- match *self.color_attachment.as_ref().unwrap() {
- ColorAttachment::Renderbuffer(color_renderbuffer) => {
- gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
- gl::COLOR_ATTACHMENT0,
- gl::RENDERBUFFER,
- color_renderbuffer);
- debug_assert!(gl::is_renderbuffer(color_renderbuffer) == gl::TRUE);
- },
- ColorAttachment::Texture(texture_id) => {
- gl::framebuffer_texture_2d(gl::FRAMEBUFFER,
- gl::COLOR_ATTACHMENT0,
- gl::TEXTURE_2D,
- texture_id, 0);
- },
- }
-
- if self.depth_renderbuffer != 0 {
- gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
- gl::DEPTH_ATTACHMENT,
- gl::RENDERBUFFER,
- self.depth_renderbuffer);
- debug_assert!(gl::is_renderbuffer(self.depth_renderbuffer) == gl::TRUE);
- }
-
- if self.stencil_renderbuffer != 0 {
- gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
- gl::STENCIL_ATTACHMENT,
- gl::RENDERBUFFER,
- self.stencil_renderbuffer);
- debug_assert!(gl::is_renderbuffer(self.stencil_renderbuffer) == gl::TRUE);
- }
-
- Ok(())
- }
-}
--- a/third_party/rust/offscreen_gl_context/src/gl_context.rs
+++ b/third_party/rust/offscreen_gl_context/src/gl_context.rs
@@ -1,52 +1,63 @@
use euclid::Size2D;
use gleam::gl;
use gleam::gl::types::{GLuint};
+use std::rc::Rc;
use NativeGLContextMethods;
use GLContextAttributes;
use GLContextCapabilities;
use GLFormats;
use GLLimits;
use DrawBuffer;
use ColorAttachmentType;
/// This is a wrapper over a native headless GL context
pub struct GLContext<Native> {
+ gl_: Rc<gl::Gl>,
native_context: Native,
/// This an abstraction over a custom framebuffer
/// with attachments according to WebGLContextAttributes
// TODO(ecoal95): Ideally we may want a read and a draw
// framebuffer, but this is not supported in GLES2, review
// when we have better support
draw_buffer: Option<DrawBuffer>,
attributes: GLContextAttributes,
capabilities: GLContextCapabilities,
formats: GLFormats,
limits: GLLimits,
}
impl<Native> GLContext<Native>
- where Native: NativeGLContextMethods
+ where Native: NativeGLContextMethods,
{
- pub fn create(shared_with: Option<&Native::Handle>) -> Result<GLContext<Native>, &'static str> {
- Self::create_shared_with_dispatcher(shared_with, None)
+ pub fn create(api_type: gl::GlType,
+ shared_with: Option<&Native::Handle>)
+ -> Result<Self, &'static str> {
+ Self::create_shared_with_dispatcher(api_type, shared_with, None)
}
- pub fn create_shared_with_dispatcher(shared_with: Option<&Native::Handle>,
+ pub fn create_shared_with_dispatcher(api_type: gl::GlType,
+ shared_with: Option<&Native::Handle>,
dispatcher: Option<Box<GLContextDispatcher>>)
- -> Result<GLContext<Native>, &'static str> {
+ -> Result<Self, &'static str> {
let native_context = try!(Native::create_shared_with_dispatcher(shared_with, dispatcher));
+ let gl_ = match api_type {
+ gl::GlType::Gl => unsafe { gl::GlFns::load_with(|s| Self::get_proc_address(s) as *const _) },
+ gl::GlType::Gles => unsafe { gl::GlesFns::load_with(|s| Self::get_proc_address(s) as *const _) },
+ };
+
try!(native_context.make_current());
let attributes = GLContextAttributes::any();
let formats = GLFormats::detect(&attributes);
- let limits = GLLimits::detect();
+ let limits = GLLimits::detect(&*gl_);
Ok(GLContext {
+ gl_: gl_,
native_context: native_context,
draw_buffer: None,
attributes: attributes,
capabilities: GLContextCapabilities::detect(),
formats: formats,
limits: limits,
})
}
@@ -59,67 +70,99 @@ impl<Native> GLContext<Native>
#[inline(always)]
pub fn current_handle() -> Option<Native::Handle> {
Native::current_handle()
}
pub fn new(size: Size2D<i32>,
attributes: GLContextAttributes,
color_attachment_type: ColorAttachmentType,
+ api_type: gl::GlType,
shared_with: Option<&Native::Handle>)
- -> Result<GLContext<Native>, &'static str> {
- Self::new_shared_with_dispatcher(size, attributes, color_attachment_type, shared_with, None)
+ -> Result<Self, &'static str> {
+ Self::new_shared_with_dispatcher(size,
+ attributes,
+ color_attachment_type,
+ api_type,
+ shared_with,
+ None)
}
pub fn new_shared_with_dispatcher(size: Size2D<i32>,
attributes: GLContextAttributes,
color_attachment_type: ColorAttachmentType,
+ api_type: gl::GlType,
shared_with: Option<&Native::Handle>,
dispatcher: Option<Box<GLContextDispatcher>>)
- -> Result<GLContext<Native>, &'static str> {
+ -> Result<Self, &'static str> {
// We create a headless context with a dummy size, we're painting to the
// draw_buffer's framebuffer anyways.
- let mut context = try!(Self::create_shared_with_dispatcher(shared_with, dispatcher));
+ let mut context =
+ try!(Self::create_shared_with_dispatcher(api_type,
+ shared_with,
+ dispatcher));
context.formats = GLFormats::detect(&attributes);
context.attributes = attributes;
try!(context.init_offscreen(size, color_attachment_type));
Ok(context)
}
#[inline(always)]
pub fn with_default_color_attachment(size: Size2D<i32>,
attributes: GLContextAttributes,
+ api_type: gl::GlType,
shared_with: Option<&Native::Handle>)
- -> Result<GLContext<Native>, &'static str> {
- GLContext::new(size, attributes, ColorAttachmentType::default(), shared_with)
+ -> Result<Self, &'static str> {
+ Self::new(size, attributes, ColorAttachmentType::default(), api_type, shared_with)
}
#[inline(always)]
pub fn make_current(&self) -> Result<(), &'static str> {
self.native_context.make_current()
}
#[inline(always)]
pub fn unbind(&self) -> Result<(), &'static str> {
- self.native_context.unbind()
+ let ret = self.native_context.unbind();
+
+ // OSMesa doesn't allow any API to unbind a context before [1], and just
+ // bails out on null context, buffer, or whatever, so not much we can do
+ // here. Thus, ignore the failure and just flush the context if we're
+ // using an old OSMesa version.
+ //
+ // [1]: https://www.mail-archive.com/mesa-dev@lists.freedesktop.org/msg128408.html
+ if self.native_context.is_osmesa() && ret.is_err() {
+ self.gl().flush();
+ return Ok(())
+ }
+
+ ret
}
#[inline(always)]
pub fn is_current(&self) -> bool {
self.native_context.is_current()
}
#[inline(always)]
pub fn handle(&self) -> Native::Handle {
self.native_context.handle()
}
+ pub fn gl(&self) -> &gl::Gl {
+ &*self.gl_
+ }
+
+ pub fn clone_gl(&self) -> Rc<gl::Gl> {
+ self.gl_.clone()
+ }
+
// Allow borrowing these unmutably
pub fn borrow_attributes(&self) -> &GLContextAttributes {
&self.attributes
}
pub fn borrow_capabilities(&self) -> &GLContextCapabilities {
&self.capabilities
}
@@ -136,60 +179,53 @@ impl<Native> GLContext<Native>
self.draw_buffer.as_ref()
}
pub fn get_framebuffer(&self) -> GLuint {
if let Some(ref db) = self.draw_buffer {
return db.get_framebuffer();
}
- let ret = gl::get_integer_v(gl::FRAMEBUFFER_BINDING);
+ let ret = self.gl().get_integer_v(gl::FRAMEBUFFER_BINDING);
ret as GLuint
}
pub fn draw_buffer_size(&self) -> Option<Size2D<i32>> {
- self.draw_buffer.as_ref().map( |db| db.size() )
+ self.draw_buffer.as_ref().map(|db| db.size())
}
// We resize just replacing the draw buffer, we don't perform size optimizations
// in order to keep this generic
pub fn resize(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
if self.draw_buffer.is_some() {
let color_attachment_type =
self.borrow_draw_buffer().unwrap().color_attachment_type();
self.init_offscreen(size, color_attachment_type)
} else {
Err("No DrawBuffer found")
}
}
+
+ fn init_offscreen(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
+ try!(self.create_draw_buffer(size, color_attachment_type));
+
+ debug_assert!(self.is_current());
+
+ self.gl().clear_color(0.0, 0.0, 0.0, 0.0);
+ self.gl().clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
+ self.gl().scissor(0, 0, size.width, size.height);
+ self.gl().viewport(0, 0, size.width, size.height);
+
+ Ok(())
+ }
+
+ fn create_draw_buffer(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
+ self.draw_buffer = Some(try!(DrawBuffer::new(self, size, color_attachment_type)));
+ Ok(())
+ }
}
// Dispatches functions to the thread where a NativeGLContext is bound.
// Right now it's used in the WGL implementation to dispatch functions to the thread
// where the context we share from is bound. See the WGL implementation for more details.
pub trait GLContextDispatcher {
fn dispatch(&self, Box<Fn() + Send>);
}
-
-trait GLContextPrivateMethods {
- fn init_offscreen(&mut self, Size2D<i32>, ColorAttachmentType) -> Result<(), &'static str>;
- fn create_draw_buffer(&mut self, Size2D<i32>, ColorAttachmentType) -> Result<(), &'static str>;
-}
-
-impl<T: NativeGLContextMethods> GLContextPrivateMethods for GLContext<T> {
- fn init_offscreen(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
- try!(self.create_draw_buffer(size, color_attachment_type));
-
- debug_assert!(self.is_current());
-
- gl::clear_color(0.0, 0.0, 0.0, 0.0);
- gl::clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
- gl::scissor(0, 0, size.width, size.height);
- gl::viewport(0, 0, size.width, size.height);
-
- Ok(())
- }
-
- fn create_draw_buffer(&mut self, size: Size2D<i32>, color_attachment_type: ColorAttachmentType) -> Result<(), &'static str> {
- self.draw_buffer = Some(try!(DrawBuffer::new(&self, size, color_attachment_type)));
- Ok(())
- }
-}
--- a/third_party/rust/offscreen_gl_context/src/gl_limits.rs
+++ b/third_party/rust/offscreen_gl_context/src/gl_limits.rs
@@ -1,9 +1,10 @@
use gleam::gl;
+
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone)]
pub struct GLLimits {
pub max_vertex_attribs: u32,
pub max_tex_size: u32,
pub max_cube_map_tex_size: u32
@@ -29,16 +30,16 @@ impl Serialize for GLLimits {
where S: Serializer
{
[self.max_vertex_attribs, self.max_tex_size, self.max_cube_map_tex_size]
.serialize(serializer)
}
}
impl GLLimits {
- pub fn detect() -> GLLimits {
+ pub fn detect(gl_: &gl::Gl) -> GLLimits {
GLLimits {
- max_vertex_attribs: gl::get_integer_v(gl::MAX_VERTEX_ATTRIBS) as u32,
- max_tex_size: gl::get_integer_v(gl::MAX_TEXTURE_SIZE) as u32,
- max_cube_map_tex_size: gl::get_integer_v(gl::MAX_CUBE_MAP_TEXTURE_SIZE) as u32
+ max_vertex_attribs: gl_.get_integer_v(gl::MAX_VERTEX_ATTRIBS) as u32,
+ max_tex_size: gl_.get_integer_v(gl::MAX_TEXTURE_SIZE) as u32,
+ max_cube_map_tex_size: gl_.get_integer_v(gl::MAX_CUBE_MAP_TEXTURE_SIZE) as u32
}
}
}
--- a/third_party/rust/offscreen_gl_context/src/lib.rs
+++ b/third_party/rust/offscreen_gl_context/src/lib.rs
@@ -2,17 +2,17 @@ extern crate gleam;
extern crate euclid;
#[macro_use]
extern crate log;
#[cfg(feature="serde")]
extern crate serde;
-#[cfg(target_os="linux")]
+#[cfg(all(target_os="linux", feature="x11"))]
extern crate x11;
#[cfg(target_os="macos")]
extern crate cgl;
#[cfg(target_os="macos")]
extern crate core_foundation;
#[cfg(feature="osmesa")]
extern crate osmesa_sys;
#[cfg(target_os = "windows")]
@@ -24,16 +24,17 @@ extern crate gdi32;
#[cfg(target_os = "windows")]
extern crate user32;
#[cfg(any(target_os="macos", target_os="windows"))]
#[macro_use]
extern crate lazy_static;
mod platform;
pub use platform::{NativeGLContext, NativeGLContextMethods, NativeGLContextHandle};
+
#[cfg(feature="osmesa")]
pub use platform::{OSMesaContext, OSMesaContextHandle};
mod gl_context;
pub use gl_context::{GLContext, GLContextDispatcher};
mod draw_buffer;
pub use draw_buffer::{DrawBuffer, ColorAttachmentType};
@@ -48,17 +49,17 @@ mod gl_feature;
pub use gl_feature::GLFeature;
mod gl_formats;
pub use gl_formats::GLFormats;
mod gl_limits;
pub use gl_limits::GLLimits;
-#[cfg(target_os="linux")]
+#[cfg(all(target_os="linux", feature="x11"))]
#[allow(improper_ctypes)]
mod glx {
include!(concat!(env!("OUT_DIR"), "/glx_bindings.rs"));
}
#[cfg(any(target_os="android", all(target_os="linux", feature = "test_egl_in_linux")))]
#[allow(non_camel_case_types)]
mod egl {
--- a/third_party/rust/offscreen_gl_context/src/platform/mod.rs
+++ b/third_party/rust/offscreen_gl_context/src/platform/mod.rs
@@ -19,27 +19,34 @@ pub trait NativeGLContextMethods: Sized
fn create_headless() -> Result<Self, &'static str> {
Self::create_shared(None)
}
fn handle(&self) -> Self::Handle;
fn is_current(&self) -> bool;
fn make_current(&self) -> Result<(), &'static str>;
fn unbind(&self) -> Result<(), &'static str>;
+
+ /// Just a somewhat dirty hack to special-case the handling of context
+ /// unbinding on old OSMesa versions.
+ fn is_osmesa(&self) -> bool { false }
}
-#[cfg(target_os="linux")]
+#[cfg(all(target_os="linux", feature="x11"))]
pub mod with_glx;
-#[cfg(target_os="linux")]
+#[cfg(all(target_os="linux", feature="x11"))]
pub use self::with_glx::{NativeGLContext, NativeGLContextHandle};
#[cfg(feature="osmesa")]
pub mod with_osmesa;
#[cfg(feature="osmesa")]
pub use self::with_osmesa::{OSMesaContext, OSMesaContextHandle};
+#[cfg(all(target_os="linux", not(feature="x11")))]
+pub use self::with_osmesa::{OSMesaContext as NativeGLContext, OSMesaContextHandle as NativeGLContextHandle};
+
#[cfg(any(target_os="android", all(target_os="linux", feature = "test_egl_in_linux")))]
pub mod with_egl;
#[cfg(target_os="android")]
pub use self::with_egl::{NativeGLContext, NativeGLContextHandle};
#[cfg(target_os="macos")]
pub mod with_cgl;
--- a/third_party/rust/offscreen_gl_context/src/platform/with_osmesa/mod.rs
+++ b/third_party/rust/offscreen_gl_context/src/platform/with_osmesa/mod.rs
@@ -93,33 +93,29 @@ impl NativeGLContextMethods for OSMesaCo
Err("OSMesaMakeCurrent")
} else {
Ok(())
}
}
}
fn unbind(&self) -> Result<(), &'static str> {
- // OSMesa doesn't allow any API to unbind a context before [1], and just
- // bails out on null context, buffer, or whatever, so not much we can do
- // here. Thus, ignore the failure and just flush the context if we're
- // using an old OSMesa version.
- //
- // [1]: https://www.mail-archive.com/mesa-dev@lists.freedesktop.org/msg128408.html
if self.is_current() {
let ret = unsafe {
osmesa_sys::OSMesaMakeCurrent(ptr::null_mut(),
ptr::null_mut(), 0, 0, 0)
};
if ret == gl::FALSE {
- gl::flush();
+ return Err("OSMesaMakeCurrent");
}
}
Ok(())
}
+
+ fn is_osmesa(&self) -> bool { true }
}
impl Drop for OSMesaContext {
fn drop(&mut self) {
unsafe { osmesa_sys::OSMesaDestroyContext(self.context) }
}
}
--- a/third_party/rust/offscreen_gl_context/src/tests.rs
+++ b/third_party/rust/offscreen_gl_context/src/tests.rs
@@ -1,11 +1,10 @@
use gleam::gl;
use euclid::Size2D;
-use std::sync::{Once, ONCE_INIT};
use GLContext;
#[cfg(all(target_os = "linux", feature = "test_egl_in_linux"))]
use platform::with_egl::NativeGLContext;
#[cfg(feature="test_osmesa")]
use platform::OSMesaContext as NativeGLContext;
#[cfg(not(any(feature = "test_egl_in_linux", feature = "test_osmesa")))]
use NativeGLContext;
@@ -14,42 +13,29 @@ use GLContextAttributes;
use ColorAttachmentType;
use std::thread;
use std::sync::mpsc;
#[cfg(target_os="macos")]
#[link(name="OpenGL", kind="framework")]
extern {}
-#[cfg(target_os="linux")]
+#[cfg(all(target_os="linux", feature="x11"))]
#[link(name="GL")]
extern {}
-#[cfg(not(target_os="android"))]
-static LOAD_GL: Once = ONCE_INIT;
-
-#[cfg(not(target_os="android"))]
-fn load_gl() {
- LOAD_GL.call_once(|| {
- gl::load_with(|s| GLContext::<NativeGLContext>::get_proc_address(s) as *const _);
- });
-}
-#[cfg(target_os="android")]
-fn load_gl() {
-}
-
fn test_gl_context<T: NativeGLContextMethods>(context: &GLContext<T>) {
context.make_current().unwrap();
- gl::clear_color(1.0, 0.0, 0.0, 1.0);
- gl::clear(gl::COLOR_BUFFER_BIT);
+ context.gl().clear_color(1.0, 0.0, 0.0, 1.0);
+ context.gl().clear(gl::COLOR_BUFFER_BIT);
let size = context.draw_buffer_size().unwrap();
- let pixels = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let pixels = context.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
assert!(pixels.len() == (size.width * size.height * 4) as usize);
test_pixels(&pixels);
}
fn test_pixels_eq(pixels: &[u8], to: &[u8]) {
assert!(to.len() == 4);
for pixel in pixels.chunks(4) {
@@ -60,171 +46,168 @@ fn test_pixels_eq(pixels: &[u8], to: &[u
fn test_pixels(pixels: &[u8]) {
test_pixels_eq(pixels, &[255, 0, 0, 255]);
}
#[test]
#[cfg(not(feature = "test_osmesa"))]
fn test_unbinding() {
- load_gl();
let ctx = GLContext::<NativeGLContext>::new(Size2D::new(256, 256),
GLContextAttributes::default(),
ColorAttachmentType::Renderbuffer,
+ gl::GlType::default(),
None).unwrap();
assert!(NativeGLContext::current_handle().is_some());
ctx.unbind().unwrap();
assert!(NativeGLContext::current_handle().is_none());
}
#[test]
fn test_renderbuffer_color_attachment() {
- load_gl();
test_gl_context(&GLContext::<NativeGLContext>::new(Size2D::new(256, 256),
GLContextAttributes::default(),
ColorAttachmentType::Renderbuffer,
+ gl::GlType::default(),
None).unwrap());
}
#[test]
fn test_texture_color_attachment() {
- load_gl();
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
test_gl_context(&context);
// Get the bound texture and check we're painting on it
let texture_id = context.borrow_draw_buffer().unwrap().get_bound_texture_id().unwrap();
assert!(texture_id != 0);
- assert!(gl::get_error() == gl::NO_ERROR);
+ assert!(context.gl().get_error() == gl::NO_ERROR);
// Actually we just check that writing to the framebuffer works, and that there's a texture
// attached to it. Doing a getTexImage should be a good idea, but it's not available on gles,
// so what we should do is rebinding to another FBO.
//
// This is done in the `test_sharing` test though, so if that passes we know everything
// works and we're just happy.
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let vec = context.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
test_pixels(&vec);
}
#[test]
fn test_sharing() {
- load_gl();
-
let size = Size2D::new(256, 256);
let primary = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
let primary_texture_id = primary.borrow_draw_buffer().unwrap().get_bound_texture_id().unwrap();
assert!(primary_texture_id != 0);
let secondary = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
Some(&primary.handle())).unwrap();
// Paint the second context red
test_gl_context(&secondary);
// Now the secondary context is bound, get the texture id, switch contexts, and check the
// texture is there.
let secondary_texture_id = secondary.borrow_draw_buffer().unwrap().get_bound_texture_id().unwrap();
assert!(secondary_texture_id != 0);
primary.make_current().unwrap();
- assert!(unsafe { gl::IsTexture(secondary_texture_id) != 0 });
+ assert!(primary.gl().is_texture(secondary_texture_id) != 0);
- // Clearing and re-binding to a framebuffer instead of using getTexImage since it's not
- // available in GLES2
- gl::clear_color(0.0, 0.0, 0.0, 1.0);
- gl::clear(gl::COLOR_BUFFER_BIT);
+ // Clearing and re-binding to a framebuffer instead of using getTexImage
+ // since it's not available in GLES2
+ primary.gl().clear_color(0.0, 0.0, 0.0, 1.0);
+ primary.gl().clear(gl::COLOR_BUFFER_BIT);
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let vec = primary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
test_pixels_eq(&vec, &[0, 0, 0, 255]);
- gl::bind_texture(gl::TEXTURE_2D, secondary_texture_id);
+ primary.gl().bind_texture(gl::TEXTURE_2D, secondary_texture_id);
- unsafe {
- gl::FramebufferTexture2D(gl::FRAMEBUFFER,
- gl::COLOR_ATTACHMENT0,
- gl::TEXTURE_2D,
- secondary_texture_id, 0);
- }
+ primary.gl().framebuffer_texture_2d(gl::FRAMEBUFFER,
+ gl::COLOR_ATTACHMENT0,
+ gl::TEXTURE_2D,
+ secondary_texture_id, 0);
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
- assert!(gl::get_error() == gl::NO_ERROR);
+ let vec = primary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ assert!(primary.gl().get_error() == gl::NO_ERROR);
test_pixels(&vec);
}
#[test]
fn test_multithread_render() {
- load_gl();
-
let size = Size2D::new(256, 256);
let primary = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
test_gl_context(&primary);
let (tx, rx) = mpsc::channel();
let (end_tx, end_rx) = mpsc::channel();
thread::spawn(move ||{
//create the context in a different thread
let secondary = GLContext::<NativeGLContext>::new(size,
- GLContextAttributes::default(),
- ColorAttachmentType::Texture,
- None).unwrap();
+ GLContextAttributes::default(),
+ ColorAttachmentType::Texture,
+ gl::GlType::default(),
+ None).unwrap();
secondary.make_current().unwrap();
assert!(secondary.is_current());
//render green adn test pixels
- gl::clear_color(0.0, 1.0, 0.0, 1.0);
- gl::clear(gl::COLOR_BUFFER_BIT);
+ secondary.gl().clear_color(0.0, 1.0, 0.0, 1.0);
+ secondary.gl().clear(gl::COLOR_BUFFER_BIT);
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let vec = secondary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
test_pixels_eq(&vec, &[0, 255, 0, 255]);
tx.send(()).unwrap();
// Avoid drop until test ends
end_rx.recv().unwrap();
});
// Wait until thread has drawn the texture
rx.recv().unwrap();
// This context must remain to be current in this thread
assert!(primary.is_current());
// The colors must remain unchanged
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let vec = primary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
test_pixels_eq(&vec, &[255, 0, 0, 255]);
end_tx.send(()).unwrap();
}
struct SGLUint(gl::GLuint);
unsafe impl Sync for SGLUint {}
unsafe impl Send for SGLUint {}
#[test]
fn test_multithread_sharing() {
- load_gl();
-
let size = Size2D::new(256, 256);
let primary = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
primary.make_current().unwrap();
let primary_texture_id = primary.borrow_draw_buffer().unwrap().get_bound_texture_id().unwrap();
assert!(primary_texture_id != 0);
let (tx, rx) = mpsc::channel();
let (end_tx, end_rx) = mpsc::channel();
@@ -233,16 +216,17 @@ fn test_multithread_sharing() {
// Unbind required by some APIs as WGL
primary.unbind().unwrap();
thread::spawn(move || {
// Create the context in a different thread
let secondary = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
Some(&primary_handle)).unwrap();
// Make the context current on this thread only
secondary.make_current().unwrap();
// Paint the second context red
test_gl_context(&secondary);
// Send texture_id to main thread
let texture_id = secondary.borrow_draw_buffer().unwrap().get_bound_texture_id().unwrap();
assert!(texture_id != 0);
@@ -250,138 +234,137 @@ fn test_multithread_sharing() {
// Avoid drop until test ends
end_rx.recv().unwrap();
});
// Wait until thread has drawn the texture
let secondary_texture_id = rx.recv().unwrap().0;
primary.make_current().unwrap();
- // Clearing and re-binding to a framebuffer instead of using getTexImage since it's not
- // available in GLES2
- gl::clear_color(0.0, 0.0, 0.0, 1.0);
- gl::clear(gl::COLOR_BUFFER_BIT);
+ // Clearing and re-binding to a framebuffer instead of using getTexImage
+ // since it's not available in GLES2
+ primary.gl().clear_color(0.0, 0.0, 0.0, 1.0);
+ primary.gl().clear(gl::COLOR_BUFFER_BIT);
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ let vec = primary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
test_pixels_eq(&vec, &[0, 0, 0, 255]);
- unsafe {
- gl::FramebufferTexture2D(gl::FRAMEBUFFER,
- gl::COLOR_ATTACHMENT0,
- gl::TEXTURE_2D,
- secondary_texture_id, 0);
- }
+ primary.gl().framebuffer_texture_2d(gl::FRAMEBUFFER,
+ gl::COLOR_ATTACHMENT0,
+ gl::TEXTURE_2D,
+ secondary_texture_id,
+ 0);
- let vec = gl::read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
- assert!(gl::get_error() == gl::NO_ERROR);
+ let vec = primary.gl().read_pixels(0, 0, size.width, size.height, gl::RGBA, gl::UNSIGNED_BYTE);
+ assert!(primary.gl().get_error() == gl::NO_ERROR);
test_pixels(&vec);
end_tx.send(()).unwrap();
}
#[test]
fn test_limits() {
- load_gl();
-
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
assert!(context.borrow_limits().max_vertex_attribs != 0);
}
#[test]
fn test_no_alpha() {
- load_gl();
let mut attributes = GLContextAttributes::default();
attributes.alpha = false;
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
attributes,
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
assert!(context.borrow_limits().max_vertex_attribs != 0);
}
#[test]
fn test_no_depth() {
- load_gl();
let mut attributes = GLContextAttributes::default();
attributes.depth = false;
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
attributes,
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
assert!(context.borrow_limits().max_vertex_attribs != 0);
}
#[test]
fn test_no_depth_no_alpha() {
- load_gl();
let mut attributes = GLContextAttributes::default();
attributes.depth = false;
attributes.alpha = false;
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
attributes,
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
assert!(context.borrow_limits().max_vertex_attribs != 0);
}
#[test]
fn test_no_premul_alpha() {
- load_gl();
let mut attributes = GLContextAttributes::default();
attributes.depth = false;
attributes.alpha = false;
attributes.premultiplied_alpha = false;
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
attributes,
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
assert!(context.borrow_limits().max_vertex_attribs != 0);
}
#[test]
fn test_in_a_row() {
- load_gl();
let mut attributes = GLContextAttributes::default();
attributes.depth = false;
attributes.alpha = false;
attributes.premultiplied_alpha = false;
let size = Size2D::new(256, 256);
let context = GLContext::<NativeGLContext>::new(size,
attributes.clone(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
let handle = context.handle();
GLContext::<NativeGLContext>::new(size,
attributes.clone(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
Some(&handle)).unwrap();
GLContext::<NativeGLContext>::new(size,
attributes.clone(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
Some(&handle)).unwrap();
}
#[test]
fn test_zero_size() {
- load_gl();
-
GLContext::<NativeGLContext>::new(Size2D::new(0, 320),
GLContextAttributes::default(),
ColorAttachmentType::Texture,
+ gl::GlType::default(),
None).unwrap();
}