From 935f35455ac2e3547cdd21cd4596538958a7217e Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 26 Nov 2023 13:36:16 +0100 Subject: feat(engine): make textures clonable --- engine/src/opengl/texture.rs | 96 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 14 deletions(-) (limited to 'engine/src/opengl') diff --git a/engine/src/opengl/texture.rs b/engine/src/opengl/texture.rs index 68ac050..4186479 100644 --- a/engine/src/opengl/texture.rs +++ b/engine/src/opengl/texture.rs @@ -1,3 +1,5 @@ +use std::ptr::null; + use crate::opengl::currently_bound::CurrentlyBound; use crate::vector::Vec2; @@ -33,26 +35,15 @@ impl Texture } pub fn generate( - _: &CurrentlyBound, + curr_bound: &CurrentlyBound, dimens: &Vec2, data: &[u8], pixel_data_format: PixelDataFormat, ) { - #[allow(clippy::cast_possible_wrap)] - unsafe { - gl::TexImage2D( - gl::TEXTURE_2D, - 0, - pixel_data_format.to_gl() as i32, - dimens.x as i32, - dimens.y as i32, - 0, - pixel_data_format.to_gl(), - gl::UNSIGNED_BYTE, - data.as_ptr().cast(), - ); + Self::alloc_image(curr_bound, pixel_data_format, dimens, Some(data)); + unsafe { gl::GenerateMipmap(gl::TEXTURE_2D); } } @@ -95,6 +86,83 @@ impl Texture ); } } + + /// Creates a copy of the texture & the texture images. + /// + /// `src_offset` and `dst_offset` are source & destination offsets from the + /// bottom-left of the images. + /// + /// New mipmaps are generated using the largest mipmap. + pub fn copy( + &self, + dimensions: &Vec2, + pixel_data_format: PixelDataFormat, + src_offset: &Vec2, + dst_offset: &Vec2, + ) -> Self + { + let new_texture = Self::new(); + + new_texture.bind(|curr_bound| { + Self::alloc_image(&curr_bound, pixel_data_format, dimensions, None); + + // Mipmap have to be generated since CopyImageSubData demands that the + // destination texture is completed + unsafe { + gl::GenerateMipmap(gl::TEXTURE_2D); + } + }); + + #[allow(clippy::cast_possible_wrap)] + unsafe { + gl::CopyImageSubData( + self.texture, + gl::TEXTURE_2D, + 0, + src_offset.x as i32, + src_offset.y as i32, + 0, + new_texture.texture, + gl::TEXTURE_2D, + 0, + dst_offset.x as i32, + dst_offset.y as i32, + 0, + dimensions.x as i32, + dimensions.y as i32, + 1, + ); + } + + unsafe { + gl::GenerateMipmap(gl::TEXTURE_2D); + } + + new_texture + } + + fn alloc_image( + _: &CurrentlyBound, + pixel_data_format: PixelDataFormat, + dimens: &Vec2, + data: Option<&[u8]>, + ) + { + unsafe { + #[allow(clippy::cast_possible_wrap)] + gl::TexImage2D( + gl::TEXTURE_2D, + 0, + pixel_data_format.to_gl() as i32, + dimens.x as i32, + dimens.y as i32, + 0, + pixel_data_format.to_gl(), + gl::UNSIGNED_BYTE, + data.map_or_else(null, |data| data.as_ptr().cast()), + ); + } + } } impl Drop for Texture -- cgit v1.2.3-18-g5258