globject_rs/
gltexture.rs

1
2#![allow(clippy::too_many_arguments)]
3
4use crate::prelude::*;
5use std::{
6	any::type_name,
7	ffi::{OsStr, c_void},
8	fmt::{self, Debug, Formatter},
9	marker::PhantomData,
10	mem::size_of_val,
11	path::Path,
12	ptr::null,
13	rc::Rc,
14};
15use image::{ImageReader, Pixel, ImageBuffer, RgbImage, DynamicImage};
16
17/// The dimension of the texture represents the type of texture
18#[derive(Clone, Copy, PartialEq)]
19pub enum TextureDimension {
20	Tex1d = GL_TEXTURE_1D as isize,
21	Tex2d = GL_TEXTURE_2D as isize,
22	Tex3d = GL_TEXTURE_3D as isize,
23	TexCube = GL_TEXTURE_CUBE_MAP as isize,
24}
25
26/// The binding target of the texture includes the 6 faces of a cubemap
27#[derive(Clone, Copy, PartialEq)]
28pub enum TextureTarget {
29	Tex1d = GL_TEXTURE_1D as isize,
30	Tex2d = GL_TEXTURE_2D as isize,
31	Tex3d = GL_TEXTURE_3D as isize,
32	TexCube = GL_TEXTURE_CUBE_MAP as isize,
33	TexCubePosX = GL_TEXTURE_CUBE_MAP_POSITIVE_X as isize,
34	TexCubeNegX = GL_TEXTURE_CUBE_MAP_NEGATIVE_X as isize,
35	TexCubePosY = GL_TEXTURE_CUBE_MAP_POSITIVE_Y as isize,
36	TexCubeNegY = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y as isize,
37	TexCubePosZ = GL_TEXTURE_CUBE_MAP_POSITIVE_Z as isize,
38	TexCubeNegZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z as isize,
39}
40
41/// The cubemap faces enum
42#[derive(Clone, Copy, PartialEq)]
43pub enum CubeMapFaces {
44	TexCubePosX = TextureTarget::TexCubePosX as isize,
45	TexCubeNegX = TextureTarget::TexCubeNegX as isize,
46	TexCubePosY = TextureTarget::TexCubePosY as isize,
47	TexCubeNegY = TextureTarget::TexCubeNegY as isize,
48	TexCubePosZ = TextureTarget::TexCubePosZ as isize,
49	TexCubeNegZ = TextureTarget::TexCubeNegZ as isize,
50}
51
52/// The constant helps to conveniently iterate through the 6 faces of a cubemap
53pub const CUBE_FACE_TARGETS: [CubeMapFaces; 6] = [
54	CubeMapFaces::TexCubePosX,
55	CubeMapFaces::TexCubeNegX,
56	CubeMapFaces::TexCubePosY,
57	CubeMapFaces::TexCubeNegY,
58	CubeMapFaces::TexCubePosZ,
59	CubeMapFaces::TexCubeNegZ,
60];
61
62/// The **internal format** of the texture indicates how the pixels are stored in the GPU texture
63#[derive(Clone, Copy, PartialEq)]
64pub enum TextureFormat {
65	Depth = GL_DEPTH_COMPONENT as isize,
66	DepthStencil = GL_DEPTH_STENCIL as isize,
67	Red = GL_RED as isize,
68	Rg = GL_RG as isize,
69	Rgb = GL_RGB as isize,
70	Rgba = GL_RGBA as isize,
71	Red8 = GL_R8 as isize,
72	Red8Snorm = GL_R8_SNORM as isize,
73	Red16 = GL_R16 as isize,
74	Red16Snorm = GL_R16_SNORM as isize,
75	Rg8 = GL_RG8 as isize,
76	Rg8Snorm = GL_RG8_SNORM as isize,
77	Rg16 = GL_RG16 as isize,
78	Rg16Snorm = GL_RG16_SNORM as isize,
79	R3g3b2 = GL_R3_G3_B2 as isize,
80	Rgb4 = GL_RGB4 as isize,
81	Rgb5 = GL_RGB5 as isize,
82	Rgb8 = GL_RGB8 as isize,
83	Rgb8Snorm = GL_RGB8_SNORM as isize,
84	Rgb10 = GL_RGB10 as isize,
85	Rgb12 = GL_RGB12 as isize,
86	Rgb16Snorm = GL_RGB16_SNORM as isize,
87	Rgba2 = GL_RGBA2 as isize,
88	Rgba4 = GL_RGBA4 as isize,
89	Rgb5a1 = GL_RGB5_A1 as isize,
90	Rgba8 = GL_RGBA8 as isize,
91	Rgba8Snorm = GL_RGBA8_SNORM as isize,
92	Rgb10a2 = GL_RGB10_A2 as isize,
93	Rgb10a2ui = GL_RGB10_A2UI as isize,
94	Rgba12 = GL_RGBA12 as isize,
95	Rgba16 = GL_RGBA16 as isize,
96	R32f = GL_R32F as isize,
97	Rg32f = GL_RG32F as isize,
98	Rgb32f = GL_RGB32F as isize,
99	Rgba32f = GL_RGBA32F as isize,
100	R11fg11fb10f = GL_R11F_G11F_B10F as isize,
101	Rgb9e5 = GL_RGB9_E5 as isize,
102	R8i = GL_R8I as isize,
103	R8ui = GL_R8UI as isize,
104	R16i = GL_R16I as isize,
105	R16ui = GL_R16UI as isize,
106	R32i = GL_R32I as isize,
107	R32ui = GL_R32UI as isize,
108	Rg8i = GL_RG8I as isize,
109	Rg8ui = GL_RG8UI as isize,
110	Rg16i = GL_RG16I as isize,
111	Rg16ui = GL_RG16UI as isize,
112	Rg32i = GL_RG32I as isize,
113	Rg32ui = GL_RG32UI as isize,
114	Rgb8i = GL_RGB8I as isize,
115	Rgb8ui = GL_RGB8UI as isize,
116	Rgb16i = GL_RGB16I as isize,
117	Rgb16ui = GL_RGB16UI as isize,
118	Rgb32i = GL_RGB32I as isize,
119	Rgb32ui = GL_RGB32UI as isize,
120	Rgba8i = GL_RGBA8I as isize,
121	Rgba8ui = GL_RGBA8UI as isize,
122	Rgba16i = GL_RGBA16I as isize,
123	Rgba16ui = GL_RGBA16UI as isize,
124	Rgba32i = GL_RGBA32I as isize,
125	Rgba32ui = GL_RGBA32UI as isize,
126}
127
128/// The wrapping rules of the textures
129#[derive(Clone, Copy, PartialEq)]
130pub enum TextureWrapping {
131	ClampToEdge = GL_CLAMP_TO_EDGE as isize,
132	ClampToBorder = GL_CLAMP_TO_BORDER as isize,
133	MirrorClampToEdge = GL_MIRROR_CLAMP_TO_EDGE as isize,
134
135	/// **NOTE**: `Repeat` is only supported to the 2^N size of the textures by most of the GPU
136	Repeat = GL_REPEAT as isize,
137
138	/// **NOTE**: `MirroredRepeat` is only supported to the 2^N size of the textures by most of the GPU
139	MirroredRepeat = GL_MIRRORED_REPEAT as isize,
140}
141
142/// The sampler filters of the textures, including how mipmap sampling should be done
143#[derive(Clone, Copy, PartialEq)]
144pub enum SamplerFilter {
145	Nearest = GL_NEAREST as isize,
146	Linear = GL_LINEAR as isize,
147	NearestMipmapNearest = GL_NEAREST_MIPMAP_NEAREST as isize,
148	LinearMipmapNearest = GL_LINEAR_MIPMAP_NEAREST as isize,
149	NearestMipmapLinear = GL_NEAREST_MIPMAP_LINEAR as isize,
150	LinearMipmapLinear = GL_LINEAR_MIPMAP_LINEAR as isize,
151}
152
153/// The sampler filters of the textures, only for magnifying sampling
154#[derive(Clone, Copy, PartialEq)]
155pub enum SamplerMagFilter {
156	Nearest = GL_NEAREST as isize,
157	Linear = GL_LINEAR as isize,
158}
159
160/// The channel type of a pixel
161#[derive(Clone, Copy, PartialEq)]
162pub enum ChannelType {
163	Red = GL_RED as isize,
164	Rg = GL_RG as isize,
165	Rgb = GL_RGB as isize,
166	Bgr = GL_BGR as isize,
167	Rgba = GL_RGBA as isize,
168	Bgra = GL_BGRA as isize,
169	RedInteger = GL_RED_INTEGER as isize,
170	RgInteger = GL_RG_INTEGER as isize,
171	RgbInteger = GL_RGB_INTEGER as isize,
172	BgrInteger = GL_BGR_INTEGER as isize,
173	RgbaInteger = GL_RGBA_INTEGER as isize,
174	BgraInteger = GL_BGRA_INTEGER as isize,
175	StencilIndex = GL_STENCIL_INDEX as isize,
176	Depth = GL_DEPTH_COMPONENT as isize,
177	DepthStencil = GL_DEPTH_STENCIL as isize,
178}
179
180/// The component type for each channel of a pixel
181#[derive(Clone, Copy, PartialEq)]
182pub enum ComponentType {
183	U8 = GL_UNSIGNED_BYTE as isize,
184	I8 = GL_BYTE as isize,
185	U16 = GL_UNSIGNED_SHORT as isize,
186	I16 = GL_SHORT as isize,
187	U32 = GL_UNSIGNED_INT as isize,
188	I32 = GL_INT as isize,
189	F16 = GL_HALF_FLOAT as isize,
190	F32 = GL_FLOAT as isize,
191	U8_332 = GL_UNSIGNED_BYTE_3_3_2 as isize,
192	U8_233Rev = GL_UNSIGNED_BYTE_2_3_3_REV as isize,
193	U16_565 = GL_UNSIGNED_SHORT_5_6_5 as isize,
194	U16_565Rev = GL_UNSIGNED_SHORT_5_6_5_REV as isize,
195	U16_4444 = GL_UNSIGNED_SHORT_4_4_4_4 as isize,
196	U16_4444Rev = GL_UNSIGNED_SHORT_4_4_4_4_REV as isize,
197	U16_5551 = GL_UNSIGNED_SHORT_5_5_5_1 as isize,
198	U16_1555Rev = GL_UNSIGNED_SHORT_1_5_5_5_REV as isize,
199	U32_8888 = GL_UNSIGNED_INT_8_8_8_8 as isize,
200	U32_8888Rev = GL_UNSIGNED_INT_8_8_8_8_REV as isize,
201	U32_10_10_10_2 = GL_UNSIGNED_INT_10_10_10_2 as isize,
202	U32_2_10_10_10Rev = GL_UNSIGNED_INT_2_10_10_10_REV as isize,
203}
204
205/// Get the size for each pixel
206pub fn size_of_pixel(channel_type: ChannelType, component_type: ComponentType) -> usize {
207	let component_len = match component_type {
208		ComponentType::U8_332 |
209		ComponentType::U8_233Rev => return 1,
210		ComponentType::U16_565 |
211		ComponentType::U16_565Rev |
212		ComponentType::U16_4444 |
213		ComponentType::U16_4444Rev |
214		ComponentType::U16_5551 |
215		ComponentType::U16_1555Rev => return 2,
216		ComponentType::U32_8888 |
217		ComponentType::U32_8888Rev |
218		ComponentType::U32_10_10_10_2 |
219		ComponentType::U32_2_10_10_10Rev => return 4,
220		ComponentType::U8 |
221		ComponentType::I8 => 1,
222		ComponentType::U16 |
223		ComponentType::I16 |
224		ComponentType::F16 => 2,
225		ComponentType::U32 |
226		ComponentType::I32 |
227		ComponentType::F32 => 4,
228	};
229	match channel_type {
230		ChannelType::Red |
231		ChannelType::RedInteger |
232		ChannelType::StencilIndex |
233		ChannelType::Depth => component_len,
234		ChannelType::Rg |
235		ChannelType::RgInteger |
236		ChannelType::DepthStencil => component_len * 2,
237		ChannelType::Rgb |
238		ChannelType::RgbInteger |
239		ChannelType::Bgr |
240		ChannelType::BgrInteger => component_len * 3,
241		ChannelType::Rgba |
242		ChannelType::RgbaInteger |
243		ChannelType::Bgra |
244		ChannelType::BgraInteger => component_len * 4,
245	}
246}
247
248/// The pixel type trait must be able to be a `BufferVec` item
249pub trait PixelType: BufferVecItem {}
250impl<T> PixelType for T where T: BufferVecItem {}
251
252/// The pixel buffer object (PBO) for the texture helps with asynchronous texture updating or retrieving back to the system memory
253#[derive(Debug)]
254pub struct PixelBuffer<B, BP>
255where
256	B: BufferVec<BP>,
257	BP: BufferVecItem {
258	buffer: B,
259	pixel_size: usize,
260	width: u32,
261	height: u32,
262	depth: u32,
263	pitch: usize,
264	pitch_wh: usize,
265	channel_type: ChannelType,
266	component_type: ComponentType,
267	_pixel_type: PhantomData<BP>,
268}
269
270/// The OpenGL texture object
271pub struct Texture<B, BP>
272where
273	B: BufferVec<BP>,
274	BP: BufferVecItem {
275	pub glcore: Rc<GLCore>,
276	name: u32,
277	dim: TextureDimension,
278	format: TextureFormat,
279	width: u32,
280	height: u32,
281	depth: u32,
282	has_mipmap: bool,
283	mag_filter: SamplerMagFilter,
284	min_filter: SamplerFilter,
285	bytes_of_texture: usize,
286	bytes_of_face: usize,
287	pixel_buffer: Option<PixelBuffer<B, BP>>,
288	_pixel_type: PhantomData<BP>,
289}
290
291/// The binding state of the texture, utilizing the RAII rules to manage the binding state
292pub struct TextureBind<'a> {
293	pub texture: &'a dyn GenericTexture,
294	target: TextureTarget,
295}
296
297/// The error for loading an image from a file, decoding the byte stream of the image
298#[derive(Debug)]
299pub enum LoadImageError {
300	IOError(std::io::Error),
301	TurboJpegError(turbojpeg::Error),
302	ImageError(image::ImageError),
303	UnsupportedImageType(String),
304}
305
306impl From<std::io::Error> for LoadImageError {
307	fn from(err: std::io::Error) -> Self {
308		Self::IOError(err)
309	}
310}
311
312impl From<turbojpeg::Error> for LoadImageError {
313	fn from(err: turbojpeg::Error) -> Self {
314		Self::TurboJpegError(err)
315	}
316}
317
318impl From<image::ImageError> for LoadImageError {
319	fn from(err: image::ImageError) -> Self {
320		Self::ImageError(err)
321	}
322}
323
324impl TextureFormat {
325	/// Get how many bits that composed of a pixel. The implementation is just to ask anything from OpenGL
326	pub fn bits_of_pixel(&self, glcore: &GLCore, target: TextureTarget) -> usize {
327		let target = target as u32;
328		let mut data: i32 = 0;
329		let mut size: usize = 0;
330		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_DEPTH_SIZE, &mut data as *mut _);		size += data as usize;
331		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &mut data as *mut _);	size += data as usize;
332		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_RED_SIZE, &mut data as *mut _);		size += data as usize;
333		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_GREEN_SIZE, &mut data as *mut _);		size += data as usize;
334		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_BLUE_SIZE, &mut data as *mut _);		size += data as usize;
335		glcore.glGetTexLevelParameteriv(target, 0, GL_TEXTURE_ALPHA_SIZE, &mut data as *mut _);		size += data as usize;
336		size
337	}
338
339	/// Create a `TextureFormat` from the channel type and the component type, returns `None` if the combination couldn't have its corresponding format
340	pub fn from_channel_type_and_component_type(channel_type: ChannelType, component_type: ComponentType) -> Option<Self> {
341		match component_type {
342			ComponentType::U8_332 => Some(Self::R3g3b2),
343			ComponentType::U16_4444 => Some(Self::Rgba4),
344			ComponentType::U16_5551 => Some(Self::Rgb5a1),
345			ComponentType::U32_8888 => Some(Self::Rgba8),
346			ComponentType::U32_10_10_10_2 => Some(Self::Rgb10a2),
347			ComponentType::I8 => match channel_type {
348				ChannelType::Red =>  Some(Self::R8i),
349				ChannelType::Rg =>   Some(Self::Rg8i),
350				ChannelType::Rgb =>  Some(Self::Rgb8i),
351				ChannelType::Rgba => Some(Self::Rgba8i),
352				_ => None,
353			}
354			ComponentType::U8 => match channel_type {
355				ChannelType::Red =>  Some(Self::R8ui),
356				ChannelType::Rg =>   Some(Self::Rg8ui),
357				ChannelType::Rgb =>  Some(Self::Rgb8ui),
358				ChannelType::Rgba => Some(Self::Rgba8ui),
359				_ => None,
360			}
361			ComponentType::I16 => match channel_type {
362				ChannelType::Red =>  Some(Self::R16i),
363				ChannelType::Rg =>   Some(Self::Rg16i),
364				ChannelType::Rgb =>  Some(Self::Rgb16i),
365				ChannelType::Rgba => Some(Self::Rgba16i),
366				_ => None,
367			}
368			ComponentType::U16 => match channel_type {
369				ChannelType::Red =>  Some(Self::R16ui),
370				ChannelType::Rg =>   Some(Self::Rg16ui),
371				ChannelType::Rgb =>  Some(Self::Rgb16ui),
372				ChannelType::Rgba => Some(Self::Rgba16ui),
373				_ => None,
374			}
375			ComponentType::I32 => match channel_type {
376				ChannelType::Red =>  Some(Self::R32i),
377				ChannelType::Rg =>   Some(Self::Rg32i),
378				ChannelType::Rgb =>  Some(Self::Rgb32i),
379				ChannelType::Rgba => Some(Self::Rgba32i),
380				_ => None,
381			}
382			ComponentType::U32 => match channel_type {
383				ChannelType::Red =>  Some(Self::R32ui),
384				ChannelType::Rg =>   Some(Self::Rg32ui),
385				ChannelType::Rgb =>  Some(Self::Rgb32ui),
386				ChannelType::Rgba => Some(Self::Rgba32ui),
387				_ => None,
388			}
389			ComponentType::F32 => match channel_type {
390				ChannelType::Red =>  Some(Self::R32f),
391				ChannelType::Rg =>   Some(Self::Rg32f),
392				ChannelType::Rgb =>  Some(Self::Rgb32f),
393				ChannelType::Rgba => Some(Self::Rgba32f),
394				_ => None,
395			}
396			_ => None
397		}
398	}
399}
400
401impl ComponentType {
402	/// Get the component type from a string
403	pub fn from_typename(typename: &str) -> Self {
404		if typename.ends_with("u8" ) {Self::U8} else
405		if typename.ends_with("u16") {Self::U16} else
406		if typename.ends_with("u32") {Self::U32} else
407		if typename.ends_with("i8" ) {Self::I8} else
408		if typename.ends_with("i16") {Self::I16} else
409		if typename.ends_with("i32") {Self::I32} else
410		if typename.ends_with("f16") {Self::F16} else
411		if typename.ends_with("f32") {Self::F32} else
412		{panic!("Currently only supports: u8, u16, u32, i8, i16, i32, f16, f32.")}
413	}
414}
415
416/// Input a generic type of `P` as the pixel data type, retrieve the channel type, and the component type
417pub fn get_channel_type_and_component_type_from_image_pixel<P: Pixel>(channel_type: &mut ChannelType, component_type: &mut ComponentType) -> Result<(), LoadImageError> {
418	*component_type = ComponentType::from_typename(type_name::<P::Subpixel>());
419	*channel_type = match component_type {
420		ComponentType::I32 | ComponentType::U32 => {
421			match P::CHANNEL_COUNT {
422				1 => ChannelType::RedInteger,
423				2 => ChannelType::RgInteger,
424				3 => ChannelType::RgbInteger,
425				4 => ChannelType::RgbaInteger,
426				o => return Err(LoadImageError::UnsupportedImageType(format!("Unknown channel count ({o}) of the `ImageBuffer`"))),
427			}
428		}
429		_ => {
430			match P::CHANNEL_COUNT {
431				1 => ChannelType::Red,
432				2 => ChannelType::Rg,
433				3 => ChannelType::Rgb,
434				4 => ChannelType::Rgba,
435				o => return Err(LoadImageError::UnsupportedImageType(format!("Unknown channel count ({o}) of the `ImageBuffer`"))),
436			}
437		}
438	};
439	Ok(())
440}
441
442/// The `GenericPixelBuffer` trait helps the `PixelBuffer` struct to be able to turn into an object
443pub trait GenericPixelBuffer: Debug {
444	/// Get the underlying buffer
445	fn get_buffer(&self) -> &Buffer;
446
447	/// Get the channel type
448	fn get_channel_type(&self) -> ChannelType;
449
450	/// Get the component type
451	fn get_component_type(&self) -> ComponentType;
452
453	/// Get the size of the buffer
454	fn size_in_bytes(&self) -> usize {
455		self.get_buffer().size()
456	}
457
458	/// Create a `BufferBind` to use the RAII system to manage the binding state
459	fn bind<'a>(&'a self) -> BufferBind<'a> {
460		self.get_buffer().bind()
461	}
462}
463
464impl<B, BP> PixelBuffer<B, BP>
465where
466	B: BufferVec<BP>,
467	BP: BufferVecItem {
468	/// Create a new pixel buffer
469	pub fn new(glcore: Rc<GLCore>,
470			width: u32,
471			height: u32,
472			depth: u32,
473			size_in_bytes: usize,
474			channel_type: ChannelType,
475			component_type: ComponentType,
476			initial_data: Option<*const c_void>,
477		) -> Self {
478		let pixel_size = size_of_pixel(channel_type, component_type);
479		let pitch = ((width as usize * pixel_size - 1) / 4 + 1) * 4;
480		let pitch_wh = pitch * height as usize;
481		let buffer = match initial_data {
482			Some(initial_data) => Buffer::new(glcore.clone(), BufferTarget::PixelUnpackBuffer, size_in_bytes, BufferUsage::StreamDraw, initial_data),
483			None => {
484				let empty_data = vec![0u8; size_in_bytes];
485				Buffer::new(glcore.clone(), BufferTarget::PixelUnpackBuffer, size_in_bytes, BufferUsage::StreamDraw, empty_data.as_ptr() as *const c_void)
486			}
487		};
488		let buffer = B::from(buffer);
489		Self {
490			buffer,
491			pixel_size,
492			width,
493			height,
494			depth,
495			pitch,
496			pitch_wh,
497			channel_type,
498			component_type,
499			_pixel_type: PhantomData,
500		}
501	}
502
503	/// Create from an `ImageBuffer`
504	pub fn from_image<P: Pixel>(glcore: Rc<GLCore>, img: &ImageBuffer<P, Vec<P::Subpixel>>) -> Self {
505		let container = img.as_raw();
506		let mut channel_type = ChannelType::Rgb;
507		let mut component_type = ComponentType::U8;
508		get_channel_type_and_component_type_from_image_pixel::<P>(&mut channel_type, &mut component_type).unwrap();
509		Self::new(glcore, img.width(), img.height(), 1, size_of_val(&container[..]), channel_type, component_type, Some(container.as_ptr() as *const c_void))
510	}
511
512	/// Create from a file
513	pub fn from_file(glcore: Rc<GLCore>, path: &Path) -> Result<Self, LoadImageError> {
514		let ext = path.extension().map_or_else(|| String::new(), |ext| OsStr::to_str(ext).unwrap().to_lowercase());
515		match &ext[..] {
516			"jpg" | "jpeg" => {
517				let image_data = std::fs::read(path)?;
518				let img: RgbImage = turbojpeg::decompress_image(&image_data)?;
519				Ok(Self::from_image(glcore, &img))
520			}
521			_ => {
522				match ImageReader::open(path)?.decode()? {
523					DynamicImage::ImageLuma8(img) => Ok(Self::from_image(glcore, &img)),
524					DynamicImage::ImageLumaA8(img) => Ok(Self::from_image(glcore, &img)),
525					DynamicImage::ImageRgb8(img) => Ok(Self::from_image(glcore, &img)),
526					DynamicImage::ImageRgba8(img) => Ok(Self::from_image(glcore, &img)),
527					DynamicImage::ImageLuma16(img) => Ok(Self::from_image(glcore, &img)),
528					DynamicImage::ImageLumaA16(img) => Ok(Self::from_image(glcore, &img)),
529					DynamicImage::ImageRgb16(img) => Ok(Self::from_image(glcore, &img)),
530					DynamicImage::ImageRgba16(img) => Ok(Self::from_image(glcore, &img)),
531					DynamicImage::ImageRgb32F(img) => Ok(Self::from_image(glcore, &img)),
532					DynamicImage::ImageRgba32F(img) => Ok(Self::from_image(glcore, &img)),
533					_ => Err(LoadImageError::UnsupportedImageType(format!("Unsupported image type when loading pixel buffer from {path:?}"))),
534				}
535			}
536		}
537	}
538}
539
540impl<B, BP> GenericPixelBuffer for PixelBuffer<B, BP>
541where
542	B: BufferVec<BP>,
543	BP: BufferVecItem {
544	fn get_buffer(&self) -> &Buffer {
545		self.buffer.get_buffer()
546	}
547
548	fn get_channel_type(&self) -> ChannelType {
549		self.channel_type
550	}
551
552	fn get_component_type(&self) -> ComponentType {
553		self.component_type
554	}
555}
556
557/// The `GenericTexture` trait helps the `Texture` struct to be able to turn into an object
558pub trait GenericTexture: Debug {
559	/// Get the OpenGL core
560	fn get_glcore(&self) -> &GLCore;
561
562	/// Get the internal name of the texture
563	fn get_name(&self) -> u32;
564
565	/// Get the dimension of the texture
566	fn get_dim(&self) -> TextureDimension;
567
568	/// Get width
569	fn get_width(&self) -> u32;
570
571	/// Get height
572	fn get_height(&self) -> u32;
573
574	/// Get depth
575	fn get_depth(&self) -> u32;
576
577	/// Get the texture internal format
578	fn get_format(&self) -> TextureFormat;
579
580	/// Get byte of face
581	fn get_bytes_of_face(&self) -> usize;
582
583	/// Get byte of texture level 0
584	fn get_bytes_of_texture(&self) -> usize;
585
586	/// Get if have mipmap
587	fn has_mipmap(&self) -> bool;
588
589	/// Get the pixel buffer
590	fn get_pixel_buffer(&self) -> Option<&dyn GenericPixelBuffer>;
591
592	/// Create the PBO if not been created earlier
593	fn create_pixel_buffer(&mut self, buffer_channel_type: ChannelType, buffer_component_type: ComponentType, initial_data: Option<*const c_void>);
594
595	/// Discard the PBO if not necessarily need it
596	fn drop_pixel_buffer(&mut self);
597
598	/// Map the pixel buffer for the specified access
599	fn map_buffer<'a>(&'a mut self, access: MapAccess) -> Option<(BufferBind<'a>, BufferMapping<'a>, *mut c_void)> {
600		self.get_pixel_buffer().as_ref().map(|b|{
601			let bind = b.bind();
602			let (mapping, address) = bind.map(access);
603			(bind, mapping, address)
604		})
605	}
606
607	/// Bind the texture, using the RAII system to manage the binding state
608	fn bind<'a>(&'a self) -> TextureBind<'a>;
609
610	/// Bind a cubemap face, using the RAII system to manage the binding state
611	fn bind_face<'a>(&'a self, face: CubeMapFaces) -> TextureBind<'a>;
612
613	/// Retrieve the pixels from the texture to the specified data pointer regardless of is currently using a PBO or not
614	unsafe fn download_texture(&self, data: *mut c_void, buffer_channel_type: ChannelType, buffer_component_type: ComponentType) {
615		let glcore = self.get_glcore();
616		let pointer = data as *mut u8;
617		match self.get_dim() {
618			TextureDimension::Tex1d => {
619				let bind_tex = self.bind();
620				glcore.glGetTexImage(TextureTarget::Tex1d as u32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *mut c_void);
621				bind_tex.unbind();
622			}
623			TextureDimension::Tex2d => {
624				let bind_tex = self.bind();
625				glcore.glGetTexImage(TextureTarget::Tex2d as u32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *mut c_void);
626				bind_tex.unbind();
627			}
628			TextureDimension::Tex3d => {
629				let bind_tex = self.bind();
630				glcore.glGetTexImage(TextureTarget::Tex3d as u32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *mut c_void);
631				bind_tex.unbind();
632			}
633			TextureDimension::TexCube => {
634				for (i, target) in CUBE_FACE_TARGETS.iter().enumerate() {
635					let target = *target;
636					let bind_tex = self.bind_face(target);
637					let pointer = pointer.wrapping_add(i * self.get_bytes_of_face());
638					glcore.glGetTexImage(target as u32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *mut c_void);
639					bind_tex.unbind();
640				}
641			}
642		}
643	}
644
645	/// Load the texture with the specified data pointer regardless of is currently using a PBO or not
646	unsafe fn upload_texture(&self, data: *const c_void, buffer_channel_type: ChannelType, buffer_component_type: ComponentType, regen_mipmap: bool) {
647		let glcore = self.get_glcore();
648		let pointer = data as *const u8;
649		match self.get_dim() {
650			TextureDimension::Tex1d => {
651				let bind_tex = self.bind();
652				glcore.glTexImage1D(TextureTarget::Tex1d as u32, 0, self.get_format() as i32, self.get_width() as i32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *const c_void);
653				if regen_mipmap && self.has_mipmap() {
654					glcore.glGenerateMipmap(TextureTarget::Tex1d as u32);
655				}
656				bind_tex.unbind();
657			}
658			TextureDimension::Tex2d => {
659				let bind_tex = self.bind();
660				glcore.glTexImage2D(TextureTarget::Tex2d as u32, 0, self.get_format() as i32, self.get_width() as i32, self.get_height() as i32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *const c_void);
661				if regen_mipmap && self.has_mipmap() {
662					glcore.glGenerateMipmap(TextureTarget::Tex2d as u32);
663				}
664				bind_tex.unbind();
665			}
666			TextureDimension::Tex3d => {
667				let bind_tex = self.bind();
668				glcore.glTexImage3D(TextureTarget::Tex3d as u32, 0, self.get_format() as i32, self.get_width() as i32, self.get_height() as i32, self.get_depth() as i32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *const c_void);
669				if regen_mipmap && self.has_mipmap() {
670					glcore.glGenerateMipmap(TextureTarget::Tex3d as u32);
671				}
672				bind_tex.unbind();
673			}
674			TextureDimension::TexCube => {
675				for (i, target) in CUBE_FACE_TARGETS.iter().enumerate() {
676					let target = *target;
677					let bind_tex = self.bind_face(target);
678					let pointer = pointer.wrapping_add(i * self.get_bytes_of_face());
679					glcore.glTexImage2D(target as u32, 0, self.get_format() as i32, self.get_width() as i32, self.get_height() as i32, 0, buffer_channel_type as u32, buffer_component_type as u32, pointer as *const c_void);
680					if regen_mipmap && self.has_mipmap() {
681						glcore.glGenerateMipmap(target as u32);
682					}
683					bind_tex.unbind();
684				}
685			}
686		}
687	}
688
689	/// Read the pixels from the texture to the pixel buffer
690	fn pack_pixel_buffer(&self) {
691		let pixel_buffer = self.get_pixel_buffer().unwrap();
692		let buffer_channel_type = pixel_buffer.get_channel_type();
693		let buffer_component_type = pixel_buffer.get_component_type();
694		let bind_pbo = pixel_buffer.bind();
695		unsafe {self.download_texture(std::ptr::null_mut::<c_void>(), buffer_channel_type, buffer_component_type)};
696		bind_pbo.unbind();
697	}
698
699	/// Apply the change to the pixel buffer of the texture
700	fn unpack_pixel_buffer(&self, regen_mipmap: bool) {
701		let pixel_buffer = self.get_pixel_buffer().unwrap();
702		let buffer_channel_type = pixel_buffer.get_channel_type();
703		let buffer_component_type = pixel_buffer.get_component_type();
704		let bind_pbo = pixel_buffer.bind();
705		unsafe {self.upload_texture(std::ptr::null(), buffer_channel_type, buffer_component_type, regen_mipmap)};
706		bind_pbo.unbind();
707	}
708
709	/// Set the active texture unit
710	fn set_active_unit(&self, unit: u32) {
711		self.get_glcore().glActiveTexture(GL_TEXTURE0 + unit)
712	}
713}
714
715impl<B, BP> Texture<B, BP>
716where
717	B: BufferVec<BP>,
718	BP: BufferVecItem {
719	/// When to create a new texture, must set up all of the parameters that are needed to be set up due to the specifications of OpenGL
720	fn set_texture_params(
721			glcore: Rc<GLCore>,
722			name: u32,
723			dim: TextureDimension,
724			width: u32,
725			height: &mut u32,
726			depth: &mut u32,
727			size_mod: &mut usize,
728			wrapping_s: TextureWrapping,
729			wrapping_t: TextureWrapping,
730			wrapping_r: TextureWrapping,
731			mag_filter: SamplerMagFilter,
732			min_filter: SamplerFilter,
733		) -> TextureTarget
734	{
735		let target;
736		match dim {
737			TextureDimension::Tex1d => {
738				target = TextureTarget::Tex1d;
739				*height = 1;
740				*depth = 1;
741				*size_mod = 1;
742			}
743			TextureDimension::Tex2d => {
744				target = TextureTarget::Tex2d;
745				*depth = 1;
746				*size_mod = 1;
747			}
748			TextureDimension::Tex3d => {
749				target = TextureTarget::Tex3d;
750				*size_mod = 1;
751			}
752			TextureDimension::TexCube => {
753				target = TextureTarget::TexCube;
754				*height = width;
755				*depth = 1;
756				*size_mod = 6;
757			}
758		}
759		glcore.glBindTexture(target as u32, name);
760		match dim {
761			TextureDimension::Tex1d => {
762				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_S, wrapping_s as i32);
763			}
764			TextureDimension::Tex2d => {
765				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_S, wrapping_s as i32);
766				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_T, wrapping_t as i32);
767			}
768			TextureDimension::Tex3d => {
769				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_S, wrapping_s as i32);
770				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_T, wrapping_t as i32);
771				glcore.glTexParameteri(target as u32, GL_TEXTURE_WRAP_R, wrapping_r as i32);
772			}
773			_ => {}
774		}
775		glcore.glTexParameteri(target as u32, GL_TEXTURE_MAG_FILTER, mag_filter as i32);
776		glcore.glTexParameteri(target as u32, GL_TEXTURE_MIN_FILTER, min_filter as i32);
777		target
778	}
779
780	/// Create an unallocated texture for further initialization
781	fn new_unallocates(
782			glcore: Rc<GLCore>,
783			dim: TextureDimension,
784			format: TextureFormat,
785			width: u32,
786			mut height: u32,
787			mut depth: u32,
788			wrapping_s: TextureWrapping,
789			wrapping_t: TextureWrapping,
790			wrapping_r: TextureWrapping,
791			has_mipmap: bool,
792			mag_filter: SamplerMagFilter,
793			min_filter: SamplerFilter,
794		) -> Self {
795		let mut name: u32 = 0;
796		glcore.glGenTextures(1, &mut name as *mut _);
797		let mut size_mod = 1;
798		let target = Self::set_texture_params(glcore.clone(), name, dim, width, &mut height, &mut depth, &mut size_mod, wrapping_s, wrapping_t, wrapping_r, mag_filter, min_filter);
799		let pixel_bits = format.bits_of_pixel(glcore.as_ref(), target);
800		let pitch = ((pixel_bits - 1) / 32 + 1) * 4;
801		let bytes_of_face = pitch * height as usize * depth as usize;
802		let bytes_of_texture = bytes_of_face * size_mod;
803		Self {
804			glcore,
805			name,
806			dim,
807			format,
808			width,
809			height,
810			depth,
811			has_mipmap,
812			mag_filter,
813			min_filter,
814			bytes_of_texture,
815			bytes_of_face,
816			pixel_buffer: None,
817			_pixel_type: PhantomData,
818		}
819	}
820
821	/// Create from a pixel buffer
822	fn new_from_pixel_buffer(
823			glcore: Rc<GLCore>,
824			dim: TextureDimension,
825			format: TextureFormat,
826			width: u32,
827			height: u32,
828			depth: u32,
829			wrapping_s: TextureWrapping,
830			wrapping_t: TextureWrapping,
831			wrapping_r: TextureWrapping,
832			has_mipmap: bool,
833			mag_filter: SamplerMagFilter,
834			min_filter: SamplerFilter,
835			pixel_buffer: PixelBuffer<B, BP>,
836		) -> Self {
837		let ret = Self::new_unallocates(glcore, dim, format, width, height, depth, wrapping_s, wrapping_t, wrapping_r, has_mipmap, mag_filter, min_filter);
838		unsafe {ret.upload_texture(null(), pixel_buffer.get_channel_type(), pixel_buffer.get_component_type(), has_mipmap)};
839		ret
840	}
841
842	/// Create without pixel buffer
843	fn new(glcore: Rc<GLCore>,
844			dim: TextureDimension,
845			format: TextureFormat,
846			width: u32,
847			height: u32,
848			depth: u32,
849			wrapping_s: TextureWrapping,
850			wrapping_t: TextureWrapping,
851			wrapping_r: TextureWrapping,
852			has_mipmap: bool,
853			mag_filter: SamplerMagFilter,
854			min_filter: SamplerFilter,
855			buffering: bool,
856			buffer_channel_type: ChannelType,
857			buffer_component_type: ComponentType,
858			initial_data: Option<*const c_void>,
859		) -> Self {
860		let mut ret = Self::new_unallocates(glcore, dim, format, width, height, depth, wrapping_s, wrapping_t, wrapping_r, has_mipmap, mag_filter, min_filter);
861		if buffering {
862			ret.create_pixel_buffer(buffer_channel_type, buffer_component_type, initial_data);
863		} else {
864			if let Some(data_pointer) = initial_data {
865				unsafe {ret.upload_texture(data_pointer, buffer_channel_type, buffer_component_type, has_mipmap)};
866			} else {
867				let empty_data = vec![0u8; ret.bytes_of_texture];
868				unsafe {ret.upload_texture(empty_data.as_ptr() as *const c_void, buffer_channel_type, buffer_component_type, has_mipmap)};
869			}
870		}
871		ret
872	}
873
874	/// Create an 1D texture
875	pub fn new_1d(
876	        glcore: Rc<GLCore>,
877	        format: TextureFormat,
878	        width: u32,
879	        wrapping_s: TextureWrapping,
880	        has_mipmap: bool,
881	        mag_filter: SamplerMagFilter,
882			min_filter: SamplerFilter,
883			buffering: bool,
884			buffer_channel_type: ChannelType,
885			buffer_component_type: ComponentType,
886			initial_data: Option<*const c_void>,
887		) -> Self {
888		Self::new(glcore, TextureDimension::Tex1d, format, width, 1, 1, wrapping_s, TextureWrapping::Repeat, TextureWrapping::Repeat, has_mipmap, mag_filter, min_filter, buffering, buffer_channel_type, buffer_component_type, initial_data)
889	}
890
891	/// Create an 2D texture
892	pub fn new_2d(
893	        glcore: Rc<GLCore>,
894	        format: TextureFormat,
895	        width: u32,
896	        height: u32,
897	        wrapping_s: TextureWrapping,
898	        wrapping_t: TextureWrapping,
899	        has_mipmap: bool,
900	        mag_filter: SamplerMagFilter,
901			min_filter: SamplerFilter,
902			buffering: bool,
903			buffer_channel_type: ChannelType,
904			buffer_component_type: ComponentType,
905			initial_data: Option<*const c_void>,
906		) -> Self {
907		Self::new(glcore, TextureDimension::Tex2d, format, width, height, 1, wrapping_s, wrapping_t, TextureWrapping::Repeat, has_mipmap, mag_filter, min_filter, buffering, buffer_channel_type, buffer_component_type, initial_data)
908	}
909
910	/// Create an 3D texture
911	pub fn new_3d(
912	        glcore: Rc<GLCore>,
913	        format: TextureFormat,
914	        width: u32,
915	        height: u32,
916	        depth: u32,
917	        wrapping_s: TextureWrapping,
918	        wrapping_t: TextureWrapping,
919	        wrapping_r: TextureWrapping,
920	        has_mipmap: bool,
921	        mag_filter: SamplerMagFilter,
922			min_filter: SamplerFilter,
923			buffering: bool,
924			buffer_channel_type: ChannelType,
925			buffer_component_type: ComponentType,
926			initial_data: Option<*const c_void>,
927		) -> Self {
928		Self::new(glcore, TextureDimension::Tex3d, format, width, height, depth, wrapping_s, wrapping_t, wrapping_r, has_mipmap, mag_filter, min_filter, buffering, buffer_channel_type, buffer_component_type, initial_data)
929	}
930
931	/// Create an cube map texture
932	pub fn new_cube(
933	        glcore: Rc<GLCore>,
934	        format: TextureFormat,
935	        size: u32,
936	        has_mipmap: bool,
937	        mag_filter: SamplerMagFilter,
938			min_filter: SamplerFilter,
939			buffering: bool,
940			buffer_channel_type: ChannelType,
941			buffer_component_type: ComponentType,
942			initial_data: Option<*const c_void>,
943		) -> Self {
944		Self::new(glcore, TextureDimension::TexCube, format, size, size, 1, TextureWrapping::ClampToEdge, TextureWrapping::ClampToEdge, TextureWrapping::ClampToEdge, has_mipmap, mag_filter, min_filter, buffering, buffer_channel_type, buffer_component_type, initial_data)
945	}
946
947	/// Create a texture from an image
948	pub fn from_image<P: Pixel>(
949			glcore: Rc<GLCore>,
950			dim: TextureDimension,
951			img: &ImageBuffer<P, Vec<P::Subpixel>>,
952			wrapping_s: TextureWrapping,
953			wrapping_t: TextureWrapping,
954			has_mipmap: bool,
955			mag_filter: SamplerMagFilter,
956			min_filter: SamplerFilter,
957		) -> Self {
958		let mut buffer_channel_type = ChannelType::Rgb;
959		let mut buffer_component_type = ComponentType::U8;
960		get_channel_type_and_component_type_from_image_pixel::<P>(&mut buffer_channel_type, &mut buffer_component_type).unwrap();
961		let format = TextureFormat::from_channel_type_and_component_type(buffer_channel_type, buffer_component_type).unwrap();
962		let pixel_buffer = PixelBuffer::from_image(glcore.clone(), img);
963		match dim {
964			TextureDimension::Tex1d => {
965				assert_eq!(img.height(), 1);
966				Self::new_from_pixel_buffer(glcore, dim, format, img.width(), 1, 1, wrapping_s, wrapping_t, TextureWrapping::Repeat, has_mipmap, mag_filter, min_filter, pixel_buffer)
967			}
968			TextureDimension::Tex2d => {
969				Self::new_from_pixel_buffer(glcore, dim, format, img.width(), img.height(), 1, wrapping_s, wrapping_t, TextureWrapping::Repeat, has_mipmap, mag_filter, min_filter, pixel_buffer)
970			}
971			TextureDimension::TexCube => {
972				assert_eq!(img.width() * 6, img.height());
973				Self::new_from_pixel_buffer(glcore, dim, format, img.width(), img.width(), 1, TextureWrapping::ClampToEdge, TextureWrapping::ClampToEdge, TextureWrapping::ClampToEdge, has_mipmap, mag_filter, min_filter, pixel_buffer)
974			}
975			other => panic!("Could not create a {other:?} texture from a `ImageBuffer`")
976		}
977	}
978
979	/// Create a texture from a file
980	pub fn from_file(
981			glcore: Rc<GLCore>,
982			path: &Path,
983			dim: TextureDimension,
984			wrapping_s: TextureWrapping,
985			wrapping_t: TextureWrapping,
986			has_mipmap: bool,
987			mag_filter: SamplerMagFilter,
988			min_filter: SamplerFilter,
989		) -> Result<Self, LoadImageError> {
990		let ext = path.extension().map_or_else(|| String::new(), |ext| OsStr::to_str(ext).unwrap().to_lowercase());
991		match &ext[..] {
992			"jpg" | "jpeg" => {
993				let image_data = std::fs::read(path)?;
994				let img: RgbImage = turbojpeg::decompress_image(&image_data)?;
995				Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter))
996			}
997			_ => {
998				match ImageReader::open(path)?.decode()? {
999					DynamicImage::ImageLuma8(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1000					DynamicImage::ImageLumaA8(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1001					DynamicImage::ImageRgb8(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1002					DynamicImage::ImageRgba8(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1003					DynamicImage::ImageLuma16(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1004					DynamicImage::ImageLumaA16(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1005					DynamicImage::ImageRgb16(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1006					DynamicImage::ImageRgba16(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1007					DynamicImage::ImageRgb32F(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1008					DynamicImage::ImageRgba32F(img) => Ok(Self::from_image(glcore, dim, &img, wrapping_s, wrapping_t, has_mipmap, mag_filter, min_filter)),
1009					_ => Err(LoadImageError::UnsupportedImageType(format!("Unsupported image type when loading texture from {path:?}"))),
1010				}
1011			}
1012		}
1013	}
1014}
1015
1016impl<B, BP> GenericTexture for Texture<B, BP>
1017where
1018	B: BufferVec<BP>,
1019	BP: BufferVecItem {
1020	fn get_glcore(&self) -> &GLCore {
1021		&self.glcore
1022	}
1023
1024	fn get_name(&self) -> u32 {
1025		self.name
1026	}
1027
1028	fn get_dim(&self) -> TextureDimension {
1029		self.dim
1030	}
1031
1032	fn get_width(&self) -> u32 {
1033		self.width
1034	}
1035
1036	fn get_height(&self) -> u32 {
1037		self.height
1038	}
1039
1040	fn get_depth(&self) -> u32 {
1041		self.depth
1042	}
1043
1044	fn get_format(&self) -> TextureFormat {
1045		self.format
1046	}
1047
1048	fn get_bytes_of_face(&self) -> usize {
1049		self.bytes_of_face
1050	}
1051
1052	fn get_bytes_of_texture(&self) -> usize {
1053		self.bytes_of_texture
1054	}
1055
1056	fn has_mipmap(&self) -> bool {
1057		self.has_mipmap
1058	}
1059
1060	fn get_pixel_buffer(&self) -> Option<&dyn GenericPixelBuffer> {
1061		if let Some(pixel_buffer) = &self.pixel_buffer {
1062			Some(pixel_buffer)
1063		} else {
1064			None
1065		}
1066	}
1067
1068	fn create_pixel_buffer(&mut self, buffer_channel_type: ChannelType, buffer_component_type: ComponentType, initial_data: Option<*const c_void>) {
1069		self.pixel_buffer = Some(PixelBuffer::new(self.glcore.clone(), self.width, self.height, self.depth, self.bytes_of_texture, buffer_channel_type, buffer_component_type, initial_data))
1070	}
1071
1072	fn drop_pixel_buffer(&mut self) {
1073		self.pixel_buffer = None
1074	}
1075
1076	fn bind<'a>(&'a self) -> TextureBind<'a> {
1077		match self.get_dim() {
1078			TextureDimension::Tex1d => TextureBind::new(self, TextureTarget::Tex1d),
1079			TextureDimension::Tex2d => TextureBind::new(self, TextureTarget::Tex2d),
1080			TextureDimension::Tex3d => TextureBind::new(self, TextureTarget::Tex3d),
1081			TextureDimension::TexCube => panic!("Please use `bind_face()` to bind a cube map."),
1082		}
1083	}
1084
1085	fn bind_face<'a>(&'a self, face: CubeMapFaces) -> TextureBind<'a> {
1086		match self.get_dim() {
1087			TextureDimension::TexCube => {
1088				match face {
1089					CubeMapFaces::TexCubePosX => TextureBind::new(self, TextureTarget::TexCubePosX),
1090					CubeMapFaces::TexCubeNegX => TextureBind::new(self, TextureTarget::TexCubeNegX),
1091					CubeMapFaces::TexCubePosY => TextureBind::new(self, TextureTarget::TexCubePosY),
1092					CubeMapFaces::TexCubeNegY => TextureBind::new(self, TextureTarget::TexCubeNegY),
1093					CubeMapFaces::TexCubePosZ => TextureBind::new(self, TextureTarget::TexCubePosZ),
1094					CubeMapFaces::TexCubeNegZ => TextureBind::new(self, TextureTarget::TexCubeNegZ),
1095				}
1096			}
1097			_ => panic!("Please use `bind()` to bind an non-cube-map texture."),
1098		}
1099	}
1100}
1101
1102impl<B, BP> Drop for Texture<B, BP>
1103where
1104	B: BufferVec<BP>,
1105	BP: BufferVecItem {
1106	fn drop(&mut self) {
1107		self.glcore.glDeleteTextures(1, &self.name as *const u32);
1108	}
1109}
1110
1111impl<'a> TextureBind<'a> {
1112	/// Create a binding state to the texture, utilizing the RAII rules to manage the binding state
1113	fn new(texture: &'a dyn GenericTexture, target: TextureTarget) -> Self {
1114		texture.get_glcore().glBindTexture(target as u32, texture.get_name());
1115		Self {
1116			texture,
1117			target,
1118		}
1119	}
1120
1121	/// Explicitly unbind the texture.
1122	pub fn unbind(self) {}
1123}
1124
1125impl Drop for TextureBind<'_> {
1126	fn drop(&mut self) {
1127		self.texture.get_glcore().glBindTexture(self.target as u32, 0);
1128	}
1129}
1130
1131impl<B, BP> Debug for Texture<B, BP>
1132where
1133	B: BufferVec<BP>,
1134	BP: BufferVecItem {
1135	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1136		f.debug_struct("Texture")
1137		.field("name", &self.name)
1138		.field("dim", &self.dim)
1139		.field("format", &self.format)
1140		.field("width", &self.width)
1141		.field("height", &self.height)
1142		.field("depth", &self.depth)
1143		.field("has_mipmap", &self.has_mipmap)
1144		.field("pixel_buffer", &self.pixel_buffer)
1145		.finish()
1146	}
1147}
1148
1149impl Debug for TextureDimension {
1150	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1151		match self {
1152			Self::Tex1d => write!(f, "1D"),
1153			Self::Tex2d => write!(f, "2D"),
1154			Self::Tex3d => write!(f, "3D"),
1155			Self::TexCube => write!(f, "CubeMap"),
1156		}
1157	}
1158}
1159
1160impl Debug for TextureFormat {
1161	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1162		match self {
1163			Self::Depth => write!(f, "DEPTH"),
1164			Self::DepthStencil => write!(f, "DEPTH_STENCIL"),
1165			Self::Red => write!(f, "RED"),
1166			Self::Rg => write!(f, "RG"),
1167			Self::Rgb => write!(f, "RGB"),
1168			Self::Rgba => write!(f, "RGBA"),
1169			Self::Red8 => write!(f, "R8"),
1170			Self::Red8Snorm => write!(f, "R8_SNORM"),
1171			Self::Red16 => write!(f, "R16"),
1172			Self::Red16Snorm => write!(f, "R16_SNORM"),
1173			Self::Rg8 => write!(f, "RG8"),
1174			Self::Rg8Snorm => write!(f, "RG8_SNORM"),
1175			Self::Rg16 => write!(f, "RG16"),
1176			Self::Rg16Snorm => write!(f, "RG16_SNORM"),
1177			Self::R3g3b2 => write!(f, "R3_G3_B2"),
1178			Self::Rgb4 => write!(f, "RGB4"),
1179			Self::Rgb5 => write!(f, "RGB5"),
1180			Self::Rgb8 => write!(f, "RGB8"),
1181			Self::Rgb8Snorm => write!(f, "RGB8_SNORM"),
1182			Self::Rgb10 => write!(f, "RGB10"),
1183			Self::Rgb12 => write!(f, "RGB12"),
1184			Self::Rgb16Snorm => write!(f, "RGB16_SNORM"),
1185			Self::Rgba2 => write!(f, "RGBA2"),
1186			Self::Rgba4 => write!(f, "RGBA4"),
1187			Self::Rgb5a1 => write!(f, "RGB5_A1"),
1188			Self::Rgba8 => write!(f, "RGBA8"),
1189			Self::Rgba8Snorm => write!(f, "RGBA8_SNORM"),
1190			Self::Rgb10a2 => write!(f, "RGB10_A2"),
1191			Self::Rgb10a2ui => write!(f, "RGB10_A2UI"),
1192			Self::Rgba12 => write!(f, "RGBA12"),
1193			Self::Rgba16 => write!(f, "RGBA16"),
1194			Self::R32f => write!(f, "R32F"),
1195			Self::Rg32f => write!(f, "RG32F"),
1196			Self::Rgb32f => write!(f, "RGB32F"),
1197			Self::Rgba32f => write!(f, "RGBA32F"),
1198			Self::R11fg11fb10f => write!(f, "R11F_G11F_B10F"),
1199			Self::Rgb9e5 => write!(f, "RGB9_E5"),
1200			Self::R8i => write!(f, "R8I"),
1201			Self::R8ui => write!(f, "R8UI"),
1202			Self::R16i => write!(f, "R16I"),
1203			Self::R16ui => write!(f, "R16UI"),
1204			Self::R32i => write!(f, "R32I"),
1205			Self::R32ui => write!(f, "R32UI"),
1206			Self::Rg8i => write!(f, "RG8I"),
1207			Self::Rg8ui => write!(f, "RG8UI"),
1208			Self::Rg16i => write!(f, "RG16I"),
1209			Self::Rg16ui => write!(f, "RG16UI"),
1210			Self::Rg32i => write!(f, "RG32I"),
1211			Self::Rg32ui => write!(f, "RG32UI"),
1212			Self::Rgb8i => write!(f, "RGB8I"),
1213			Self::Rgb8ui => write!(f, "RGB8UI"),
1214			Self::Rgb16i => write!(f, "RGB16I"),
1215			Self::Rgb16ui => write!(f, "RGB16UI"),
1216			Self::Rgb32i => write!(f, "RGB32I"),
1217			Self::Rgb32ui => write!(f, "RGB32UI"),
1218			Self::Rgba8i => write!(f, "RGBA8I"),
1219			Self::Rgba8ui => write!(f, "RGBA8UI"),
1220			Self::Rgba16i => write!(f, "RGBA16I"),
1221			Self::Rgba16ui => write!(f, "RGBA16UI"),
1222			Self::Rgba32i => write!(f, "RGBA32I"),
1223			Self::Rgba32ui => write!(f, "RGBA32UI"),
1224		}
1225	}
1226}
1227
1228impl Debug for CubeMapFaces {
1229	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1230		match self {
1231			Self::TexCubePosX => write!(f, "Positive X"),
1232			Self::TexCubeNegX => write!(f, "Negative X"),
1233			Self::TexCubePosY => write!(f, "Positive Y"),
1234			Self::TexCubeNegY => write!(f, "Negative Y"),
1235			Self::TexCubePosZ => write!(f, "Positive Z"),
1236			Self::TexCubeNegZ => write!(f, "Negative Z"),
1237		}
1238	}
1239}
1240
1241impl Debug for ChannelType {
1242	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1243		match self {
1244			Self::Red => write!(f, "RED"),
1245			Self::Rg => write!(f, "RG"),
1246			Self::Rgb => write!(f, "RGB"),
1247			Self::Bgr => write!(f, "BGR"),
1248			Self::Rgba => write!(f, "RGBA"),
1249			Self::Bgra => write!(f, "BGRA"),
1250			Self::RedInteger => write!(f, "RED_INTEGER"),
1251			Self::RgInteger => write!(f, "RG_INTEGER"),
1252			Self::RgbInteger => write!(f, "RGB_INTEGER"),
1253			Self::BgrInteger => write!(f, "BGR_INTEGER"),
1254			Self::RgbaInteger => write!(f, "RGBA_INTEGER"),
1255			Self::BgraInteger => write!(f, "BGRA_INTEGER"),
1256			Self::StencilIndex => write!(f, "STENCIL_INDEX"),
1257			Self::Depth => write!(f, "DEPTH_COMPONENT"),
1258			Self::DepthStencil => write!(f, "DEPTH_STENCIL"),
1259		}
1260	}
1261}
1262
1263impl Debug for ComponentType {
1264	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1265		match self {
1266			Self::U8 => write!(f, "UNSIGNED_BYTE"),
1267			Self::I8 => write!(f, "BYTE"),
1268			Self::U16 => write!(f, "UNSIGNED_SHORT"),
1269			Self::I16 => write!(f, "SHORT"),
1270			Self::U32 => write!(f, "UNSIGNED_INT"),
1271			Self::I32 => write!(f, "INT"),
1272			Self::F16 => write!(f, "HALF_FLOAT"),
1273			Self::F32 => write!(f, "FLOAT"),
1274			Self::U8_332 => write!(f, "UNSIGNED_BYTE_3_3_2"),
1275			Self::U8_233Rev => write!(f, "UNSIGNED_BYTE_2_3_3_REV"),
1276			Self::U16_565 => write!(f, "UNSIGNED_SHORT_5_6_5"),
1277			Self::U16_565Rev => write!(f, "UNSIGNED_SHORT_5_6_5_REV"),
1278			Self::U16_4444 => write!(f, "UNSIGNED_SHORT_4_4_4_4"),
1279			Self::U16_4444Rev => write!(f, "UNSIGNED_SHORT_4_4_4_4_REV"),
1280			Self::U16_5551 => write!(f, "UNSIGNED_SHORT_5_5_5_1"),
1281			Self::U16_1555Rev => write!(f, "UNSIGNED_SHORT_1_5_5_5_REV"),
1282			Self::U32_8888 => write!(f, "UNSIGNED_INT_8_8_8_8"),
1283			Self::U32_8888Rev => write!(f, "UNSIGNED_INT_8_8_8_8_REV"),
1284			Self::U32_10_10_10_2 => write!(f, "UNSIGNED_INT_10_10_10_2"),
1285			Self::U32_2_10_10_10Rev => write!(f, "UNSIGNED_INT_2_10_10_10_REV"),
1286		}
1287	}
1288}