diff options
author | HampusM <hampus@hampusmat.com> | 2023-11-26 13:36:16 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2023-11-26 13:36:16 +0100 |
commit | 935f35455ac2e3547cdd21cd4596538958a7217e (patch) | |
tree | 98ed3752b1f4fbe5e95262185704544ba8be85ae /engine/src/opengl | |
parent | c4c599ae00e6a73126637bd73dce33522f5a9fef (diff) |
feat(engine): make textures clonable
Diffstat (limited to 'engine/src/opengl')
-rw-r--r-- | engine/src/opengl/texture.rs | 96 |
1 files changed, 82 insertions, 14 deletions
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<Self>, + curr_bound: &CurrentlyBound<Self>, dimens: &Vec2<u32>, 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<u32>, + pixel_data_format: PixelDataFormat, + src_offset: &Vec2<u32>, + dst_offset: &Vec2<u32>, + ) -> 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<Self>, + pixel_data_format: PixelDataFormat, + dimens: &Vec2<u32>, + 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 |