1use std::fmt;
6use std::error::Error;
7
8use crate::gl;
9use crate::context::Context;
10
11use crate::CapabilitiesSource;
12use crate::ToGlEnum;
13use crate::version::{Api, Version};
14
15#[derive(Copy, Clone, Debug)]
17pub struct FormatNotSupportedError;
18
19impl fmt::Display for FormatNotSupportedError {
20 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
21 write!(fmt, "Format is not supported by OpenGL")
22 }
23}
24
25impl Error for FormatNotSupportedError {}
26
27#[derive(Copy, Clone, Debug)]
29pub enum TextureFormatRequest {
30 Specific(TextureFormat),
32
33 AnyFloatingPoint,
35
36 AnyCompressed,
42
43 AnySrgb,
45
46 AnyCompressedSrgb,
48
49 AnyIntegral,
51
52 AnyUnsigned,
54
55 AnyDepth,
57
58 AnyStencil,
60
61 AnyDepthStencil,
63}
64
65#[allow(missing_docs)]
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum ClientFormat {
71 U8,
72 U8U8,
73 U8U8U8,
74 U8U8U8U8,
75 I8,
76 I8I8,
77 I8I8I8,
78 I8I8I8I8,
79 U16,
80 U16U16,
81 U16U16U16,
82 U16U16U16U16,
83 I16,
84 I16I16,
85 I16I16I16,
86 I16I16I16I16,
87 U32,
88 U32U32,
89 U32U32U32,
90 U32U32U32U32,
91 I32,
92 I32I32,
93 I32I32I32,
94 I32I32I32I32,
95 U3U3U2,
96 U5U6U5,
97 U4U4U4U4,
98 U5U5U5U1,
99 U1U5U5U5Reversed,
100 U10U10U10U2,
101 F16,
102 F16F16,
103 F16F16F16,
104 F16F16F16F16,
105 F32,
106 F32F32,
107 F32F32F32,
108 F32F32F32F32,
109}
110
111impl ClientFormat {
112 pub fn get_size(&self) -> usize {
114 use std::mem;
115
116 match *self {
117 ClientFormat::U8 => 1 * mem::size_of::<u8>(),
118 ClientFormat::U8U8 => 2 * mem::size_of::<u8>(),
119 ClientFormat::U8U8U8 => 3 * mem::size_of::<u8>(),
120 ClientFormat::U8U8U8U8 => 4 * mem::size_of::<u8>(),
121 ClientFormat::I8 => 1 * mem::size_of::<i8>(),
122 ClientFormat::I8I8 => 2 * mem::size_of::<i8>(),
123 ClientFormat::I8I8I8 => 3 * mem::size_of::<i8>(),
124 ClientFormat::I8I8I8I8 => 4 * mem::size_of::<i8>(),
125 ClientFormat::U16 => 1 * mem::size_of::<u16>(),
126 ClientFormat::U16U16 => 2 * mem::size_of::<u16>(),
127 ClientFormat::U16U16U16 => 3 * mem::size_of::<u16>(),
128 ClientFormat::U16U16U16U16 => 4 * mem::size_of::<u16>(),
129 ClientFormat::I16 => 1 * mem::size_of::<i16>(),
130 ClientFormat::I16I16 => 2 * mem::size_of::<i16>(),
131 ClientFormat::I16I16I16 => 3 * mem::size_of::<i16>(),
132 ClientFormat::I16I16I16I16 => 4 * mem::size_of::<i16>(),
133 ClientFormat::U32 => 1 * mem::size_of::<u32>(),
134 ClientFormat::U32U32 => 2 * mem::size_of::<u32>(),
135 ClientFormat::U32U32U32 => 3 * mem::size_of::<u32>(),
136 ClientFormat::U32U32U32U32 => 4 * mem::size_of::<u32>(),
137 ClientFormat::I32 => 1 * mem::size_of::<i32>(),
138 ClientFormat::I32I32 => 2 * mem::size_of::<i32>(),
139 ClientFormat::I32I32I32 => 3 * mem::size_of::<i32>(),
140 ClientFormat::I32I32I32I32 => 4 * mem::size_of::<i32>(),
141 ClientFormat::U3U3U2 => (3 + 3 + 2) / 8,
142 ClientFormat::U5U6U5 => (5 + 6 + 5) / 8,
143 ClientFormat::U4U4U4U4 => (4 + 4 + 4 + 4) / 8,
144 ClientFormat::U5U5U5U1 => (5 + 5 + 5 + 1) / 8,
145 ClientFormat::U1U5U5U5Reversed => (1 + 5 + 5 + 5) / 8,
146 ClientFormat::U10U10U10U2 => (10 + 10 + 10 + 2) / 8,
147 ClientFormat::F16 => 16 / 8,
148 ClientFormat::F16F16 => (16 + 16) / 8,
149 ClientFormat::F16F16F16 => (16 + 16 + 16) / 8,
150 ClientFormat::F16F16F16F16 => (16 + 16 + 16 + 16) / 8,
151 ClientFormat::F32 => 1 * mem::size_of::<f32>(),
152 ClientFormat::F32F32 => 2 * mem::size_of::<f32>(),
153 ClientFormat::F32F32F32 => 3 * mem::size_of::<f32>(),
154 ClientFormat::F32F32F32F32 => 4 * mem::size_of::<f32>(),
155 }
156 }
157
158 pub fn get_num_components(&self) -> u8 {
160 match *self {
161 ClientFormat::U8 => 1,
162 ClientFormat::U8U8 => 2,
163 ClientFormat::U8U8U8 => 3,
164 ClientFormat::U8U8U8U8 => 4,
165 ClientFormat::I8 => 1,
166 ClientFormat::I8I8 => 2,
167 ClientFormat::I8I8I8 => 3,
168 ClientFormat::I8I8I8I8 => 4,
169 ClientFormat::U16 => 1,
170 ClientFormat::U16U16 => 2,
171 ClientFormat::U16U16U16 => 3,
172 ClientFormat::U16U16U16U16 => 4,
173 ClientFormat::I16 => 1,
174 ClientFormat::I16I16 => 2,
175 ClientFormat::I16I16I16 => 3,
176 ClientFormat::I16I16I16I16 => 4,
177 ClientFormat::U32 => 1,
178 ClientFormat::U32U32 => 2,
179 ClientFormat::U32U32U32 => 3,
180 ClientFormat::U32U32U32U32 => 4,
181 ClientFormat::I32 => 1,
182 ClientFormat::I32I32 => 2,
183 ClientFormat::I32I32I32 => 3,
184 ClientFormat::I32I32I32I32 => 4,
185 ClientFormat::U3U3U2 => 3,
186 ClientFormat::U5U6U5 => 3,
187 ClientFormat::U4U4U4U4 => 4,
188 ClientFormat::U5U5U5U1 => 4,
189 ClientFormat::U1U5U5U5Reversed => 4,
190 ClientFormat::U10U10U10U2 => 4,
191 ClientFormat::F16 => 1,
192 ClientFormat::F16F16 => 2,
193 ClientFormat::F16F16F16 => 3,
194 ClientFormat::F16F16F16F16 => 4,
195 ClientFormat::F32 => 1,
196 ClientFormat::F32F32 => 2,
197 ClientFormat::F32F32F32 => 3,
198 ClientFormat::F32F32F32F32 => 4,
199 }
200 }
201}
202
203#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
210pub enum UncompressedFloatFormat {
211 U8,
215 I8,
219 U16,
223 I16,
227 U8U8,
231 I8I8,
235 U16U16,
239 I16I16,
243 U3U3U2,
245 U4U4U4,
247 U5U5U5,
249 U8U8U8,
253 I8I8I8,
257 U10U10U10,
259 U12U12U12,
261 U16U16U16,
265 I16I16I16,
269 U2U2U2U2,
271 U4U4U4U4,
273 U5U5U5U1,
275 U8U8U8U8,
279 I8I8I8I8,
283 U10U10U10U2,
287 U12U12U12U12,
289 U16U16U16U16,
293 I16I16I16I16,
297 F16,
301 F16F16,
305 F16F16F16,
309 F16F16F16F16,
313 F32,
317 F32F32,
321 F32F32F32,
325 F32F32F32F32,
329 F11F11F10,
333 F9F9F9,
339}
340
341impl UncompressedFloatFormat {
342 #[inline]
344 pub fn get_formats_list() -> Vec<UncompressedFloatFormat> {
345 vec![
346 UncompressedFloatFormat::U8,
347 UncompressedFloatFormat::I8,
348 UncompressedFloatFormat::U16,
349 UncompressedFloatFormat::I16,
350 UncompressedFloatFormat::U8U8,
351 UncompressedFloatFormat::I8I8,
352 UncompressedFloatFormat::U16U16,
353 UncompressedFloatFormat::I16I16,
354 UncompressedFloatFormat::U3U3U2,
355 UncompressedFloatFormat::U4U4U4,
356 UncompressedFloatFormat::U5U5U5,
357 UncompressedFloatFormat::U8U8U8,
358 UncompressedFloatFormat::I8I8I8,
359 UncompressedFloatFormat::U10U10U10,
360 UncompressedFloatFormat::U12U12U12,
361 UncompressedFloatFormat::U16U16U16,
362 UncompressedFloatFormat::I16I16I16,
363 UncompressedFloatFormat::U2U2U2U2,
364 UncompressedFloatFormat::U4U4U4U4,
365 UncompressedFloatFormat::U5U5U5U1,
366 UncompressedFloatFormat::U8U8U8U8,
367 UncompressedFloatFormat::I8I8I8I8,
368 UncompressedFloatFormat::U10U10U10U2,
369 UncompressedFloatFormat::U12U12U12U12,
370 UncompressedFloatFormat::U16U16U16U16,
371 UncompressedFloatFormat::I16I16I16I16,
372 UncompressedFloatFormat::F16,
373 UncompressedFloatFormat::F16F16,
374 UncompressedFloatFormat::F16F16F16,
375 UncompressedFloatFormat::F16F16F16F16,
376 UncompressedFloatFormat::F32,
377 UncompressedFloatFormat::F32F32,
378 UncompressedFloatFormat::F32F32F32,
379 UncompressedFloatFormat::F32F32F32F32,
380 UncompressedFloatFormat::F11F11F10,
381 UncompressedFloatFormat::F9F9F9,
382 ]
383 }
384
385 #[inline]
387 pub fn to_texture_format(self) -> TextureFormat {
388 TextureFormat::UncompressedFloat(self)
389 }
390
391 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
393 let version = context.get_version();
394 let extensions = context.get_extensions();
395
396 match self {
397 UncompressedFloatFormat::U8 => {
398 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
399 extensions.gl_arb_texture_rg
400 },
401 UncompressedFloatFormat::I8 => {
402 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
403 extensions.gl_ext_texture_snorm
404 },
405 UncompressedFloatFormat::U16 => {
406 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
407 extensions.gl_arb_texture_rg
408 },
409 UncompressedFloatFormat::I16 => {
410 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
411 extensions.gl_ext_texture_snorm
412 },
413 UncompressedFloatFormat::U8U8 => {
414 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
415 extensions.gl_arb_texture_rg
416 },
417 UncompressedFloatFormat::I8I8 => {
418 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
419 extensions.gl_ext_texture_snorm
420 },
421 UncompressedFloatFormat::U16U16 => {
422 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
423 extensions.gl_arb_texture_rg
424 },
425 UncompressedFloatFormat::I16I16 => {
426 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
427 extensions.gl_ext_texture_snorm
428 },
429 UncompressedFloatFormat::U3U3U2 => {
430 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
431 },
432 UncompressedFloatFormat::U4U4U4 => {
433 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
434 },
435 UncompressedFloatFormat::U5U5U5 => {
436 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
437 },
438 UncompressedFloatFormat::U8U8U8 => {
439 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
440 },
441 UncompressedFloatFormat::I8I8I8 => {
442 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
443 extensions.gl_ext_texture_snorm
444 },
445 UncompressedFloatFormat::U10U10U10 => {
446 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
447 },
448 UncompressedFloatFormat::U12U12U12 => {
449 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
450 },
451 UncompressedFloatFormat::U16U16U16 => {
452 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0)
453 },
454 UncompressedFloatFormat::I16I16I16 => {
455 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
456 extensions.gl_ext_texture_snorm
457 },
458 UncompressedFloatFormat::U2U2U2U2 => {
459 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
460 },
461 UncompressedFloatFormat::U4U4U4U4 => {
462 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
463 },
464 UncompressedFloatFormat::U5U5U5U1 => {
465 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
466 },
467 UncompressedFloatFormat::U8U8U8U8 => {
468 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
469 },
470 UncompressedFloatFormat::I8I8I8I8 => {
471 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
472 extensions.gl_ext_texture_snorm
473 },
474 UncompressedFloatFormat::U10U10U10U2 => {
475 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
476 },
477 UncompressedFloatFormat::U12U12U12U12 => {
478 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
479 },
480 UncompressedFloatFormat::U16U16U16U16 => {
481 version >= &Version(Api::Gl, 1, 1) || version >= &Version(Api::GlEs, 3, 0)
482 },
483 UncompressedFloatFormat::I16I16I16I16 => {
484 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
485 extensions.gl_ext_texture_snorm
486 },
487 UncompressedFloatFormat::F16 => {
488 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
489 (extensions.gl_arb_texture_float && extensions.gl_arb_texture_rg)
490 },
491 UncompressedFloatFormat::F16F16 => {
492 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
493 (extensions.gl_arb_texture_float && extensions.gl_arb_texture_rg)
494 },
495 UncompressedFloatFormat::F16F16F16 => {
496 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
497 extensions.gl_arb_texture_float || extensions.gl_ati_texture_float
498 },
499 UncompressedFloatFormat::F16F16F16F16 => {
500 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
501 extensions.gl_arb_texture_float || extensions.gl_ati_texture_float
502 },
503 UncompressedFloatFormat::F32 => {
504 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
505 (extensions.gl_arb_texture_float && extensions.gl_arb_texture_rg)
506 },
507 UncompressedFloatFormat::F32F32 => {
508 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
509 (extensions.gl_arb_texture_float && extensions.gl_arb_texture_rg)
510 },
511 UncompressedFloatFormat::F32F32F32 => {
512 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
513 extensions.gl_arb_texture_float || extensions.gl_ati_texture_float
514 },
515 UncompressedFloatFormat::F32F32F32F32 => {
516 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
517 extensions.gl_arb_texture_float || extensions.gl_ati_texture_float
518 },
519 UncompressedFloatFormat::F11F11F10 => {
520 version >= &Version(Api::Gl, 3, 2) || version >= &Version(Api::GlEs, 3, 0) ||
521 extensions.gl_ext_packed_float
522 },
523 UncompressedFloatFormat::F9F9F9 => {
524 version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) ||
525 extensions.gl_ext_texture_shared_exponent
526 },
527 }
528 }
529
530 pub fn is_color_renderable<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
533 if matches!(self, UncompressedFloatFormat::F9F9F9) {
535 return false;
536 }
537
538 if !self.is_supported(context) {
540 return false;
541 }
542
543 let version = context.get_version();
544 let extensions = context.get_extensions();
545
546 if version >= &Version(Api::Gl, 1, 0) {
548 return true;
549 }
550
551 match self {
554 UncompressedFloatFormat::U8 => {
555 version >= &Version(Api::GlEs, 3, 0) || extensions.gl_arb_texture_rg
556 },
557 UncompressedFloatFormat::U8U8 => {
558 version >= &Version(Api::GlEs, 3, 0) || extensions.gl_arb_texture_rg
559 },
560 UncompressedFloatFormat::U8U8U8 => {
562 version >= &Version(Api::GlEs, 3, 0) || extensions.gl_oes_rgb8_rgba8
563 },
564 UncompressedFloatFormat::U4U4U4U4 => true,
565 UncompressedFloatFormat::U5U5U5U1 => true,
566 UncompressedFloatFormat::U8U8U8U8 => {
567 version >= &Version(Api::GlEs, 3, 0) || extensions.gl_arm_rgba8 ||
568 extensions.gl_oes_rgb8_rgba8
569 },
570 UncompressedFloatFormat::U10U10U10U2 => version >= &Version(Api::GlEs, 3, 0),
571 UncompressedFloatFormat::F16 => version >= &Version(Api::GlEs, 3, 2),
572 UncompressedFloatFormat::F16F16 => version >= &Version(Api::GlEs, 3, 2),
573 UncompressedFloatFormat::F16F16F16F16 => version >= &Version(Api::GlEs, 3, 2),
574 UncompressedFloatFormat::F32 => version >= &Version(Api::GlEs, 3, 2),
575 UncompressedFloatFormat::F32F32 => version >= &Version(Api::GlEs, 3, 2),
576 UncompressedFloatFormat::F32F32F32F32 => version >= &Version(Api::GlEs, 3, 2),
577 UncompressedFloatFormat::F11F11F10 => version >= &Version(Api::GlEs, 3, 2),
578 _ => false
579 }
580 }
581
582 fn to_glenum(&self) -> gl::types::GLenum {
583 match self {
584 UncompressedFloatFormat::U8 => gl::R8,
585 UncompressedFloatFormat::I8 => gl::R8_SNORM,
586 UncompressedFloatFormat::U16 => gl::R16,
587 UncompressedFloatFormat::I16 => gl::R16_SNORM,
588 UncompressedFloatFormat::U8U8 => gl::RG8,
589 UncompressedFloatFormat::I8I8 => gl::RG8_SNORM,
590 UncompressedFloatFormat::U16U16 => gl::RG16,
591 UncompressedFloatFormat::I16I16 => gl::RG16_SNORM,
592 UncompressedFloatFormat::U3U3U2 => gl::R3_G3_B2,
593 UncompressedFloatFormat::U4U4U4 => gl::RGB4,
594 UncompressedFloatFormat::U5U5U5 => gl::RGB5,
595 UncompressedFloatFormat::U8U8U8 => gl::RGB8,
596 UncompressedFloatFormat::I8I8I8 => gl::RGB8_SNORM,
597 UncompressedFloatFormat::U10U10U10 => gl::RGB10,
598 UncompressedFloatFormat::U12U12U12 => gl::RGB12,
599 UncompressedFloatFormat::U16U16U16 => gl::RGB16,
600 UncompressedFloatFormat::I16I16I16 => gl::RGB16_SNORM,
601 UncompressedFloatFormat::U2U2U2U2 => gl::RGBA2,
602 UncompressedFloatFormat::U4U4U4U4 => gl::RGBA4,
603 UncompressedFloatFormat::U5U5U5U1 => gl::RGB5_A1,
604 UncompressedFloatFormat::U8U8U8U8 => gl::RGBA8,
605 UncompressedFloatFormat::I8I8I8I8 => gl::RGBA8_SNORM,
606 UncompressedFloatFormat::U10U10U10U2 => gl::RGB10_A2,
607 UncompressedFloatFormat::U12U12U12U12 => gl::RGBA12,
608 UncompressedFloatFormat::U16U16U16U16 => gl::RGBA16,
609 UncompressedFloatFormat::I16I16I16I16 => gl::RGBA16_SNORM,
610 UncompressedFloatFormat::F16 => gl::R16F,
611 UncompressedFloatFormat::F16F16 => gl::RG16F,
612 UncompressedFloatFormat::F16F16F16 => gl::RGB16F,
613 UncompressedFloatFormat::F16F16F16F16 => gl::RGBA16F,
614 UncompressedFloatFormat::F32 => gl::R32F,
615 UncompressedFloatFormat::F32F32 => gl::RG32F,
616 UncompressedFloatFormat::F32F32F32 => gl::RGB32F,
617 UncompressedFloatFormat::F32F32F32F32 => gl::RGBA32F,
618 UncompressedFloatFormat::F11F11F10 => gl::R11F_G11F_B10F,
619 UncompressedFloatFormat::F9F9F9 => gl::RGB9_E5,
620 }
621 }
622}
623
624#[allow(missing_docs)]
626#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
627pub enum SrgbFormat {
628 U8U8U8,
629 U8U8U8U8,
630}
631
632impl SrgbFormat {
633 #[inline]
635 pub fn get_formats_list() -> Vec<SrgbFormat> {
636 vec![
637 SrgbFormat::U8U8U8,
638 SrgbFormat::U8U8U8U8,
639 ]
640 }
641
642 #[inline]
644 pub fn to_texture_format(self) -> TextureFormat {
645 TextureFormat::Srgb(self)
646 }
647
648 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
650 let version = context.get_version();
651 let extensions = context.get_extensions();
652
653 match self {
654 SrgbFormat::U8U8U8 => {
655 version >= &Version(Api::Gl, 2, 1) || version >= &Version(Api::GlEs, 3, 0) ||
656 extensions.gl_ext_texture_srgb
657 },
658
659 SrgbFormat::U8U8U8U8 => {
660 version >= &Version(Api::Gl, 2, 1) || version >= &Version(Api::GlEs, 3, 0) ||
661 extensions.gl_ext_texture_srgb
662 },
663 }
664 }
665
666 pub fn is_color_renderable<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
669 if !self.is_supported(context) {
671 return false;
672 }
673
674 let version = context.get_version();
675 let extensions = context.get_extensions();
676
677 match self {
678 SrgbFormat::U8U8U8 => version >= &Version(Api::Gl, 1, 0),
679 SrgbFormat::U8U8U8U8 => version >= &Version(Api::Gl, 1, 0) ||
680 version >= &Version(Api::GlEs, 3, 0),
681 }
682 }
683
684 fn to_glenum(&self) -> gl::types::GLenum {
685 match self {
686 SrgbFormat::U8U8U8 => gl::SRGB8,
687 SrgbFormat::U8U8U8U8 => gl::SRGB8_ALPHA8,
688 }
689 }
690}
691
692#[allow(missing_docs)]
694#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
695pub enum UncompressedIntFormat {
696 I8,
697 I16,
698 I32,
699 I8I8,
700 I16I16,
701 I32I32,
702 I8I8I8,
703 I16I16I16,
705 I32I32I32,
707 I8I8I8I8,
709 I16I16I16I16,
710 I32I32I32I32,
711}
712
713impl UncompressedIntFormat {
714 #[inline]
716 pub fn get_formats_list() -> Vec<UncompressedIntFormat> {
717 vec![
718 UncompressedIntFormat::I8,
719 UncompressedIntFormat::I16,
720 UncompressedIntFormat::I32,
721 UncompressedIntFormat::I8I8,
722 UncompressedIntFormat::I16I16,
723 UncompressedIntFormat::I32I32,
724 UncompressedIntFormat::I8I8I8,
725 UncompressedIntFormat::I16I16I16,
726 UncompressedIntFormat::I32I32I32,
727 UncompressedIntFormat::I8I8I8I8,
728 UncompressedIntFormat::I16I16I16I16,
729 UncompressedIntFormat::I32I32I32I32,
730 ]
731 }
732
733 #[inline]
735 pub fn to_texture_format(self) -> TextureFormat {
736 TextureFormat::UncompressedIntegral(self)
737 }
738
739 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
741 let version = context.get_version();
742 let extensions = context.get_extensions();
743
744 match self {
745 UncompressedIntFormat::I8 => {
746 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
747 extensions.gl_arb_texture_rg)
748 },
749
750 UncompressedIntFormat::I16 => {
751 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
752 extensions.gl_arb_texture_rg)
753 },
754
755 UncompressedIntFormat::I32 => {
756 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
757 extensions.gl_arb_texture_rg)
758 },
759
760 UncompressedIntFormat::I8I8 => {
761 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
762 extensions.gl_arb_texture_rg)
763 },
764
765 UncompressedIntFormat::I16I16 => {
766 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
767 extensions.gl_arb_texture_rg)
768 },
769
770 UncompressedIntFormat::I32I32 => {
771 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
772 extensions.gl_arb_texture_rg)
773 },
774
775 UncompressedIntFormat::I8I8I8 => {
776 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
777 },
778
779 UncompressedIntFormat::I16I16I16 => {
780 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
781 },
782
783 UncompressedIntFormat::I32I32I32 => {
784 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
785 },
786
787 UncompressedIntFormat::I8I8I8I8 => {
788 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
789 },
790
791 UncompressedIntFormat::I16I16I16I16 => {
792 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
793 },
794
795 UncompressedIntFormat::I32I32I32I32 => {
796 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
797 },
798 }
799 }
800
801 pub fn is_color_renderable<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
804 if !self.is_supported(context) {
806 return false;
807 }
808
809 let version = context.get_version();
810
811 if version >= &Version(Api::Gl, 1, 0) {
813 return true;
814 }
815
816 match self {
818 UncompressedIntFormat::I8 => version >= &Version(Api::GlEs, 3, 0),
819 UncompressedIntFormat::I16 => version >= &Version(Api::GlEs, 3, 0),
820 UncompressedIntFormat::I32 => version >= &Version(Api::GlEs, 3, 0),
821 UncompressedIntFormat::I8I8 => version >= &Version(Api::GlEs, 3, 0),
822 UncompressedIntFormat::I16I16 => version >= &Version(Api::GlEs, 3, 0),
823 UncompressedIntFormat::I32I32 => version >= &Version(Api::GlEs, 3, 0),
824 UncompressedIntFormat::I8I8I8 => false,
825 UncompressedIntFormat::I16I16I16 => false,
826 UncompressedIntFormat::I32I32I32 => false,
827 UncompressedIntFormat::I8I8I8I8 => version >= &Version(Api::GlEs, 3, 0),
828 UncompressedIntFormat::I16I16I16I16 => version >= &Version(Api::GlEs, 3, 0),
829 UncompressedIntFormat::I32I32I32I32 => version >= &Version(Api::GlEs, 3, 0),
830 }
831 }
832
833 fn to_glenum(&self) -> gl::types::GLenum {
834 match self {
835 UncompressedIntFormat::I8 => gl::R8I,
836 UncompressedIntFormat::I16 => gl::R16I,
837 UncompressedIntFormat::I32 => gl::R32I,
838 UncompressedIntFormat::I8I8 => gl::RG8I,
839 UncompressedIntFormat::I16I16 => gl::RG16I,
840 UncompressedIntFormat::I32I32 => gl::RG32I,
841 UncompressedIntFormat::I8I8I8 => gl::RGB8I,
842 UncompressedIntFormat::I16I16I16 => gl::RGB16I,
843 UncompressedIntFormat::I32I32I32 => gl::RGB32I,
844 UncompressedIntFormat::I8I8I8I8 => gl::RGBA8I,
845 UncompressedIntFormat::I16I16I16I16 => gl::RGBA16I,
846 UncompressedIntFormat::I32I32I32I32 => gl::RGBA32I,
847 }
848 }
849}
850
851#[allow(missing_docs)]
853#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
854pub enum UncompressedUintFormat {
855 U8,
856 U16,
857 U32,
858 U8U8,
859 U16U16,
860 U32U32,
861 U8U8U8,
862 U16U16U16,
864 U32U32U32,
866 U8U8U8U8,
868 U16U16U16U16,
869 U32U32U32U32,
870 U10U10U10U2,
871}
872
873impl UncompressedUintFormat {
874 #[inline]
876 pub fn get_formats_list() -> Vec<UncompressedUintFormat> {
877 vec![
878 UncompressedUintFormat::U8,
879 UncompressedUintFormat::U16,
880 UncompressedUintFormat::U32,
881 UncompressedUintFormat::U8U8,
882 UncompressedUintFormat::U16U16,
883 UncompressedUintFormat::U32U32,
884 UncompressedUintFormat::U8U8U8,
885 UncompressedUintFormat::U16U16U16,
886 UncompressedUintFormat::U32U32U32,
887 UncompressedUintFormat::U8U8U8U8,
888 UncompressedUintFormat::U16U16U16U16,
889 UncompressedUintFormat::U32U32U32U32,
890 UncompressedUintFormat::U10U10U10U2,
891 ]
892 }
893
894 #[inline]
896 pub fn to_texture_format(self) -> TextureFormat {
897 TextureFormat::UncompressedUnsigned(self)
898 }
899
900 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
902 let version = context.get_version();
903 let extensions = context.get_extensions();
904
905 match self {
906 UncompressedUintFormat::U8 => {
907 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
908 extensions.gl_arb_texture_rg)
909 },
910
911 UncompressedUintFormat::U16 => {
912 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
913 extensions.gl_arb_texture_rg)
914 },
915
916 UncompressedUintFormat::U32 => {
917 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
918 extensions.gl_arb_texture_rg)
919 },
920
921 UncompressedUintFormat::U8U8 => {
922 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
923 extensions.gl_arb_texture_rg)
924 },
925
926 UncompressedUintFormat::U16U16 => {
927 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
928 extensions.gl_arb_texture_rg)
929 },
930
931 UncompressedUintFormat::U32U32 => {
932 version >= &Version(Api::Gl, 3, 0) || (extensions.gl_ext_texture_integer &&
933 extensions.gl_arb_texture_rg)
934 },
935
936 UncompressedUintFormat::U8U8U8 => {
937 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
938 },
939
940 UncompressedUintFormat::U16U16U16 => {
941 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
942 },
943
944 UncompressedUintFormat::U32U32U32 => {
945 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
946 },
947
948 UncompressedUintFormat::U8U8U8U8 => {
949 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
950 },
951
952 UncompressedUintFormat::U16U16U16U16 => {
953 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
954 },
955
956 UncompressedUintFormat::U32U32U32U32 => {
957 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_texture_integer
958 },
959
960 UncompressedUintFormat::U10U10U10U2 => {
961 version >= &Version(Api::Gl, 3, 3) || extensions.gl_arb_texture_rgb10_a2ui
962 },
963 }
964 }
965
966 pub fn is_color_renderable<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
969 if !self.is_supported(context) {
971 return false;
972 }
973
974 let version = context.get_version();
975
976 if version >= &Version(Api::Gl, 1, 0) {
978 return true;
979 }
980
981 match self {
983 UncompressedUintFormat::U8 => version >= &Version(Api::GlEs, 3, 0),
984 UncompressedUintFormat::U16 => version >= &Version(Api::GlEs, 3, 0),
985 UncompressedUintFormat::U32 => version >= &Version(Api::GlEs, 3, 0),
986 UncompressedUintFormat::U8U8 => version >= &Version(Api::GlEs, 3, 0),
987 UncompressedUintFormat::U16U16 => version >= &Version(Api::GlEs, 3, 0),
988 UncompressedUintFormat::U32U32 => version >= &Version(Api::GlEs, 3, 0),
989 UncompressedUintFormat::U8U8U8 => false,
990 UncompressedUintFormat::U16U16U16 => false,
991 UncompressedUintFormat::U32U32U32 => false,
992 UncompressedUintFormat::U8U8U8U8 => version >= &Version(Api::GlEs, 3, 0),
993 UncompressedUintFormat::U16U16U16U16 => version >= &Version(Api::GlEs, 3, 0),
994 UncompressedUintFormat::U32U32U32U32 => version >= &Version(Api::GlEs, 3, 0),
995 UncompressedUintFormat::U10U10U10U2 => version >= &Version(Api::GlEs, 3, 0),
996 }
997 }
998
999 fn to_glenum(&self) -> gl::types::GLenum {
1000 match self {
1001 UncompressedUintFormat::U8 => gl::R8UI,
1002 UncompressedUintFormat::U16 => gl::R16UI,
1003 UncompressedUintFormat::U32 => gl::R32UI,
1004 UncompressedUintFormat::U8U8 => gl::RG8UI,
1005 UncompressedUintFormat::U16U16 => gl::RG16UI,
1006 UncompressedUintFormat::U32U32 => gl::RG32UI,
1007 UncompressedUintFormat::U8U8U8 => gl::RGB8UI,
1008 UncompressedUintFormat::U16U16U16 => gl::RGB16UI,
1009 UncompressedUintFormat::U32U32U32 => gl::RGB32UI,
1010 UncompressedUintFormat::U8U8U8U8 => gl::RGBA8UI,
1011 UncompressedUintFormat::U16U16U16U16 => gl::RGBA16UI,
1012 UncompressedUintFormat::U32U32U32U32 => gl::RGBA32UI,
1013 UncompressedUintFormat::U10U10U10U2 => gl::RGB10_A2UI,
1014 }
1015 }
1016}
1017
1018#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1020pub enum CompressedFormat {
1021 RgtcFormatU,
1023 RgtcFormatI,
1025 RgtcFormatUU,
1027 RgtcFormatII,
1029
1030 BptcUnorm4,
1032 BptcSignedFloat3,
1034 BptcUnsignedFloat3,
1036
1037 S3tcDxt1NoAlpha,
1039 S3tcDxt1Alpha,
1041 S3tcDxt3Alpha,
1043 S3tcDxt5Alpha,
1045}
1046
1047impl CompressedFormat {
1048 #[inline]
1050 pub fn get_formats_list() -> Vec<CompressedFormat> {
1051 vec![
1052 CompressedFormat::RgtcFormatU,
1053 CompressedFormat::RgtcFormatI,
1054 CompressedFormat::RgtcFormatUU,
1055 CompressedFormat::RgtcFormatII,
1056 CompressedFormat::BptcUnorm4,
1057 CompressedFormat::BptcSignedFloat3,
1058 CompressedFormat::BptcUnsignedFloat3,
1059 CompressedFormat::S3tcDxt1NoAlpha,
1060 CompressedFormat::S3tcDxt1Alpha,
1061 CompressedFormat::S3tcDxt3Alpha,
1062 CompressedFormat::S3tcDxt5Alpha,
1063 ]
1064 }
1065
1066 #[inline]
1068 pub fn to_texture_format(self) -> TextureFormat {
1069 TextureFormat::CompressedFormat(self)
1070 }
1071
1072 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
1074 let version = context.get_version();
1075 let extensions = context.get_extensions();
1076
1077 match self {
1078 CompressedFormat::RgtcFormatU => {
1079 version >= &Version(Api::Gl, 3, 0)
1080 },
1081 CompressedFormat::RgtcFormatI => {
1082 version >= &Version(Api::Gl, 3, 0)
1083 },
1084 CompressedFormat::RgtcFormatUU => {
1085 version >= &Version(Api::Gl, 3, 0)
1086 },
1087 CompressedFormat::RgtcFormatII => {
1088 version >= &Version(Api::Gl, 3, 0)
1089 },
1090 CompressedFormat::BptcUnorm4 => {
1091 version >= &Version(Api::Gl, 4, 2) || extensions.gl_arb_texture_compression_bptc
1092 },
1093 CompressedFormat::BptcSignedFloat3 => {
1094 version >= &Version(Api::Gl, 4, 2) || extensions.gl_arb_texture_compression_bptc
1095 },
1096 CompressedFormat::BptcUnsignedFloat3 => {
1097 version >= &Version(Api::Gl, 4, 2) || extensions.gl_arb_texture_compression_bptc
1098 },
1099 CompressedFormat::S3tcDxt1NoAlpha => {
1100 extensions.gl_ext_texture_compression_s3tc
1101 },
1102 CompressedFormat::S3tcDxt1Alpha => {
1103 extensions.gl_ext_texture_compression_s3tc
1104 },
1105 CompressedFormat::S3tcDxt3Alpha => {
1106 extensions.gl_ext_texture_compression_s3tc
1107 },
1108 CompressedFormat::S3tcDxt5Alpha => {
1109 extensions.gl_ext_texture_compression_s3tc
1110 },
1111 }
1112 }
1113
1114 fn to_glenum(&self) -> gl::types::GLenum {
1115 match self {
1116 CompressedFormat::RgtcFormatU => gl::COMPRESSED_RED_RGTC1,
1117 CompressedFormat::RgtcFormatI => gl::COMPRESSED_SIGNED_RED_RGTC1,
1118 CompressedFormat::RgtcFormatUU => gl::COMPRESSED_RG_RGTC2,
1119 CompressedFormat::RgtcFormatII => gl::COMPRESSED_SIGNED_RG_RGTC2,
1120 CompressedFormat::BptcUnorm4 => gl::COMPRESSED_RGBA_BPTC_UNORM,
1121 CompressedFormat::BptcSignedFloat3 => gl::COMPRESSED_RGB_BPTC_SIGNED_FLOAT,
1122 CompressedFormat::BptcUnsignedFloat3 => gl::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
1123 CompressedFormat::S3tcDxt1NoAlpha => gl::COMPRESSED_RGB_S3TC_DXT1_EXT,
1124 CompressedFormat::S3tcDxt1Alpha => gl::COMPRESSED_RGBA_S3TC_DXT1_EXT,
1125 CompressedFormat::S3tcDxt3Alpha => gl::COMPRESSED_RGBA_S3TC_DXT3_EXT,
1126 CompressedFormat::S3tcDxt5Alpha => gl::COMPRESSED_RGBA_S3TC_DXT5_EXT,
1127 }
1128 }
1129}
1130
1131#[allow(missing_docs)]
1133#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1134pub enum CompressedSrgbFormat {
1135 Bptc,
1137 S3tcDxt1NoAlpha,
1138 S3tcDxt1Alpha,
1139 S3tcDxt3Alpha,
1140 S3tcDxt5Alpha,
1141}
1142
1143impl CompressedSrgbFormat {
1144 #[inline]
1146 pub fn get_formats_list() -> Vec<CompressedSrgbFormat> {
1147 vec![
1148 CompressedSrgbFormat::Bptc,
1149 CompressedSrgbFormat::S3tcDxt1NoAlpha,
1150 CompressedSrgbFormat::S3tcDxt1Alpha,
1151 CompressedSrgbFormat::S3tcDxt3Alpha,
1152 CompressedSrgbFormat::S3tcDxt5Alpha,
1153 ]
1154 }
1155
1156 #[inline]
1158 pub fn to_texture_format(self) -> TextureFormat {
1159 TextureFormat::CompressedSrgbFormat(self)
1160 }
1161
1162 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
1164 let version = context.get_version();
1165 let extensions = context.get_extensions();
1166
1167 match self {
1168 CompressedSrgbFormat::Bptc => {
1169 version >= &Version(Api::Gl, 4, 2) || extensions.gl_arb_texture_compression_bptc
1170 },
1171 CompressedSrgbFormat::S3tcDxt1NoAlpha => {
1172 extensions.gl_ext_texture_compression_s3tc && extensions.gl_ext_texture_srgb
1173 },
1174 CompressedSrgbFormat::S3tcDxt1Alpha => {
1175 extensions.gl_ext_texture_compression_s3tc && extensions.gl_ext_texture_srgb
1176 },
1177 CompressedSrgbFormat::S3tcDxt3Alpha => {
1178 extensions.gl_ext_texture_compression_s3tc && extensions.gl_ext_texture_srgb
1179 },
1180 CompressedSrgbFormat::S3tcDxt5Alpha => {
1181 extensions.gl_ext_texture_compression_s3tc && extensions.gl_ext_texture_srgb
1182 },
1183 }
1184 }
1185
1186 fn to_glenum(&self) -> gl::types::GLenum {
1187 match self {
1188 CompressedSrgbFormat::Bptc => gl::COMPRESSED_SRGB_ALPHA_BPTC_UNORM,
1189 CompressedSrgbFormat::S3tcDxt1NoAlpha => gl::COMPRESSED_SRGB_S3TC_DXT1_EXT,
1190 CompressedSrgbFormat::S3tcDxt1Alpha => gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
1191 CompressedSrgbFormat::S3tcDxt3Alpha => gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
1192 CompressedSrgbFormat::S3tcDxt5Alpha => gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
1193 }
1194 }
1195}
1196
1197#[allow(missing_docs)]
1202#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1203pub enum DepthFormat {
1204 I16,
1205 I24,
1206 I32,
1208 F32,
1209}
1210
1211impl DepthFormat {
1212 #[inline]
1214 pub fn get_formats_list() -> Vec<DepthFormat> {
1215 vec![
1216 DepthFormat::I16,
1217 DepthFormat::I24,
1218 DepthFormat::I32,
1219 DepthFormat::F32,
1220 ]
1221 }
1222
1223 #[inline]
1225 pub fn to_texture_format(self) -> TextureFormat {
1226 TextureFormat::DepthFormat(self)
1227 }
1228
1229 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
1231 let version = context.get_version();
1232 let extensions = context.get_extensions();
1233
1234 match self {
1235 DepthFormat::I16 => {
1236 version >= &Version(Api::Gl, 3, 0) || extensions.gl_arb_depth_texture
1237 },
1238
1239 DepthFormat::I24 => {
1240 version >= &Version(Api::Gl, 3, 0) || extensions.gl_arb_depth_texture
1241 },
1242
1243 DepthFormat::I32 => {
1244 version >= &Version(Api::Gl, 3, 0) || extensions.gl_arb_depth_texture
1245 },
1246
1247 DepthFormat::F32 => {
1248 version >= &Version(Api::Gl, 3, 0)
1249 },
1250 }
1251 }
1252
1253 fn to_glenum(&self) -> gl::types::GLenum {
1254 match self {
1255 DepthFormat::I16 => gl::DEPTH_COMPONENT16,
1256 DepthFormat::I24 => gl::DEPTH_COMPONENT24,
1257 DepthFormat::I32 => gl::DEPTH_COMPONENT32,
1258 DepthFormat::F32 => gl::DEPTH_COMPONENT32F,
1259 }
1260 }
1261}
1262
1263#[allow(missing_docs)]
1267#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1268pub enum DepthStencilFormat {
1269 I24I8,
1270 F32I8,
1271}
1272
1273impl DepthStencilFormat {
1274 #[inline]
1276 pub fn get_formats_list() -> Vec<DepthStencilFormat> {
1277 vec![
1278 DepthStencilFormat::I24I8,
1279 DepthStencilFormat::F32I8,
1280 ]
1281 }
1282
1283 #[inline]
1285 pub fn to_texture_format(self) -> TextureFormat {
1286 TextureFormat::DepthStencilFormat(self)
1287 }
1288
1289 pub fn is_supported<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
1291 let version = context.get_version();
1292 let extensions = context.get_extensions();
1293
1294 match self {
1295 DepthStencilFormat::I24I8 => {
1296 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_packed_depth_stencil ||
1297 extensions.gl_oes_packed_depth_stencil
1298 },
1299
1300 DepthStencilFormat::F32I8 => {
1301 version >= &Version(Api::Gl, 3, 0)
1302 },
1303 }
1304 }
1305
1306 fn to_glenum(&self) -> gl::types::GLenum {
1307 match self {
1308 DepthStencilFormat::I24I8 => gl::DEPTH24_STENCIL8,
1309 DepthStencilFormat::F32I8 => gl::DEPTH32F_STENCIL8,
1310 }
1311 }
1312}
1313
1314#[allow(missing_docs)]
1321#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1322pub enum StencilFormat {
1323 I1,
1324 I4,
1325 I8,
1326 I16,
1327}
1328
1329impl StencilFormat {
1330 #[inline]
1332 pub fn get_formats_list() -> Vec<StencilFormat> {
1333 vec![
1334 StencilFormat::I1,
1335 StencilFormat::I4,
1336 StencilFormat::I8,
1337 StencilFormat::I16,
1338 ]
1339 }
1340
1341 #[inline]
1343 pub fn to_texture_format(self) -> TextureFormat {
1344 TextureFormat::StencilFormat(self)
1345 }
1346
1347 pub fn is_supported_for_textures<C: ?Sized>(&self, context: &C) -> bool where C: CapabilitiesSource {
1349 let version = context.get_version();
1350 let extensions = context.get_extensions();
1351
1352 match self {
1353 StencilFormat::I8 => {
1354 version >= &Version(Api::Gl, 4, 4) || version >= &Version(Api::GlEs, 3, 2) ||
1355 extensions.gl_arb_texture_stencil8 || extensions.gl_oes_texture_stencil8
1356 },
1357
1358 _ => false
1359 }
1360 }
1361
1362 pub fn is_supported_for_renderbuffers<C: ?Sized>(&self, context: &C) -> bool
1364 where C: CapabilitiesSource
1365 {
1366 let version = context.get_version();
1367 let extensions = context.get_extensions();
1368
1369 match self {
1370 StencilFormat::I1 => {
1371 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_framebuffer_object ||
1372 extensions.gl_arb_framebuffer_object || extensions.gl_oes_stencil1
1373 },
1374
1375 StencilFormat::I4 => {
1376 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_framebuffer_object ||
1377 extensions.gl_arb_framebuffer_object || extensions.gl_oes_stencil4
1378 },
1379
1380 StencilFormat::I8 => {
1381 version >= &Version(Api::Gl, 3, 0) || extensions.gl_arb_texture_stencil8 ||
1382 version >= &Version(Api::GlEs, 2, 0)
1383 },
1384
1385 StencilFormat::I16 => {
1386 version >= &Version(Api::Gl, 3, 0) || extensions.gl_ext_framebuffer_object ||
1387 extensions.gl_arb_framebuffer_object
1388 },
1389 }
1390 }
1391
1392 fn to_glenum(&self) -> gl::types::GLenum {
1393 match self {
1394 StencilFormat::I1 => gl::STENCIL_INDEX1,
1395 StencilFormat::I4 => gl::STENCIL_INDEX4,
1396 StencilFormat::I8 => gl::STENCIL_INDEX8,
1397 StencilFormat::I16 => gl::STENCIL_INDEX16,
1398 }
1399 }
1400}
1401
1402#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
1404#[allow(missing_docs)]
1405pub enum TextureFormat {
1406 UncompressedFloat(UncompressedFloatFormat),
1407 UncompressedIntegral(UncompressedIntFormat),
1408 UncompressedUnsigned(UncompressedUintFormat),
1409 Srgb(SrgbFormat),
1410 CompressedFormat(CompressedFormat),
1411 CompressedSrgbFormat(CompressedSrgbFormat),
1412 DepthFormat(DepthFormat),
1413 StencilFormat(StencilFormat),
1414 DepthStencilFormat(DepthStencilFormat),
1415}
1416
1417impl TextureFormat {
1418 #[inline]
1420 pub fn get_formats_list() -> Vec<TextureFormat> {
1421 let mut result: Vec<_> = UncompressedFloatFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()).collect();
1423 result.extend(UncompressedIntFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1424 result.extend(UncompressedUintFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1425 result.extend(SrgbFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1426 result.extend(CompressedFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1427 result.extend(CompressedSrgbFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1428 result.extend(DepthFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1429 result.extend(StencilFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1430 result.extend(DepthStencilFormat::get_formats_list().into_iter().map(|f| f.to_texture_format()));
1431 result
1432 }
1433
1434 #[inline]
1436 pub fn is_supported_for_textures<C: ?Sized>(&self, c: &C) -> bool where C: CapabilitiesSource {
1437 match self {
1438 TextureFormat::UncompressedFloat(format) => format.is_supported(c),
1439 TextureFormat::UncompressedIntegral(format) => format.is_supported(c),
1440 TextureFormat::UncompressedUnsigned(format) => format.is_supported(c),
1441 TextureFormat::Srgb(format) => format.is_supported(c),
1442 TextureFormat::CompressedFormat(format) => format.is_supported(c),
1443 TextureFormat::CompressedSrgbFormat(format) => format.is_supported(c),
1444 TextureFormat::DepthFormat(format) => format.is_supported(c),
1445 TextureFormat::StencilFormat(format) => format.is_supported_for_textures(c),
1446 TextureFormat::DepthStencilFormat(format) => format.is_supported(c),
1447 }
1448 }
1449
1450 #[inline]
1452 pub fn is_supported_for_renderbuffers<C: ?Sized>(&self, c: &C) -> bool where C: CapabilitiesSource {
1453 match self {
1454 TextureFormat::UncompressedFloat(format) => format.is_supported(c),
1455 TextureFormat::UncompressedIntegral(format) => format.is_supported(c),
1456 TextureFormat::UncompressedUnsigned(format) => format.is_supported(c),
1457 TextureFormat::Srgb(format) => format.is_supported(c),
1458 TextureFormat::CompressedFormat(format) => format.is_supported(c),
1459 TextureFormat::CompressedSrgbFormat(format) => format.is_supported(c),
1460 TextureFormat::DepthFormat(format) => format.is_supported(c),
1461 TextureFormat::StencilFormat(format) => format.is_supported_for_renderbuffers(c),
1462 TextureFormat::DepthStencilFormat(format) => format.is_supported(c),
1463 }
1464 }
1465
1466 #[inline]
1469 pub fn is_renderable<C: ?Sized>(&self, c: &C) -> bool where C: CapabilitiesSource {
1470 match self {
1471 TextureFormat::UncompressedFloat(format) => format.is_color_renderable(c),
1472 TextureFormat::UncompressedIntegral(format) => format.is_color_renderable(c),
1473 TextureFormat::UncompressedUnsigned(format) => format.is_color_renderable(c),
1474 TextureFormat::Srgb(format) => format.is_color_renderable(c),
1475 TextureFormat::CompressedFormat(_) => false,
1476 TextureFormat::CompressedSrgbFormat(_) => false,
1477 TextureFormat::DepthFormat(_) => true,
1478 TextureFormat::StencilFormat(_) => true,
1479 TextureFormat::DepthStencilFormat(_) => true,
1480 }
1481 }
1482}
1483
1484impl ToGlEnum for TextureFormat {
1485 fn to_glenum(&self) -> gl::types::GLenum {
1486 match self {
1487 TextureFormat::UncompressedFloat(f) => f.to_glenum(),
1488 TextureFormat::UncompressedIntegral(f) => f.to_glenum(),
1489 TextureFormat::UncompressedUnsigned(f) => f.to_glenum(),
1490 TextureFormat::Srgb(f) => f.to_glenum(),
1491 TextureFormat::CompressedFormat(f) => f.to_glenum(),
1492 TextureFormat::CompressedSrgbFormat(f) => f.to_glenum(),
1493 TextureFormat::DepthFormat(f) => f.to_glenum(),
1494 TextureFormat::StencilFormat(f) => f.to_glenum(),
1495 TextureFormat::DepthStencilFormat(f) => f.to_glenum(),
1496 }
1497 }
1498}
1499
1500#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1501pub enum ClientFormatAny {
1502 ClientFormat(ClientFormat),
1503 CompressedFormat(CompressedFormat),
1504 CompressedSrgbFormat(CompressedSrgbFormat),
1505}
1506
1507impl ClientFormatAny {
1508 #[inline]
1510 pub fn is_compressed(&self) -> bool {
1511 match *self {
1512 ClientFormatAny::ClientFormat(_) => false,
1513 ClientFormatAny::CompressedFormat(_) => true,
1514 ClientFormatAny::CompressedSrgbFormat(_) => true,
1515 }
1516 }
1517
1518 pub fn get_buffer_size(&self, width: u32, height: Option<u32>,
1525 depth: Option<u32>, array_size: Option<u32>) -> usize {
1526 match *self {
1527 ClientFormatAny::ClientFormat(ref format) => {
1528 format.get_size() * width as usize * height.unwrap_or(1) as usize *
1529 depth.unwrap_or(1) as usize * array_size.unwrap_or(1) as usize
1530 },
1531
1532 ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt1Alpha) |
1534 ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt1Alpha) |
1535 ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt1NoAlpha) |
1536 ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt1NoAlpha) |
1537 ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatU) |
1538 ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatI) => {
1539
1540 let width = if width < 4 { 4 } else { width as usize };
1541 let height = height.map(|height| if height < 4 { 4 } else { height as usize })
1542 .expect("ST3C, RGTC and BPTC textures must have 2 dimensions");
1543 if (width % 4) != 0 || (height % 4) != 0 {
1544 panic!("ST3C, RGTC and BPTC textures must have a width and height multiple of 4.");
1545 }
1546 if depth.is_some() { panic!("ST3C, RGTC and BPTC textures are 2 dimension only.")
1548 }
1549
1550 let uncompressed_bit_size = 4 * width as usize * height as usize *
1551 depth.unwrap_or(1) as usize * array_size.unwrap_or(1) as usize;
1552 uncompressed_bit_size / 8 },
1554
1555 ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt3Alpha) |
1557 ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt3Alpha) |
1558 ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt5Alpha) |
1559 ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt5Alpha) |
1560 ClientFormatAny::CompressedFormat(CompressedFormat::BptcUnorm4) |
1561 ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::Bptc) |
1562 ClientFormatAny::CompressedFormat(CompressedFormat::BptcSignedFloat3) |
1563 ClientFormatAny::CompressedFormat(CompressedFormat::BptcUnsignedFloat3) |
1564 ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatUU) |
1565 ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatII) => {
1566
1567 let width = if width < 4 { 4 } else { width as usize };
1568 let height = height.map(|height| if height < 4 { 4 } else { height as usize })
1569 .expect("ST3C, RGTC and BPTC textures must have 2 dimensions");
1570 if (width % 4) != 0 || (height % 4) != 0 {
1571 panic!("ST3C, RGTC and BPTC textures must have a width and height multiple of 4.");
1572 }
1573 if depth.is_some() { panic!("ST3C, RGTC and BPTC textures are 2 dimension only.")
1575 }
1576
1577 let uncompressed_bit_size = 4 * width as usize * height as usize *
1578 depth.unwrap_or(1) as usize * array_size.unwrap_or(1) as usize;
1579 uncompressed_bit_size / 4 },
1581 }
1582 }
1583
1584 #[inline]
1585 pub fn get_num_components(&self) -> u8 {
1586 match *self {
1587 ClientFormatAny::ClientFormat(ref format) => format.get_num_components(),
1588 _ => unimplemented!(),
1589 }
1590 }
1591
1592 #[doc(hidden)]
1593 pub fn from_internal_compressed_format(internal: gl::types::GLenum) -> Option<ClientFormatAny> {
1594 match internal {
1595 gl::COMPRESSED_RGB_S3TC_DXT1_EXT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt1NoAlpha)),
1596 gl::COMPRESSED_RGBA_S3TC_DXT1_EXT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt1Alpha)),
1597 gl::COMPRESSED_RGBA_S3TC_DXT3_EXT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt3Alpha)),
1598 gl::COMPRESSED_RGBA_S3TC_DXT5_EXT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::S3tcDxt5Alpha)),
1599 gl::COMPRESSED_SRGB_S3TC_DXT1_EXT => Some(ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt1NoAlpha)),
1600 gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT => Some(ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt1Alpha)),
1601 gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT => Some(ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt3Alpha)),
1602 gl::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT => Some(ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::S3tcDxt5Alpha)),
1603 gl::COMPRESSED_RGBA_BPTC_UNORM => Some(ClientFormatAny::CompressedFormat(CompressedFormat::BptcUnorm4)),
1604 gl::COMPRESSED_SRGB_ALPHA_BPTC_UNORM => Some(ClientFormatAny::CompressedSrgbFormat(CompressedSrgbFormat::Bptc)),
1605 gl::COMPRESSED_RGB_BPTC_SIGNED_FLOAT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::BptcSignedFloat3)),
1606 gl::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT => Some(ClientFormatAny::CompressedFormat(CompressedFormat::BptcUnsignedFloat3)),
1607 gl::COMPRESSED_RED_RGTC1 => Some(ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatU)),
1608 gl::COMPRESSED_SIGNED_RED_RGTC1 => Some(ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatI)),
1609 gl::COMPRESSED_RG_RGTC2 => Some(ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatUU)),
1610 gl::COMPRESSED_SIGNED_RG_RGTC2 => Some(ClientFormatAny::CompressedFormat(CompressedFormat::RgtcFormatII)),
1611 _ => None,
1612 }
1613 }
1614}
1615
1616#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1618pub enum RequestType {
1619 TexImage(Option<ClientFormatAny>),
1621 TexStorage,
1623 Renderbuffer,
1625}
1626
1627impl RequestType {
1628 #[inline]
1630 pub fn get_client_format(&self) -> Option<ClientFormatAny> {
1631 match self {
1632 RequestType::TexImage(f) => *f,
1633 RequestType::TexStorage => None,
1634 RequestType::Renderbuffer => None,
1635 }
1636 }
1637}
1638
1639pub fn format_request_to_glenum(context: &Context, format: TextureFormatRequest,
1645 rq_ty: RequestType)
1646 -> Result<gl::types::GLenum, FormatNotSupportedError>
1647{
1648 let version = context.get_opengl_version();
1649 let extensions = context.get_extensions();
1650
1651 let is_client_compressed = match rq_ty.get_client_format() {
1652 Some(ref client) => client.is_compressed(),
1653 None => false,
1654 };
1655
1656 Ok(match format {
1657 TextureFormatRequest::AnyFloatingPoint => {
1661 let size = rq_ty.get_client_format().map(|c| c.get_num_components());
1662
1663 if version >= &Version(Api::Gl, 3, 0) || version >= &Version(Api::GlEs, 3, 0) {
1664
1665 match (rq_ty, size) {
1666 (RequestType::TexImage(_), Some(1)) => gl::RED,
1667 (RequestType::TexImage(_), Some(2)) => gl::RG,
1668 (RequestType::TexImage(_), Some(3)) => gl::RGB,
1669 (RequestType::TexImage(_), Some(4)) => gl::RGBA,
1670 (RequestType::TexImage(_), None) => gl::RGBA,
1671 (_, Some(1)) => gl::R8,
1672 (_, Some(2)) => gl::RG8,
1673 (_, Some(3)) => gl::RGB8,
1674 (_, Some(4)) => gl::RGBA8,
1675 (_, None) => gl::RGBA8,
1676 _ => unreachable!(),
1677 }
1678
1679 } else if version >= &Version(Api::Gl, 1, 1) {
1680 match (rq_ty, size) {
1681 (RequestType::TexImage(_), Some(1)) => gl::RED,
1682 (RequestType::TexImage(_), Some(2)) => gl::RG,
1683 (RequestType::TexImage(_), Some(3)) => gl::RGB,
1684 (RequestType::TexImage(_), Some(4)) => gl::RGBA,
1685 (RequestType::TexImage(_), None) => gl::RGBA,
1686 (_, Some(1)) if extensions.gl_arb_texture_rg => gl::R8,
1687 (_, Some(2)) if extensions.gl_arb_texture_rg => gl::RG8,
1688 (_, Some(3)) => gl::RGB8,
1689 (_, Some(4)) => gl::RGBA8,
1690 (_, None) => gl::RGBA8,
1691 _ => return Err(FormatNotSupportedError),
1692 }
1693
1694 } else if version >= &Version(Api::Gl, 1, 0) {
1695 match rq_ty {
1696 RequestType::TexImage(_) => size.unwrap_or(4) as gl::types::GLenum,
1697 _ => return Err(FormatNotSupportedError)
1698 }
1699
1700 } else if version >= &Version(Api::GlEs, 2, 0) {
1701 match (rq_ty, size) {
1702 (RequestType::TexImage(_), Some(3)) => gl::RGB,
1703 (_, Some(3)) => {
1704 if extensions.gl_oes_rgb8_rgba8 {
1705 gl::RGB8_OES
1706 } else if extensions.gl_arm_rgba8 {
1707 gl::RGBA8_OES
1708 } else {
1709 gl::RGB565
1710 }
1711 },
1712 (RequestType::TexImage(_), Some(4)) => gl::RGBA,
1713 (RequestType::TexImage(_), None) => gl::RGBA,
1714 (_, Some(4)) | (_, None) => {
1715 if extensions.gl_oes_rgb8_rgba8 || extensions.gl_arm_rgba8 {
1716 gl::RGBA8_OES
1717 } else {
1718 gl::RGB5_A1
1719 }
1720 },
1721 _ => return Err(FormatNotSupportedError)
1722 }
1723
1724 } else {
1725 unreachable!();
1726 }
1727 },
1728
1729 TextureFormatRequest::Specific(TextureFormat::UncompressedFloat(format)) => {
1730 if format.is_supported(context) {
1731 format.to_glenum()
1732 } else {
1733 return Err(FormatNotSupportedError);
1734 }
1735 },
1736
1737 TextureFormatRequest::AnyCompressed if is_client_compressed => {
1741 let newformat = TextureFormat::CompressedFormat(match rq_ty.get_client_format() {
1744 Some(ClientFormatAny::CompressedFormat(format)) => format,
1745 _ => unreachable!(),
1746 });
1747 format_request_to_glenum(context, TextureFormatRequest::Specific(newformat), rq_ty)?
1748 },
1749
1750 TextureFormatRequest::AnyCompressed => {
1751 match rq_ty {
1752 RequestType::TexImage(client) => {
1753 let size = client.map(|c| c.get_num_components());
1754
1755 if version >= &Version(Api::Gl, 1, 1) {
1756 match size {
1757 Some(1) => if version >= &Version(Api::Gl, 3, 0) ||
1758 extensions.gl_arb_texture_rg
1759 {
1760 gl::COMPRESSED_RED
1761 } else {
1762 1
1763 },
1764 Some(2) => if version >= &Version(Api::Gl, 3, 0) ||
1765 extensions.gl_arb_texture_rg
1766 {
1767 gl::COMPRESSED_RG
1768 } else {
1769 2
1770 },
1771 Some(3) => gl::COMPRESSED_RGB,
1772 Some(4) => gl::COMPRESSED_RGBA,
1773 None => gl::COMPRESSED_RGBA,
1774 _ => unreachable!(),
1775 }
1776
1777 } else {
1778 size.unwrap_or(4) as gl::types::GLenum
1781 }
1782 },
1783 RequestType::TexStorage | RequestType::Renderbuffer => {
1784 return Err(FormatNotSupportedError)
1785 },
1786 }
1787 },
1788
1789 TextureFormatRequest::Specific(TextureFormat::CompressedFormat(format)) => {
1790 if format.is_supported(context) {
1791 format.to_glenum()
1792 } else {
1793 return Err(FormatNotSupportedError);
1794 }
1795 },
1796
1797 TextureFormatRequest::AnySrgb => {
1801 let size = rq_ty.get_client_format().map(|c| c.get_num_components());
1802
1803 if version >= &Version(Api::Gl, 2, 1) || version >= &Version(Api::GlEs, 3, 0) ||
1804 extensions.gl_ext_texture_srgb
1805 {
1806 match size {
1807 Some(1 ..= 3) => gl::SRGB8,
1808 Some(4) => gl::SRGB8_ALPHA8,
1809 None => if let RequestType::TexImage(_) = rq_ty { gl::SRGB8 } else { gl::SRGB8_ALPHA8 },
1810 _ => unreachable!(),
1811 }
1812
1813 } else {
1814 format_request_to_glenum(context, TextureFormatRequest::AnyFloatingPoint,
1816 rq_ty)?
1817 }
1818 },
1819
1820 TextureFormatRequest::Specific(TextureFormat::Srgb(format)) => {
1821 if format.is_supported(context) {
1822 format.to_glenum()
1823 } else {
1824 return Err(FormatNotSupportedError);
1825 }
1826 },
1827
1828 TextureFormatRequest::AnyCompressedSrgb if is_client_compressed => {
1832 let newformat = TextureFormat::CompressedSrgbFormat(match rq_ty.get_client_format() {
1833 Some(ClientFormatAny::CompressedSrgbFormat(format)) => format,
1834 _ => unreachable!(),
1835 });
1836 format_request_to_glenum(context, TextureFormatRequest::Specific(newformat), rq_ty)?
1837 },
1838
1839 TextureFormatRequest::AnyCompressedSrgb => {
1840 if version >= &Version(Api::Gl, 4, 0) || extensions.gl_ext_texture_srgb {
1841 match rq_ty {
1842 RequestType::TexImage(client) => {
1843 match client.map(|c| c.get_num_components()) {
1844 Some(1 ..= 3) => gl::COMPRESSED_SRGB,
1845 Some(4) => gl::COMPRESSED_SRGB_ALPHA,
1846 None => gl::COMPRESSED_SRGB_ALPHA,
1847 _ => unreachable!(),
1848 }
1849 },
1850 RequestType::TexStorage | RequestType::Renderbuffer => {
1851 return Err(FormatNotSupportedError)
1852 },
1853 }
1854
1855 } else {
1856 format_request_to_glenum(context, TextureFormatRequest::AnySrgb, rq_ty)?
1858 }
1859 },
1860
1861 TextureFormatRequest::Specific(TextureFormat::CompressedSrgbFormat(format)) => {
1862 if format.is_supported(context) {
1863 format.to_glenum()
1864 } else {
1865 return Err(FormatNotSupportedError);
1866 }
1867 },
1868
1869 TextureFormatRequest::AnyIntegral => {
1873 let size = rq_ty.get_client_format().map(|c| c.get_num_components());
1874
1875 if version >= &Version(Api::Gl, 3, 0) {
1876 match size { Some(1) => gl::R32I,
1878 Some(2) => gl::RG32I,
1879 Some(3) => gl::RGB32I,
1880 Some(4) => gl::RGBA32I,
1881 None => gl::RGBA32I,
1882 _ => unreachable!(),
1883 }
1884
1885 } else {
1886 if !extensions.gl_ext_texture_integer {
1887 return Err(FormatNotSupportedError);
1888 }
1889
1890 match size { Some(1) => if extensions.gl_arb_texture_rg {
1892 gl::R32I
1893 } else {
1894 return Err(FormatNotSupportedError);
1895 },
1896 Some(2) => if extensions.gl_arb_texture_rg {
1897 gl::RG32I
1898 } else {
1899 return Err(FormatNotSupportedError);
1900 },
1901 Some(3) => gl::RGB32I_EXT,
1902 Some(4) => gl::RGBA32I_EXT,
1903 None => gl::RGBA32I_EXT,
1904 _ => unreachable!(),
1905 }
1906 }
1907 },
1908
1909 TextureFormatRequest::Specific(TextureFormat::UncompressedIntegral(format)) => {
1910 if format.is_supported(context) {
1911 format.to_glenum()
1912 } else {
1913 return Err(FormatNotSupportedError);
1914 }
1915 },
1916
1917 TextureFormatRequest::AnyUnsigned => {
1921 let size = rq_ty.get_client_format().map(|c| c.get_num_components());
1922
1923 if version >= &Version(Api::Gl, 3, 0) {
1924 match size { Some(1) => gl::R32UI,
1926 Some(2) => gl::RG32UI,
1927 Some(3) => gl::RGB32UI,
1928 Some(4) => gl::RGBA32UI,
1929 None => gl::RGBA32UI,
1930 _ => unreachable!(),
1931 }
1932
1933 } else {
1934 if !extensions.gl_ext_texture_integer {
1935 return Err(FormatNotSupportedError);
1936 }
1937
1938 match size { Some(1) => if extensions.gl_arb_texture_rg {
1940 gl::R32UI
1941 } else {
1942 return Err(FormatNotSupportedError);
1943 },
1944 Some(2) => if extensions.gl_arb_texture_rg {
1945 gl::RG32UI
1946 } else {
1947 return Err(FormatNotSupportedError);
1948 },
1949 Some(3) => gl::RGB32UI_EXT,
1950 Some(4) => gl::RGBA32UI_EXT,
1951 None => gl::RGBA32UI_EXT,
1952 _ => unreachable!(),
1953 }
1954 }
1955 },
1956
1957 TextureFormatRequest::Specific(TextureFormat::UncompressedUnsigned(format)) => {
1958 if format.is_supported(context) {
1959 format.to_glenum()
1960 } else {
1961 return Err(FormatNotSupportedError);
1962 }
1963 },
1964
1965 TextureFormatRequest::AnyDepth => {
1969 if version >= &Version(Api::Gl, 2, 0) {
1970 match rq_ty {
1971 RequestType::TexImage(_) => gl::DEPTH_COMPONENT,
1972 RequestType::TexStorage | RequestType::Renderbuffer => gl::DEPTH_COMPONENT24,
1973 }
1974
1975 } else if version >= &Version(Api::Gl, 1, 4) || extensions.gl_arb_depth_texture ||
1976 extensions.gl_oes_depth_texture
1977 {
1978 match rq_ty {
1979 RequestType::TexImage(_) => gl::DEPTH_COMPONENT,
1980 RequestType::TexStorage | RequestType::Renderbuffer => return Err(FormatNotSupportedError), }
1982
1983 } else {
1984 return Err(FormatNotSupportedError);
1985 }
1986 },
1987
1988 TextureFormatRequest::Specific(TextureFormat::DepthFormat(format)) => {
1989 if format.is_supported(context) {
1990 format.to_glenum()
1991 } else {
1992 return Err(FormatNotSupportedError);
1993 }
1994 },
1995
1996 TextureFormatRequest::AnyStencil => {
2000 return format_request_to_glenum(context,
2002 TextureFormatRequest::Specific(
2003 TextureFormat::StencilFormat(
2004 StencilFormat::I8)), rq_ty);
2005 },
2006
2007 TextureFormatRequest::Specific(TextureFormat::StencilFormat(format)) => {
2008 match rq_ty {
2009 RequestType::TexImage(_) | RequestType::TexStorage => {
2010 if format.is_supported_for_textures(context) {
2011 format.to_glenum()
2012 } else {
2013 return Err(FormatNotSupportedError);
2014 }
2015 },
2016 RequestType::Renderbuffer => {
2017 if format.is_supported_for_renderbuffers(context) {
2018 format.to_glenum()
2019 } else {
2020 return Err(FormatNotSupportedError);
2021 }
2022 },
2023 }
2024 },
2025
2026 TextureFormatRequest::AnyDepthStencil => {
2030 if version >= &Version(Api::Gl, 3, 0) {
2031 match rq_ty {
2032 RequestType::TexImage(_) => gl::DEPTH_STENCIL,
2033 RequestType::TexStorage | RequestType::Renderbuffer => gl::DEPTH24_STENCIL8,
2034 }
2035
2036 } else if extensions.gl_ext_packed_depth_stencil {
2037 match rq_ty {
2038 RequestType::TexImage(_) => gl::DEPTH_STENCIL_EXT,
2039 RequestType::TexStorage | RequestType::Renderbuffer => gl::DEPTH24_STENCIL8_EXT,
2040 }
2041
2042 } else if extensions.gl_oes_packed_depth_stencil {
2043 match rq_ty {
2044 RequestType::TexImage(_) => gl::DEPTH_STENCIL_OES,
2045 RequestType::TexStorage | RequestType::Renderbuffer => gl::DEPTH24_STENCIL8_OES,
2046 }
2047
2048 } else {
2049 return Err(FormatNotSupportedError);
2050 }
2051 },
2052
2053 TextureFormatRequest::Specific(TextureFormat::DepthStencilFormat(format)) => {
2054 if format.is_supported(context) {
2055 format.to_glenum()
2056 } else {
2057 return Err(FormatNotSupportedError);
2058 }
2059 },
2060 })
2061}
2062
2063pub fn client_format_to_glenum(context: &Context, client: ClientFormatAny,
2069 format: TextureFormatRequest, inverted: bool)
2070 -> Result<(gl::types::GLenum, gl::types::GLenum),
2071 FormatNotSupportedError>
2072{
2073 let value = match format {
2074 TextureFormatRequest::AnyCompressed if client.is_compressed() => {
2075 match client {
2076 ClientFormatAny::CompressedFormat(client_format) => {
2077 if client_format.is_supported(context) {
2078 let e = client_format.to_glenum();
2079 Ok((e, e))
2080 } else {
2081 return Err(FormatNotSupportedError);
2082 }
2083 },
2084 _ => unreachable!(),
2085 }
2086 },
2087
2088 TextureFormatRequest::AnyCompressedSrgb if client.is_compressed() => {
2089 match client {
2090 ClientFormatAny::CompressedSrgbFormat(client_format) => {
2091 if client_format.is_supported(context) {
2092 let e = client_format.to_glenum();
2093 Ok((e, e))
2094 } else {
2095 return Err(FormatNotSupportedError);
2096 }
2097 },
2098 _ => unreachable!(),
2099 }
2100 },
2101
2102 TextureFormatRequest::Specific(TextureFormat::CompressedFormat(format))
2103 if client.is_compressed() => {
2104 if format.is_supported(context) {
2105 let e = format.to_glenum();
2106 Ok((e, e))
2107 } else {
2108 return Err(FormatNotSupportedError);
2109 }
2110 },
2111
2112 TextureFormatRequest::Specific(TextureFormat::CompressedSrgbFormat(format))
2113 if client.is_compressed() => {
2114 if format.is_supported(context) {
2115 let e = format.to_glenum();
2116 Ok((e, e))
2117 } else {
2118 return Err(FormatNotSupportedError);
2119 }
2120 },
2121
2122 TextureFormatRequest::AnyFloatingPoint | TextureFormatRequest::AnyCompressed |
2123 TextureFormatRequest::AnySrgb | TextureFormatRequest::AnyCompressedSrgb |
2124 TextureFormatRequest::Specific(TextureFormat::UncompressedFloat(_)) |
2125 TextureFormatRequest::Specific(TextureFormat::Srgb(_)) |
2126 TextureFormatRequest::Specific(TextureFormat::CompressedFormat(_)) |
2127 TextureFormatRequest::Specific(TextureFormat::CompressedSrgbFormat(_)) =>
2128 {
2129 match client {
2130 ClientFormatAny::ClientFormat(ClientFormat::U8) => Ok((gl::RED, gl::UNSIGNED_BYTE)),
2131 ClientFormatAny::ClientFormat(ClientFormat::U8U8) => Ok((gl::RG, gl::UNSIGNED_BYTE)),
2132 ClientFormatAny::ClientFormat(ClientFormat::U8U8U8) => Ok((gl::RGB, gl::UNSIGNED_BYTE)),
2133 ClientFormatAny::ClientFormat(ClientFormat::U8U8U8U8) => Ok((gl::RGBA, gl::UNSIGNED_BYTE)),
2134 ClientFormatAny::ClientFormat(ClientFormat::I8) => Ok((gl::RED, gl::BYTE)),
2135 ClientFormatAny::ClientFormat(ClientFormat::I8I8) => Ok((gl::RG, gl::BYTE)),
2136 ClientFormatAny::ClientFormat(ClientFormat::I8I8I8) => Ok((gl::RGB, gl::BYTE)),
2137 ClientFormatAny::ClientFormat(ClientFormat::I8I8I8I8) => Ok((gl::RGBA, gl::BYTE)),
2138 ClientFormatAny::ClientFormat(ClientFormat::U16) => Ok((gl::RED, gl::UNSIGNED_SHORT)),
2139 ClientFormatAny::ClientFormat(ClientFormat::U16U16) => Ok((gl::RG, gl::UNSIGNED_SHORT)),
2140 ClientFormatAny::ClientFormat(ClientFormat::U16U16U16) => Ok((gl::RGB, gl::UNSIGNED_SHORT)),
2141 ClientFormatAny::ClientFormat(ClientFormat::U16U16U16U16) => Ok((gl::RGBA, gl::UNSIGNED_SHORT)),
2142 ClientFormatAny::ClientFormat(ClientFormat::I16) => Ok((gl::RED, gl::SHORT)),
2143 ClientFormatAny::ClientFormat(ClientFormat::I16I16) => Ok((gl::RG, gl::SHORT)),
2144 ClientFormatAny::ClientFormat(ClientFormat::I16I16I16) => Ok((gl::RGB, gl::SHORT)),
2145 ClientFormatAny::ClientFormat(ClientFormat::I16I16I16I16) => Ok((gl::RGBA, gl::SHORT)),
2146 ClientFormatAny::ClientFormat(ClientFormat::U32) => Ok((gl::RED, gl::UNSIGNED_INT)),
2147 ClientFormatAny::ClientFormat(ClientFormat::U32U32) => Ok((gl::RG, gl::UNSIGNED_INT)),
2148 ClientFormatAny::ClientFormat(ClientFormat::U32U32U32) => Ok((gl::RGB, gl::UNSIGNED_INT)),
2149 ClientFormatAny::ClientFormat(ClientFormat::U32U32U32U32) => Ok((gl::RGBA, gl::UNSIGNED_INT)),
2150 ClientFormatAny::ClientFormat(ClientFormat::I32) => Ok((gl::RED, gl::INT)),
2151 ClientFormatAny::ClientFormat(ClientFormat::I32I32) => Ok((gl::RG, gl::INT)),
2152 ClientFormatAny::ClientFormat(ClientFormat::I32I32I32) => Ok((gl::RGB, gl::INT)),
2153 ClientFormatAny::ClientFormat(ClientFormat::I32I32I32I32) => Ok((gl::RGBA, gl::INT)),
2154 ClientFormatAny::ClientFormat(ClientFormat::U3U3U2) => Ok((gl::RGB, gl::UNSIGNED_BYTE_3_3_2)),
2155 ClientFormatAny::ClientFormat(ClientFormat::U5U6U5) => Ok((gl::RGB, gl::UNSIGNED_SHORT_5_6_5)),
2156 ClientFormatAny::ClientFormat(ClientFormat::U4U4U4U4) => Ok((gl::RGBA, gl::UNSIGNED_SHORT_4_4_4_4)),
2157 ClientFormatAny::ClientFormat(ClientFormat::U5U5U5U1) => Ok((gl::RGBA, gl::UNSIGNED_SHORT_5_5_5_1)),
2158 ClientFormatAny::ClientFormat(ClientFormat::U1U5U5U5Reversed) => Ok((gl::RGBA, gl::UNSIGNED_SHORT_1_5_5_5_REV)),
2159 ClientFormatAny::ClientFormat(ClientFormat::U10U10U10U2) => Ok((gl::RGBA, gl::UNSIGNED_INT_10_10_10_2)),
2160 ClientFormatAny::ClientFormat(ClientFormat::F16) => Ok((gl::RED, gl::HALF_FLOAT)),
2161 ClientFormatAny::ClientFormat(ClientFormat::F16F16) => Ok((gl::RG, gl::HALF_FLOAT)),
2162 ClientFormatAny::ClientFormat(ClientFormat::F16F16F16) => Ok((gl::RGB, gl::HALF_FLOAT)),
2163 ClientFormatAny::ClientFormat(ClientFormat::F16F16F16F16) => Ok((gl::RGBA, gl::HALF_FLOAT)),
2164 ClientFormatAny::ClientFormat(ClientFormat::F32) => Ok((gl::RED, gl::FLOAT)),
2165 ClientFormatAny::ClientFormat(ClientFormat::F32F32) => Ok((gl::RG, gl::FLOAT)),
2166 ClientFormatAny::ClientFormat(ClientFormat::F32F32F32) => Ok((gl::RGB, gl::FLOAT)),
2167 ClientFormatAny::ClientFormat(ClientFormat::F32F32F32F32) => Ok((gl::RGBA, gl::FLOAT)),
2168
2169 ClientFormatAny::CompressedFormat(_) => unreachable!(),
2172 ClientFormatAny::CompressedSrgbFormat(_) => unreachable!(),
2173 }
2174 },
2175
2176 TextureFormatRequest::AnyIntegral | TextureFormatRequest::AnyUnsigned |
2177 TextureFormatRequest::Specific(TextureFormat::UncompressedIntegral(_)) |
2178 TextureFormatRequest::Specific(TextureFormat::UncompressedUnsigned(_)) =>
2179 {
2180 match client {
2181 ClientFormatAny::ClientFormat(ClientFormat::U8) => Ok((gl::RED_INTEGER, gl::UNSIGNED_BYTE)),
2182 ClientFormatAny::ClientFormat(ClientFormat::U8U8) => Ok((gl::RG_INTEGER, gl::UNSIGNED_BYTE)),
2183 ClientFormatAny::ClientFormat(ClientFormat::U8U8U8) => Ok((gl::RGB_INTEGER, gl::UNSIGNED_BYTE)),
2184 ClientFormatAny::ClientFormat(ClientFormat::U8U8U8U8) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_BYTE)),
2185 ClientFormatAny::ClientFormat(ClientFormat::I8) => Ok((gl::RED_INTEGER, gl::BYTE)),
2186 ClientFormatAny::ClientFormat(ClientFormat::I8I8) => Ok((gl::RG_INTEGER, gl::BYTE)),
2187 ClientFormatAny::ClientFormat(ClientFormat::I8I8I8) => Ok((gl::RGB_INTEGER, gl::BYTE)),
2188 ClientFormatAny::ClientFormat(ClientFormat::I8I8I8I8) => Ok((gl::RGBA_INTEGER, gl::BYTE)),
2189 ClientFormatAny::ClientFormat(ClientFormat::U16) => Ok((gl::RED_INTEGER, gl::UNSIGNED_SHORT)),
2190 ClientFormatAny::ClientFormat(ClientFormat::U16U16) => Ok((gl::RG_INTEGER, gl::UNSIGNED_SHORT)),
2191 ClientFormatAny::ClientFormat(ClientFormat::U16U16U16) => Ok((gl::RGB_INTEGER, gl::UNSIGNED_SHORT)),
2192 ClientFormatAny::ClientFormat(ClientFormat::U16U16U16U16) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_SHORT)),
2193 ClientFormatAny::ClientFormat(ClientFormat::I16) => Ok((gl::RED_INTEGER, gl::SHORT)),
2194 ClientFormatAny::ClientFormat(ClientFormat::I16I16) => Ok((gl::RG_INTEGER, gl::SHORT)),
2195 ClientFormatAny::ClientFormat(ClientFormat::I16I16I16) => Ok((gl::RGB_INTEGER, gl::SHORT)),
2196 ClientFormatAny::ClientFormat(ClientFormat::I16I16I16I16) => Ok((gl::RGBA_INTEGER, gl::SHORT)),
2197 ClientFormatAny::ClientFormat(ClientFormat::U32) => Ok((gl::RED_INTEGER, gl::UNSIGNED_INT)),
2198 ClientFormatAny::ClientFormat(ClientFormat::U32U32) => Ok((gl::RG_INTEGER, gl::UNSIGNED_INT)),
2199 ClientFormatAny::ClientFormat(ClientFormat::U32U32U32) => Ok((gl::RGB_INTEGER, gl::UNSIGNED_INT)),
2200 ClientFormatAny::ClientFormat(ClientFormat::U32U32U32U32) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_INT)),
2201 ClientFormatAny::ClientFormat(ClientFormat::I32) => Ok((gl::RED_INTEGER, gl::INT)),
2202 ClientFormatAny::ClientFormat(ClientFormat::I32I32) => Ok((gl::RG_INTEGER, gl::INT)),
2203 ClientFormatAny::ClientFormat(ClientFormat::I32I32I32) => Ok((gl::RGB_INTEGER, gl::INT)),
2204 ClientFormatAny::ClientFormat(ClientFormat::I32I32I32I32) => Ok((gl::RGBA_INTEGER, gl::INT)),
2205 ClientFormatAny::ClientFormat(ClientFormat::U3U3U2) => Ok((gl::RGB_INTEGER, gl::UNSIGNED_BYTE_3_3_2)),
2206 ClientFormatAny::ClientFormat(ClientFormat::U5U6U5) => Ok((gl::RGB_INTEGER, gl::UNSIGNED_SHORT_5_6_5)),
2207 ClientFormatAny::ClientFormat(ClientFormat::U4U4U4U4) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_SHORT_4_4_4_4)),
2208 ClientFormatAny::ClientFormat(ClientFormat::U5U5U5U1) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_SHORT_5_5_5_1)),
2209 ClientFormatAny::ClientFormat(ClientFormat::U1U5U5U5Reversed) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_SHORT_1_5_5_5_REV)),
2210 ClientFormatAny::ClientFormat(ClientFormat::U10U10U10U2) => Ok((gl::RGBA_INTEGER, gl::UNSIGNED_INT_10_10_10_2)),
2211 ClientFormatAny::ClientFormat(ClientFormat::F16) => Ok((gl::RED_INTEGER, gl::HALF_FLOAT)),
2212 ClientFormatAny::ClientFormat(ClientFormat::F16F16) => Ok((gl::RG_INTEGER, gl::HALF_FLOAT)),
2213 ClientFormatAny::ClientFormat(ClientFormat::F16F16F16) => Ok((gl::RGB_INTEGER, gl::HALF_FLOAT)),
2214 ClientFormatAny::ClientFormat(ClientFormat::F16F16F16F16) => Ok((gl::RGBA_INTEGER, gl::HALF_FLOAT)),
2215 ClientFormatAny::ClientFormat(ClientFormat::F32) => Ok((gl::RED_INTEGER, gl::FLOAT)),
2216 ClientFormatAny::ClientFormat(ClientFormat::F32F32) => Ok((gl::RG_INTEGER, gl::FLOAT)),
2217 ClientFormatAny::ClientFormat(ClientFormat::F32F32F32) => Ok((gl::RGB_INTEGER, gl::FLOAT)),
2218 ClientFormatAny::ClientFormat(ClientFormat::F32F32F32F32) => Ok((gl::RGBA_INTEGER, gl::FLOAT)),
2219
2220 ClientFormatAny::CompressedFormat(_) => unreachable!(),
2223 ClientFormatAny::CompressedSrgbFormat(_) => unreachable!(),
2224 }
2225 },
2226
2227 TextureFormatRequest::AnyDepth |
2228 TextureFormatRequest::Specific(TextureFormat::DepthFormat(_)) =>
2229 {
2230 if client != ClientFormatAny::ClientFormat(ClientFormat::F32) {
2231 panic!("Only ClientFormatAny::ClientFormat(ClientFormat::F32) can be used to upload on a depth texture");
2232 }
2233
2234 Ok((gl::DEPTH_COMPONENT, gl::FLOAT))
2235 }
2236
2237 TextureFormatRequest::AnyStencil |
2238 TextureFormatRequest::Specific(TextureFormat::StencilFormat(_)) =>
2239 {
2240 match client {
2241 ClientFormatAny::ClientFormat(ClientFormat::U8) => Ok((gl::RED_INTEGER, gl::UNSIGNED_BYTE)),
2242 ClientFormatAny::ClientFormat(ClientFormat::I8) => Ok((gl::RED_INTEGER, gl::BYTE)),
2243 ClientFormatAny::ClientFormat(ClientFormat::U16) => Ok((gl::RED_INTEGER, gl::UNSIGNED_SHORT)),
2244 ClientFormatAny::ClientFormat(ClientFormat::I16) => Ok((gl::RED_INTEGER, gl::SHORT)),
2245 ClientFormatAny::ClientFormat(ClientFormat::U32) => Ok((gl::RED_INTEGER, gl::UNSIGNED_INT)),
2246 ClientFormatAny::ClientFormat(ClientFormat::I32) => Ok((gl::RED_INTEGER, gl::INT)),
2247 ClientFormatAny::ClientFormat(ClientFormat::F16) => Ok((gl::RED_INTEGER, gl::HALF_FLOAT)),
2248 ClientFormatAny::ClientFormat(ClientFormat::F32) => Ok((gl::RED_INTEGER, gl::FLOAT)),
2249 _ => panic!("Can't upload to a stencil texture with more than one channel")
2250 }
2251 }
2252
2253 TextureFormatRequest::AnyDepthStencil |
2254 TextureFormatRequest::Specific(TextureFormat::DepthStencilFormat(_)) =>
2255 {
2256 unimplemented!();
2257 },
2258 };
2259
2260 if inverted {
2261 value.and_then(|(format, ty)| {
2262 let format = match format {
2263 gl::RGB => gl::BGR,
2264 gl::RGBA => gl::BGRA,
2265 f => return Err(FormatNotSupportedError)
2266 };
2267
2268 Ok((format, ty))
2269 })
2270 } else {
2271 value
2272 }
2273}