summaryrefslogtreecommitdiff
path: root/engine/src
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src')
-rw-r--r--engine/src/opengl/texture.rs96
-rw-r--r--engine/src/texture.rs27
2 files changed, 107 insertions, 16 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
diff --git a/engine/src/texture.rs b/engine/src/texture.rs
index bde3cd2..f32bc0a 100644
--- a/engine/src/texture.rs
+++ b/engine/src/texture.rs
@@ -17,6 +17,8 @@ pub use reexports::*;
pub struct Texture
{
inner: InnerTexture,
+ pixel_data_format: PixelDataFormat,
+ dimensions: Vec2<u32>,
}
impl Texture
@@ -45,16 +47,18 @@ impl Texture
let inner = InnerTexture::new();
+ let dimensions = Vec2 { x: image.width(), y: image.height() };
+
inner.bind(|texture_curr_bound| {
InnerTexture::generate(
&texture_curr_bound,
- &Vec2 { x: image.width(), y: image.height() },
+ &dimensions,
image.as_bytes(),
pixel_data_format,
);
});
- let me = Self { inner };
+ let me = Self { inner, pixel_data_format, dimensions };
me.set_wrap(Wrapping::Repeat);
me.set_magnifying_filter(Filtering::Linear);
@@ -90,6 +94,25 @@ impl Texture
}
}
+impl Clone for Texture
+{
+ fn clone(&self) -> Self
+ {
+ let inner = self.inner.copy(
+ &self.dimensions,
+ self.pixel_data_format,
+ &Vec2::ZERO,
+ &Vec2::ZERO,
+ );
+
+ Self {
+ inner,
+ pixel_data_format: self.pixel_data_format,
+ dimensions: self.dimensions.clone(),
+ }
+ }
+}
+
/// Texture error.
#[derive(Debug, thiserror::Error)]
pub enum Error