From b8cd39871ed9ed7e4cc7fffb4e6fc6fc5ddf9fef Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Wed, 30 May 2018 14:49:10 -0400 Subject: [PATCH] Detect more GL limits. --- Cargo.toml | 2 +- src/gl_limits.rs | 110 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 428a24b..e55473e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "offscreen_gl_context" license = "MIT / Apache-2.0" -version = "0.16.0" +version = "0.17.0" authors = ["Emilio Cobos Álvarez ", "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" diff --git a/src/gl_limits.rs b/src/gl_limits.rs index ead2481..9317f89 100644 --- a/src/gl_limits.rs +++ b/src/gl_limits.rs @@ -7,7 +7,14 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub struct GLLimits { pub max_vertex_attribs: u32, pub max_tex_size: u32, - pub max_cube_map_tex_size: u32 + pub max_cube_map_tex_size: u32, + pub max_combined_texture_image_units: u32, + pub max_fragment_uniform_vectors: u32, + pub max_renderbuffer_size: u32, + pub max_texture_image_units: u32, + pub max_varying_vectors: u32, + pub max_vertex_texture_image_units: u32, + pub max_vertex_uniform_vectors: u32 } #[cfg(feature = "serde")] @@ -15,11 +22,18 @@ impl<'de> Deserialize<'de> for GLLimits { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - let values = try!(<[_; 3]>::deserialize(deserializer)); + let values = try!(<[_; 10]>::deserialize(deserializer)); Ok(GLLimits { max_vertex_attribs: values[0], max_tex_size: values[1], max_cube_map_tex_size: values[2], + max_combined_texture_image_units: values[3], + max_fragment_uniform_vectors: values[4], + max_renderbuffer_size: values[5], + max_texture_image_units: values[6], + max_varying_vectors: values[7], + max_vertex_texture_image_units: values[8], + max_vertex_uniform_vectors: values[9], }) } } @@ -29,26 +43,90 @@ impl Serialize for GLLimits { fn serialize(&self, serializer: S) -> Result where S: Serializer { - [self.max_vertex_attribs, self.max_tex_size, self.max_cube_map_tex_size] + [self.max_vertex_attribs, self.max_tex_size, self.max_cube_map_tex_size, + self.max_combined_texture_image_units, self.max_fragment_uniform_vectors, + self.max_renderbuffer_size, self.max_texture_image_units, self.max_varying_vectors, + self.max_vertex_texture_image_units, self.max_vertex_uniform_vectors] .serialize(serializer) } } +macro_rules! gl_integer { + ($gl:ident, $pname:ident) => { + { + debug_assert!($gl.get_error() == gl::NO_ERROR); + let mut val = [0]; + unsafe { + $gl.get_integer_v(gl::$pname, &mut val); + } + assert_eq!($gl.get_error(), gl::NO_ERROR, "Error retrieving {}", stringify!($pname)); + val[0] as u32 + } + } +} + +fn gl_fallible_integer(gl_: &gl::Gl, pname: gl::GLenum) -> Result { + let mut val = [0]; + unsafe { + gl_.get_integer_v(pname, &mut val); + } + let err = gl_.get_error(); + if err == gl::INVALID_ENUM { + return Err(()); + } + assert_eq!(err, gl::NO_ERROR); + Ok(val[0] as u32) +} + impl GLLimits { pub fn detect(gl_: &gl::Gl) -> GLLimits { - let mut limit = [0]; - unsafe { - gl_.get_integer_v(gl::MAX_VERTEX_ATTRIBS, &mut limit); - } - let max_vertex_attribs = limit[0] as u32; - unsafe { - gl_.get_integer_v(gl::MAX_TEXTURE_SIZE, &mut limit); - } - let max_tex_size = limit[0] as u32; - unsafe { - gl_.get_integer_v(gl::MAX_CUBE_MAP_TEXTURE_SIZE, &mut limit); + let max_vertex_attribs = gl_integer!(gl_, MAX_VERTEX_ATTRIBS); + let max_tex_size = gl_integer!(gl_, MAX_TEXTURE_SIZE); + let max_cube_map_tex_size = gl_integer!(gl_, MAX_CUBE_MAP_TEXTURE_SIZE); + let max_combined_texture_image_units = gl_integer!(gl_, MAX_COMBINED_TEXTURE_IMAGE_UNITS); + let max_renderbuffer_size = gl_integer!(gl_, MAX_RENDERBUFFER_SIZE); + let max_texture_image_units = gl_integer!(gl_, MAX_TEXTURE_IMAGE_UNITS); + let max_vertex_texture_image_units = gl_integer!(gl_, MAX_VERTEX_TEXTURE_IMAGE_UNITS); + + // Based off of https://searchfox.org/mozilla-central/rev/5a744713370ec47969595e369fd5125f123e6d24/dom/canvas/WebGLContextValidate.cpp#523-558 + let (max_fragment_uniform_vectors, + max_varying_vectors, + max_vertex_uniform_vectors) = match gl_fallible_integer(gl_, gl::MAX_FRAGMENT_UNIFORM_VECTORS) { + Ok(limit) => { + (limit, + gl_integer!(gl_, MAX_VARYING_VECTORS), + gl_integer!(gl_, MAX_VERTEX_UNIFORM_VECTORS)) + } + Err(()) => { + let max_fragment_uniform_components = + gl_integer!(gl_, MAX_FRAGMENT_UNIFORM_COMPONENTS); + let max_vertex_uniform_components = + gl_integer!(gl_, MAX_VERTEX_UNIFORM_COMPONENTS); + + let max_vertex_output_components = + gl_fallible_integer(gl_, gl::MAX_VERTEX_OUTPUT_COMPONENTS).unwrap_or(0); + let max_fragment_input_components = + gl_fallible_integer(gl_, gl::MAX_FRAGMENT_INPUT_COMPONENTS).unwrap_or(0); + let max_varying_components = + max_vertex_output_components.min(max_fragment_input_components).max(16); + + (max_fragment_uniform_components / 4, + max_varying_components / 4, + max_vertex_uniform_components / 4) + } + }; + + GLLimits { + max_vertex_attribs, + max_tex_size, + max_cube_map_tex_size, + max_combined_texture_image_units, + max_fragment_uniform_vectors, + max_renderbuffer_size, + max_texture_image_units, + max_varying_vectors, + max_vertex_texture_image_units, + max_vertex_uniform_vectors, } - let max_cube_map_tex_size = limit[0] as u32; - GLLimits { max_vertex_attribs, max_tex_size, max_cube_map_tex_size } } }