diff --git a/.travis.yml b/.travis.yml index 4ecd9b6..86e461a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,7 @@ rust: - nightly - beta - stable + +script: + - cargo check --verbose --no-default-features + - cargo check --verbose --no-default-features --features="std" \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index d92dcc7..80deb70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gleam" -version = "0.13.1" +version = "0.15.0" license = "Apache-2.0/MIT" authors = ["The Servo Project Developers"] build = "build.rs" @@ -9,4 +9,8 @@ repository = "https://github.com/servo/gleam" description = "Generated OpenGL bindings and wrapper for Servo." [build-dependencies] -gl_generator = "0.14" +gl_generator = { version = "0.15", git = "https://github.com/fschutt/gl-rs", branch = "no_std", default-features = false } + +[features] +default = ["std"] +std = [] \ No newline at end of file diff --git a/src/gl.rs b/src/gl.rs index e66ff6d..8c153ff 100644 --- a/src/gl.rs +++ b/src/gl.rs @@ -7,14 +7,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern crate core; +extern crate alloc; + use ffi; -use std::ffi::{CStr, CString}; -use std::mem; -use std::mem::size_of; -use std::os::raw::{c_char, c_int, c_void}; -use std::ptr; -use std::rc::Rc; -use std::str; +use core::mem; +use core::mem::size_of; +use ffi::__gl_imports::{c_void, c_int}; +use core::ptr; +use alloc::rc::Rc; +use alloc::vec::Vec; +use alloc::string::String; +use core::str; +#[cfg(feature = "std")] use std::time::{Duration, Instant}; pub use ffi::types::*; @@ -104,6 +109,7 @@ macro_rules! declare_gl_apis { })+ } + #[cfg(feature = "std")] impl Gl for ProfilingGl { $($(unsafe $($garbo)*)* fn $name(&self $(, $arg:$t)*) $(-> $retty)* { let start = Instant::now(); @@ -783,12 +789,14 @@ impl ErrorReactingGl { /// A wrapper around GL context that times each call and invokes the callback /// if the call takes longer than the threshold. +#[cfg(feature = "std")] pub struct ProfilingGl { gl: Rc, threshold: Duration, callback: F, } +#[cfg(feature = "std")] impl ProfilingGl { pub fn wrap(fns: Rc, threshold: Duration, callback: F) -> Rc { Rc::new(ProfilingGl { diff --git a/src/gl_fns.rs b/src/gl_fns.rs index 0c7eb26..1c2d219 100644 --- a/src/gl_fns.rs +++ b/src/gl_fns.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use utils::cstring_from_str; + pub struct GlFns { ffi_gl_: GlFfi, } @@ -399,7 +401,7 @@ impl Gl for GlFns { } fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) { - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_ .BindAttribLocation(program, index, c_string.as_ptr()) @@ -421,7 +423,7 @@ impl Gl for GlFns { } fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_ .GetUniformBlockIndex(program, c_string.as_ptr()) @@ -429,7 +431,7 @@ impl Gl for GlFns { } fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec { - let c_strings: Vec = names.iter().map(|n| CString::new(*n).unwrap()).collect(); + let c_strings: Vec> = names.iter().map(|n| cstring_from_str(*n)).collect(); let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect(); let mut result = Vec::with_capacity(c_strings.len()); unsafe { @@ -1623,17 +1625,17 @@ impl Gl for GlFns { } fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int { - let name = CString::new(name).unwrap(); + let name = cstring_from_str(name); 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(); + let name = cstring_from_str(name); 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(); + let name = cstring_from_str(name); unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) } } @@ -1786,10 +1788,9 @@ impl Gl for GlFns { 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(); + cstr_from_ptr(llstr).to_string() } else { - return "".to_string(); + String::new() } } } @@ -1798,10 +1799,9 @@ impl Gl for GlFns { unsafe { let llstr = self.ffi_gl_.GetStringi(which, index); if !llstr.is_null() { - str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) - .to_string() + cstr_from_ptr(llstr).to_string() } else { - "".to_string() + String::new() } } } @@ -2098,7 +2098,7 @@ impl Gl for GlFns { return; } - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_.BindFragDataLocationIndexed( @@ -2115,7 +2115,7 @@ impl Gl for GlFns { return -1; } - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_.GetFragDataIndex(program, c_string.as_ptr()) } } diff --git a/src/gles_fns.rs b/src/gles_fns.rs index 7fbba87..ed5fea2 100644 --- a/src/gles_fns.rs +++ b/src/gles_fns.rs @@ -7,6 +7,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use alloc::string::ToString; +use utils::cstr_from_ptr; + pub struct GlesFns { ffi_gl_: GlesFfi, } @@ -414,7 +417,7 @@ impl Gl for GlesFns { } fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) { - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_ .BindAttribLocation(program, index, c_string.as_ptr()) @@ -436,7 +439,7 @@ impl Gl for GlesFns { } fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint { - let c_string = CString::new(name).unwrap(); + let c_string = cstring_from_str(name); unsafe { self.ffi_gl_ .GetUniformBlockIndex(program, c_string.as_ptr()) @@ -444,7 +447,7 @@ impl Gl for GlesFns { } fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec { - let c_strings: Vec = names.iter().map(|n| CString::new(*n).unwrap()).collect(); + let c_strings: Vec> = names.iter().map(|n| cstring_from_str(*n)).collect(); let pointers: Vec<*const GLchar> = c_strings.iter().map(|string| string.as_ptr()).collect(); let mut result = Vec::with_capacity(c_strings.len()); unsafe { @@ -1622,7 +1625,7 @@ impl Gl for GlesFns { } fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int { - let name = CString::new(name).unwrap(); + let name = cstring_from_str(name); unsafe { self.ffi_gl_.GetAttribLocation(program, name.as_ptr()) } } @@ -1632,7 +1635,7 @@ impl Gl for GlesFns { } fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int { - let name = CString::new(name).unwrap(); + let name = cstring_from_str(name); unsafe { self.ffi_gl_.GetUniformLocation(program, name.as_ptr()) } } @@ -1776,10 +1779,9 @@ impl Gl for GlesFns { 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(); + cstr_from_ptr(llstr).to_string() } else { - return "".to_string(); + String::new() } } } @@ -1788,10 +1790,9 @@ impl Gl for GlesFns { unsafe { let llstr = self.ffi_gl_.GetStringi(which, index); if !llstr.is_null() { - str::from_utf8_unchecked(CStr::from_ptr(llstr as *const c_char).to_bytes()) - .to_string() + cstr_from_ptr(llstr).to_string() } else { - "".to_string() + String::new() } } } diff --git a/src/lib.rs b/src/lib.rs index aebb612..8c02976 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,9 +7,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg_attr(not(feature = "std"), no_std)] #![crate_name = "gleam"] #![crate_type = "lib"] +#[macro_use] +extern crate alloc; + pub mod gl; mod ffi { @@ -23,3 +27,28 @@ mod ffi_gl { mod ffi_gles { include!(concat!(env!("OUT_DIR"), "/gles_bindings.rs")); } + +pub(crate) mod utils { + use alloc::vec::Vec; + + /// CString is not available on libcore, but all that CString does + /// is to cast the string to bytes, then append a "0" at the end. + pub fn cstring_from_str(s: &str) -> Vec { let mut v: Vec = s.into(); v.push(0); v } + /// no-std port of Cstr::from_ptr + pub unsafe fn cstr_from_ptr<'a>(ptr: *const crate::ffi::__gl_imports::c_uchar) -> &'a str { + + #[inline] + unsafe fn strlen(mut s: *const crate::ffi::__gl_imports::c_uchar) -> usize { + let mut result = 0; + while *s != 0 { + s = s.offset(1); + result += 1; + } + result + } + + let len = strlen(ptr); + let ptr = ptr as *const u8; // c_char is always one byte, safe cast + core::str::from_utf8_unchecked(core::slice::from_raw_parts(ptr, len as usize + 1)) + } +} \ No newline at end of file