diff --git a/Cargo.toml b/Cargo.toml index ee0e443..918aaf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ features = [ "WebGl2RenderingContext", "WebGlSampler", "WebGlShader", + "WebGlShaderPrecisionFormat", "WebGlSync", "WebGlTexture", "WebGlTransformFeedback", diff --git a/src/lib.rs b/src/lib.rs index 50f1c37..9b14eb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,6 +57,45 @@ pub struct ActiveTransformFeedback { pub name: String, } +#[derive(Debug)] +pub struct ShaderPrecisionFormat { + /// The base 2 log of the absolute value of the minimum value that can be represented + pub range_min: i32, + /// The base 2 log of the absolute value of the maximum value that can be represented. + pub range_max: i32, + /// The number of bits of precision that can be represented. + /// For integer formats this value is always 0. + pub precision: i32, +} + +impl ShaderPrecisionFormat { + /// Returns OpenGL standard precision that most desktop hardware support + pub fn default(precision_type: u32, is_embedded: bool) -> Self { + let (range_min, range_max, precision) = match precision_type { + LOW_INT | MEDIUM_INT | HIGH_INT => { + // Precision: For integer formats this value is always 0 + if is_embedded { + // These values are for a 32-bit twos-complement integer format. + (31, 30, 0) + } else { + // Range: from -2^24 to 2^24 + (24, 24, 0) + } + } + // IEEE 754 single-precision floating-point + // Range: from -2^127 to 2^127 + // Significand precision: 23 bits + LOW_FLOAT | MEDIUM_FLOAT | HIGH_FLOAT => (127, 127, 23), + _ => unreachable!("invalid precision"), + }; + Self { + range_min, + range_max, + precision, + } + } +} + #[allow(dead_code)] #[derive(Debug)] pub struct DebugMessageLogEntry { @@ -156,6 +195,12 @@ pub trait HasContext: __private::Sealed { unsafe fn get_shader_info_log(&self, shader: Self::Shader) -> String; + unsafe fn get_shader_precision_format( + &self, + shader_type: u32, + precision_mode: u32, + ) -> Option; + unsafe fn get_tex_image( &self, target: u32, diff --git a/src/native.rs b/src/native.rs index 2505d5b..490a280 100644 --- a/src/native.rs +++ b/src/native.rs @@ -366,6 +366,36 @@ impl HasContext for Context { } } + unsafe fn get_shader_precision_format( + &self, + shader_type: u32, + precision_type: u32, + ) -> Option { + let gl = &self.raw; + + if gl.GetShaderPrecisionFormat_is_loaded() { + let mut range = [0, 0]; + let mut precision = 0; + gl.GetShaderPrecisionFormat( + shader_type, + precision_type, + range.as_mut_ptr(), + &mut precision, + ); + // In some cases GetShaderPrecisionFormat exists but it's just a stub + // so we return only if variables got populated + if range[1] != 0 { + return Some(ShaderPrecisionFormat { + range_min: range[0], + range_max: range[1], + precision, + }); + } + } + + None + } + unsafe fn get_tex_image( &self, target: u32, diff --git a/src/web_sys.rs b/src/web_sys.rs index 1922995..062fd6a 100644 --- a/src/web_sys.rs +++ b/src/web_sys.rs @@ -1825,6 +1825,26 @@ impl HasContext for Context { .unwrap_or_else(|| String::from("")) } + unsafe fn get_shader_precision_format( + &self, + shader_type: u32, + precision_mode: u32, + ) -> Option { + match self.raw { + RawRenderingContext::WebGl1(ref gl) => { + gl.get_shader_precision_format(shader_type, precision_mode) + } + RawRenderingContext::WebGl2(ref gl) => { + gl.get_shader_precision_format(shader_type, precision_mode) + } + } + .map(|spf| ShaderPrecisionFormat { + range_min: spf.range_min(), + range_max: spf.range_max(), + precision: spf.precision(), + }) + } + unsafe fn get_tex_image( &self, _target: u32,