Dairy-Drift/imgui_glow_renderer/src/versions.rs

189 lines
6.1 KiB
Rust

#![allow(clippy::must_use_candidate)]
#[derive(PartialEq, Clone, Copy)]
pub struct GlVersion {
pub major: u16,
pub minor: u16,
pub is_gles: bool,
}
impl GlVersion {
pub const fn gl(major: u16, minor: u16) -> Self {
Self {
major,
minor,
is_gles: false,
}
}
pub const fn gles(major: u16, minor: u16) -> Self {
Self {
major,
minor,
is_gles: true,
}
}
pub fn read<G: glow::HasContext>(gl: &G) -> Self {
Self::parse(&unsafe { gl.get_parameter_string(glow::VERSION) })
}
/// Parse the OpenGL version from the version string queried from the driver
/// via the `GL_VERSION` enum.
///
/// Version strings are documented to be in the form
/// `<major>.<minor>[.<release>][ <vendor specific information>]`
/// for full-fat OpenGL, and
/// `OpenGL ES <major>.<minor>[.<release>][ <vendor specific information>]`
/// for OpenGL ES.
///
/// Examples based on strings found in the wild:
/// ```rust
/// # use imgui_glow_renderer::versions::GlVersion;
/// let version = GlVersion::parse("4.6.0 NVIDIA 465.27");
/// assert!(!version.is_gles);
/// assert_eq!(version.major, 4);
/// assert_eq!(version.minor, 6);
/// let version = GlVersion::parse("OpenGL ES 3.2 NVIDIA 465.27");
/// assert!(version.is_gles);
/// assert_eq!(version.major, 3);
/// assert_eq!(version.minor, 2);
/// ```
pub fn parse(gl_version_string: &str) -> Self {
let (version_string, is_gles) = gl_version_string
.strip_prefix("OpenGL ES ")
.map_or_else(|| (gl_version_string, false), |version| (version, true));
let mut parts = version_string.split(|c: char| !c.is_numeric());
let major = parts.next().unwrap_or("0").parse().unwrap_or(0);
let minor = parts.next().unwrap_or("0").parse().unwrap_or(0);
Self {
major,
minor,
is_gles,
}
}
/// Debug messages are provided by `glDebugMessageInsert`, which is only
/// present in OpenGL >= 4.3
#[cfg(feature = "debug_message_insert_support")]
pub fn debug_message_insert_support(self) -> bool {
self >= Self::gl(4, 3)
}
/// Vertex array binding is provided by `glBindVertexArray`, which is
/// not present in OpenGL (ES) <3.0
#[cfg(feature = "bind_vertex_array_support")]
pub fn bind_vertex_array_support(self) -> bool {
self.major >= 3
}
/// Vertex offset support is provided by `glDrawElementsBaseVertex`, which is
/// only present from OpenGL 3.2 and above.
#[cfg(feature = "vertex_offset_support")]
pub fn vertex_offset_support(self) -> bool {
self >= Self::gl(3, 2)
}
/// Vertex arrays (e.g. `glBindVertexArray`) are supported from OpenGL 3.0
/// and OpenGL ES 3.0
#[cfg(feature = "vertex_array_support")]
pub fn vertex_array_support(self) -> bool {
self >= Self::gl(3, 0) || self >= Self::gles(3, 0)
}
/// Separate binding of sampler (`glBindSampler`) is supported from OpenGL
/// 3.2 or ES 3.0
#[cfg(feature = "bind_sampler_support")]
pub fn bind_sampler_support(self) -> bool {
self >= GlVersion::gl(3, 2) || self >= GlVersion::gles(3, 0)
}
/// Setting the clip origin (`GL_CLIP_ORIGIN`) is suppoted from OpenGL 4.5
#[cfg(feature = "clip_origin_support")]
pub fn clip_origin_support(self) -> bool {
self >= GlVersion::gl(4, 5)
}
#[cfg(feature = "polygon_mode_support")]
pub fn polygon_mode_support(self) -> bool {
!self.is_gles
}
#[cfg(feature = "primitive_restart_support")]
pub fn primitive_restart_support(self) -> bool {
self >= GlVersion::gl(3, 1)
}
}
impl PartialOrd for GlVersion {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.is_gles == other.is_gles {
Some(
self.major
.cmp(&other.major)
.then(self.minor.cmp(&other.minor)),
)
} else {
None
}
}
}
pub struct GlslVersion {
pub major: u16,
pub minor: u16,
pub is_gles: bool,
}
impl GlslVersion {
pub fn read<G: glow::HasContext>(gl: &G) -> Self {
Self::parse(&unsafe { gl.get_parameter_string(glow::SHADING_LANGUAGE_VERSION) })
}
/// Parse the OpenGL version from the version string queried from the driver
/// via the `GL_SHADING_LANGUAGE_VERSION` enum.
///
/// Version strings are documented to be in the form
/// `<major>.<minor>[.<release>][ <vendor specific information>]`
/// for full-fat OpenGL, and
/// `OpenGL ES GLSL ES <major>.<minor>[.<release>][ <vendor specific information>]`
/// for OpenGL ES (however, strings omitting that prefix have been observed).
///
/// Examples based on strings found in the wild:
/// ```rust
/// # use imgui_glow_renderer::versions::GlslVersion;
/// let version = GlslVersion::parse("4.60 NVIDIA");
/// assert!(!version.is_gles);
/// assert_eq!(version.major, 4);
/// assert_eq!(version.minor, 6);
/// let version = GlslVersion::parse("OpenGL ES GLSL ES 3.20");
/// assert!(version.is_gles);
/// assert_eq!(version.major, 3);
/// assert_eq!(version.minor, 2);
/// ```
pub fn parse(gl_shading_language_version: &str) -> Self {
let (version_string, is_gles) = gl_shading_language_version
.strip_prefix("OpenGL ES GLSL ES ")
.map_or_else(
|| (gl_shading_language_version, false),
|version| (version, true),
);
let mut parts = version_string.split(|c: char| !c.is_numeric());
let major = parts.next().unwrap_or("0").parse().unwrap_or(0);
let minor = parts.next().unwrap_or("0").parse().unwrap_or(0);
// The minor version has been observed specified as both a single- or
// double-digit version
let minor = if minor >= 10 { minor / 10 } else { minor };
Self {
major,
minor,
is_gles,
}
}
}