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#[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#[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#[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
52pub 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#[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#[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 Repeat = GL_REPEAT as isize,
137
138 MirroredRepeat = GL_MIRRORED_REPEAT as isize,
140}
141
142#[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#[derive(Clone, Copy, PartialEq)]
155pub enum SamplerMagFilter {
156 Nearest = GL_NEAREST as isize,
157 Linear = GL_LINEAR as isize,
158}
159
160#[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#[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
205pub 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
248pub trait PixelType: BufferVecItem {}
250impl<T> PixelType for T where T: BufferVecItem {}
251
252#[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
270pub 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
291pub struct TextureBind<'a> {
293 pub texture: &'a dyn GenericTexture,
294 target: TextureTarget,
295}
296
297#[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 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 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 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
416pub 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
442pub trait GenericPixelBuffer: Debug {
444 fn get_buffer(&self) -> &Buffer;
446
447 fn get_channel_type(&self) -> ChannelType;
449
450 fn get_component_type(&self) -> ComponentType;
452
453 fn size_in_bytes(&self) -> usize {
455 self.get_buffer().size()
456 }
457
458 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 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 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 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
557pub trait GenericTexture: Debug {
559 fn get_glcore(&self) -> &GLCore;
561
562 fn get_name(&self) -> u32;
564
565 fn get_dim(&self) -> TextureDimension;
567
568 fn get_width(&self) -> u32;
570
571 fn get_height(&self) -> u32;
573
574 fn get_depth(&self) -> u32;
576
577 fn get_format(&self) -> TextureFormat;
579
580 fn get_bytes_of_face(&self) -> usize;
582
583 fn get_bytes_of_texture(&self) -> usize;
585
586 fn has_mipmap(&self) -> bool;
588
589 fn get_pixel_buffer(&self) -> Option<&dyn GenericPixelBuffer>;
591
592 fn create_pixel_buffer(&mut self, buffer_channel_type: ChannelType, buffer_component_type: ComponentType, initial_data: Option<*const c_void>);
594
595 fn drop_pixel_buffer(&mut self);
597
598 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 fn bind<'a>(&'a self) -> TextureBind<'a>;
609
610 fn bind_face<'a>(&'a self, face: CubeMapFaces) -> TextureBind<'a>;
612
613 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}