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