tge/graphics/opengl/
texture.rs

1use super::{Filter, Wrap};
2use glow::{Context, HasContext, PixelUnpackData};
3use std::rc::Rc;
4
5pub type TextureId = <Context as HasContext>::Texture;
6
7pub struct Texture {
8    gl: Rc<Context>,
9    id: TextureId,
10}
11
12impl Texture {
13    pub fn new(gl: Rc<Context>) -> Result<Self, String> {
14        let id = unsafe {
15            gl.create_texture()?
16        };
17        Ok(Self { gl, id })
18    }
19
20    pub fn id(&self) -> TextureId {
21        self.id
22    }
23
24    pub fn bind(&self) {
25        unsafe {
26            self.gl.bind_texture(glow::TEXTURE_2D, Some(self.id));
27        }
28    }
29
30    pub fn unbind(&self) {
31        unsafe {
32            self.gl.bind_texture(glow::TEXTURE_2D, None);
33        }
34    }
35
36    pub fn init_image(&self, width: u32, height: u32, pixels: Option<&[u8]>) {
37        unsafe {
38            self.gl.tex_image_2d(
39                glow::TEXTURE_2D,
40                0,
41                glow::RGBA as i32,
42                width as i32,
43                height as i32,
44                0,
45                glow::RGBA,
46                glow::UNSIGNED_BYTE,
47                pixels,
48            );
49        }
50    }
51
52    pub fn sub_image(&self, offset_x: u32, offset_y: u32, width: u32, height: u32, pixels: Option<&[u8]>) {
53        unsafe {
54            self.gl.tex_sub_image_2d(
55                glow::TEXTURE_2D,
56                0,
57                offset_x as i32,
58                offset_y as i32,
59                width as i32,
60                height as i32,
61                glow::RGBA,
62                glow::UNSIGNED_BYTE,
63                match pixels {
64                    Some(pixels) => PixelUnpackData::Slice(pixels),
65                    None => PixelUnpackData::BufferOffset(0),
66                },
67            );
68        }
69    }
70
71    pub fn set_filter(&self, filter: Filter) {
72        unsafe {
73            self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, filter.to_min_flag() as i32);
74            self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, filter.to_mag_flag() as i32);
75        }
76    }
77
78    pub fn generate_mipmap(&self) {
79        unsafe {
80            self.gl.generate_mipmap(glow::TEXTURE_2D);
81        }
82    }
83
84    pub fn set_wrap(&self, wrap: Wrap) {
85        unsafe {
86            self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, wrap.horizontal.to_flag() as i32);
87            self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, wrap.vertical.to_flag() as i32);
88        }
89    }
90}
91
92impl Drop for Texture {
93    fn drop(&mut self) {
94        unsafe {
95            self.gl.delete_texture(self.id);
96        }
97    }
98}
99
100impl PartialEq for Texture {
101    fn eq(&self, other: &Self) -> bool {
102        self.id == other.id
103    }
104}