use bitflags::bitflags; use crate::data_types::{Dimens, Vec2}; use crate::CurrentContextWithFns; /// Sets the viewport. /// /// The `u32` values in `position` and `size` must fit in `i32`s. /// /// # Errors /// Returns `Err` if any value in `position` or `size` does not fit into a `i32`. pub fn set_viewport( current_context: &CurrentContextWithFns<'_>, position: &Vec2, size: &Dimens, ) -> Result<(), SetViewportError> { let position = Vec2:: { x: position.x.try_into().map_err(|_| { SetViewportError::PositionXValueTooLarge { value: position.x, max_value: crate::sys::types::GLint::MAX as u32, } })?, y: position.y.try_into().map_err(|_| { SetViewportError::PositionYValueTooLarge { value: position.y, max_value: crate::sys::types::GLint::MAX as u32, } })?, }; let size = Dimens:: { width: size.width.try_into().map_err(|_| { SetViewportError::SizeWidthValueTooLarge { value: size.width, max_value: crate::sys::types::GLsizei::MAX as u32, } })?, height: size.height.try_into().map_err(|_| { SetViewportError::SizeHeightValueTooLarge { value: size.height, max_value: crate::sys::types::GLsizei::MAX as u32, } })?, }; unsafe { current_context .fns() .Viewport(position.x, position.y, size.width, size.height); } Ok(()) } pub fn clear_buffers(current_context: &CurrentContextWithFns<'_>, mask: BufferClearMask) { unsafe { current_context.fns().Clear(mask.bits()); } } pub fn set_polygon_mode( current_context: &CurrentContextWithFns<'_>, face: impl Into, mode: impl Into, ) { unsafe { current_context .fns() .PolygonMode(face.into() as u32, mode.into() as u32); } } pub fn enable(current_context: &CurrentContextWithFns<'_>, capacity: Capability) { unsafe { current_context.fns().Enable(capacity as u32); } } pub fn disable(current_context: &CurrentContextWithFns<'_>, capability: Capability) { unsafe { current_context.fns().Disable(capability as u32); } } pub fn set_enabled( current_context: &CurrentContextWithFns<'_>, capability: Capability, enabled: bool, ) { if enabled { enable(current_context, capability); } else { disable(current_context, capability); } } #[must_use] pub fn get_context_flags(current_context: &CurrentContextWithFns<'_>) -> ContextFlags { let mut context_flags = crate::sys::types::GLint::default(); unsafe { current_context .fns() .GetIntegerv(crate::sys::CONTEXT_FLAGS, &raw mut context_flags); } ContextFlags::from_bits_truncate(context_flags.cast_unsigned()) } bitflags! { #[derive(Debug, Clone, Copy)] pub struct BufferClearMask: u32 { const COLOR = crate::sys::COLOR_BUFFER_BIT; const DEPTH = crate::sys::DEPTH_BUFFER_BIT; const STENCIL = crate::sys::STENCIL_BUFFER_BIT; } } #[derive(Debug)] #[repr(u32)] pub enum Capability { DepthTest = crate::sys::DEPTH_TEST, MultiSample = crate::sys::MULTISAMPLE, DebugOutput = crate::sys::DEBUG_OUTPUT, DebugOutputSynchronous = crate::sys::DEBUG_OUTPUT_SYNCHRONOUS, } #[derive(Debug)] #[repr(u32)] pub enum PolygonMode { Point = crate::sys::POINT, Line = crate::sys::LINE, Fill = crate::sys::FILL, } #[derive(Debug)] #[repr(u32)] pub enum PolygonModeFace { Front = crate::sys::FRONT, Back = crate::sys::BACK, FrontAndBack = crate::sys::FRONT_AND_BACK, } bitflags! { #[derive(Debug, Clone, Copy)] pub struct ContextFlags: u32 { const FORWARD_COMPATIBLE = crate::sys::CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; const DEBUG = crate::sys::CONTEXT_FLAG_DEBUG_BIT; const ROBUST_ACCESS = crate::sys::CONTEXT_FLAG_ROBUST_ACCESS_BIT; } } #[derive(Debug, thiserror::Error)] pub enum SetViewportError { #[error("Position X value ({value}) is too large. Must be < {max_value}")] PositionXValueTooLarge { value: u32, max_value: u32 }, #[error("Position Y value ({value}) is too large. Must be < {max_value}")] PositionYValueTooLarge { value: u32, max_value: u32 }, #[error("Size width value ({value}) is too large. Must be < {max_value}")] SizeWidthValueTooLarge { value: u32, max_value: u32 }, #[error("Size height value ({value}) is too large. Must be < {max_value}")] SizeHeightValueTooLarge { value: u32, max_value: u32 }, }