summaryrefslogtreecommitdiff
path: root/engine/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/opengl')
-rw-r--r--engine/src/opengl/texture.rs96
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