use crate::data_types::dimens::Dimens; #[derive(Debug)] pub struct Texture { texture: gl::types::GLuint, } impl Texture { pub fn new() -> Self { let mut texture = gl::types::GLuint::default(); unsafe { gl::CreateTextures(gl::TEXTURE_2D, 1, &mut texture); }; Self { texture } } pub fn bind_to_texture_unit(&self, texture_unit: u32) { unsafe { gl::BindTextureUnit(texture_unit, self.texture); } } pub fn generate( &mut self, dimens: Dimens, data: &[u8], pixel_data_format: PixelDataFormat, ) { self.alloc_image(pixel_data_format, dimens, data); unsafe { gl::GenerateTextureMipmap(self.texture); } } pub fn set_wrap(&mut self, wrapping: Wrapping) { let wrapping_gl = wrapping as gl::types::GLenum; #[allow(clippy::cast_possible_wrap)] unsafe { gl::TextureParameteri(self.texture, gl::TEXTURE_WRAP_S, wrapping_gl as i32); gl::TextureParameteri(self.texture, gl::TEXTURE_WRAP_T, wrapping_gl as i32); } } pub fn set_magnifying_filter(&mut self, filtering: Filtering) { let filtering_gl = filtering as gl::types::GLenum; #[allow(clippy::cast_possible_wrap)] unsafe { gl::TextureParameteri( self.texture, gl::TEXTURE_MAG_FILTER, filtering_gl as i32, ); } } pub fn set_minifying_filter(&mut self, filtering: Filtering) { let filtering_gl = filtering as gl::types::GLenum; #[allow(clippy::cast_possible_wrap)] unsafe { gl::TextureParameteri( self.texture, gl::TEXTURE_MIN_FILTER, filtering_gl as i32, ); } } fn alloc_image( &mut self, pixel_data_format: PixelDataFormat, dimens: Dimens, data: &[u8], ) { unsafe { #[allow(clippy::cast_possible_wrap)] gl::TextureStorage2D( self.texture, 1, pixel_data_format.to_sized_internal_format(), dimens.width as i32, dimens.height as i32, ); #[allow(clippy::cast_possible_wrap)] gl::TextureSubImage2D( self.texture, 0, 0, 0, dimens.width as i32, dimens.height as i32, pixel_data_format.to_format(), gl::UNSIGNED_BYTE, data.as_ptr().cast(), ); } } } impl Drop for Texture { fn drop(&mut self) { unsafe { gl::DeleteTextures(1, &self.texture); } } } /// Texture wrapping. #[derive(Debug, Clone, Copy)] #[repr(u32)] pub enum Wrapping { Repeat = gl::REPEAT, MirroredRepeat = gl::MIRRORED_REPEAT, ClampToEdge = gl::CLAMP_TO_EDGE, ClampToBorder = gl::CLAMP_TO_BORDER, } #[derive(Debug, Clone, Copy)] #[repr(u32)] pub enum Filtering { Nearest = gl::NEAREST, Linear = gl::LINEAR, } /// Texture pixel data format. #[derive(Debug, Clone, Copy)] pub enum PixelDataFormat { Rgb8, Rgba8, } impl PixelDataFormat { fn to_sized_internal_format(self) -> gl::types::GLenum { match self { Self::Rgb8 => gl::RGB8, Self::Rgba8 => gl::RGBA8, } } fn to_format(self) -> gl::types::GLenum { match self { Self::Rgb8 => gl::RGB, Self::Rgba8 => gl::RGBA, } } }