sdl2/
pixels.rs

1use crate::sys;
2use std::convert::TryFrom;
3use std::mem::transmute;
4
5use crate::get_error;
6
7pub struct Palette {
8    raw: *mut sys::SDL_Palette,
9}
10
11impl Palette {
12    #[inline]
13    /// Create a palette structure with the specified number of color entries.
14    ///
15    /// The palette entries are initialized to white.
16    #[doc(alias = "SDL_AllocPalette")]
17    pub fn new(mut capacity: usize) -> Result<Self, String> {
18        use crate::common::*;
19
20        let ncolors = {
21            // This is kind of a hack. We have to cast twice because
22            // ncolors is a c_int, and validate_int only takes a u32.
23            // FIXME: Modify validate_int to make this unnecessary
24            let u32_max = u32::MAX as usize;
25            if capacity > u32_max {
26                capacity = u32_max;
27            }
28
29            match validate_int(capacity as u32, "capacity") {
30                Ok(len) => len,
31                Err(e) => return Err(format!("{}", e)),
32            }
33        };
34
35        let raw = unsafe { sys::SDL_AllocPalette(ncolors) };
36
37        if raw.is_null() {
38            Err(get_error())
39        } else {
40            Ok(Palette { raw })
41        }
42    }
43
44    /// Creates a palette from the provided colors
45    #[doc(alias = "SDL_SetPaletteColors")]
46    pub fn with_colors(colors: &[Color]) -> Result<Self, String> {
47        let pal = Self::new(colors.len())?;
48
49        // Already validated, so don't check again
50        let ncolors = colors.len() as ::libc::c_int;
51
52        let colors = colors.iter().map(|color| color.raw()).collect::<Vec<_>>();
53
54        let result = unsafe { sys::SDL_SetPaletteColors(pal.raw, colors.as_ptr(), 0, ncolors) };
55
56        if result < 0 {
57            Err(get_error())
58        } else {
59            Ok(pal)
60        }
61    }
62
63    pub fn len(&self) -> usize {
64        unsafe { (*self.raw).ncolors as usize }
65    }
66
67    pub fn is_empty(&self) -> bool {
68        self.len() == 0
69    }
70}
71
72impl Drop for Palette {
73    #[doc(alias = "SDL_FreePalette")]
74    fn drop(&mut self) {
75        unsafe {
76            sys::SDL_FreePalette(self.raw);
77        }
78    }
79}
80
81impl_raw_accessors!((Palette, *mut sys::SDL_Palette));
82
83#[test]
84fn create_palette() {
85    let colors: Vec<_> = (0..0xff).map(|u| Color::RGB(u, 0, 0xff - u)).collect();
86
87    let palette = Palette::with_colors(&colors).unwrap();
88
89    assert!(palette.len() == 255);
90}
91
92#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
93pub struct Color {
94    pub r: u8,
95    pub g: u8,
96    pub b: u8,
97    pub a: u8,
98}
99
100impl Color {
101    #[inline]
102    #[allow(non_snake_case)]
103    pub const fn RGB(r: u8, g: u8, b: u8) -> Color {
104        Color { r, g, b, a: 0xff }
105    }
106
107    #[inline]
108    #[allow(non_snake_case)]
109    pub const fn RGBA(r: u8, g: u8, b: u8, a: u8) -> Color {
110        Color { r, g, b, a }
111    }
112
113    #[doc(alias = "SDL_MapRGBA")]
114    pub fn to_u32(self, format: &PixelFormat) -> u32 {
115        unsafe { sys::SDL_MapRGBA(format.raw, self.r, self.g, self.b, self.a) }
116    }
117
118    #[doc(alias = "SDL_GetRGBA")]
119    pub fn from_u32(format: &PixelFormat, pixel: u32) -> Color {
120        let (mut r, mut g, mut b, mut a) = (0, 0, 0, 0);
121
122        unsafe { sys::SDL_GetRGBA(pixel, format.raw, &mut r, &mut g, &mut b, &mut a) };
123        Color::RGBA(r, g, b, a)
124    }
125
126    pub fn invert(self) -> Color {
127        Color::RGBA(255 - self.r, 255 - self.g, 255 - self.b, 255 - self.a)
128    }
129
130    #[inline]
131    pub const fn rgb(self) -> (u8, u8, u8) {
132        (self.r, self.g, self.b)
133    }
134
135    #[inline]
136    pub const fn rgba(self) -> (u8, u8, u8, u8) {
137        (self.r, self.g, self.b, self.a)
138    }
139
140    // Implemented manually and kept private, because reasons
141    #[inline]
142    const fn raw(self) -> sys::SDL_Color {
143        sys::SDL_Color {
144            r: self.r,
145            g: self.g,
146            b: self.b,
147            a: self.a,
148        }
149    }
150
151    pub const WHITE: Color = Color::RGBA(255, 255, 255, 255);
152    pub const BLACK: Color = Color::RGBA(0, 0, 0, 255);
153    pub const GRAY: Color = Color::RGBA(128, 128, 128, 255);
154    pub const GREY: Color = Color::GRAY;
155    pub const RED: Color = Color::RGBA(255, 0, 0, 255);
156    pub const GREEN: Color = Color::RGBA(0, 255, 0, 255);
157    pub const BLUE: Color = Color::RGBA(0, 0, 255, 255);
158    pub const MAGENTA: Color = Color::RGBA(255, 0, 255, 255);
159    pub const YELLOW: Color = Color::RGBA(255, 255, 0, 255);
160    pub const CYAN: Color = Color::RGBA(0, 255, 255, 255);
161}
162
163impl From<Color> for sys::SDL_Color {
164    fn from(val: Color) -> Self {
165        val.raw()
166    }
167}
168
169impl From<sys::SDL_Color> for Color {
170    fn from(raw: sys::SDL_Color) -> Color {
171        Color::RGBA(raw.r, raw.g, raw.b, raw.a)
172    }
173}
174
175impl From<(u8, u8, u8)> for Color {
176    fn from((r, g, b): (u8, u8, u8)) -> Color {
177        Color::RGB(r, g, b)
178    }
179}
180
181impl From<(u8, u8, u8, u8)> for Color {
182    fn from((r, g, b, a): (u8, u8, u8, u8)) -> Color {
183        Color::RGBA(r, g, b, a)
184    }
185}
186
187pub struct PixelMasks {
188    /// Bits per pixel; usually 15, 16, or 32
189    pub bpp: u8,
190    /// The red mask
191    pub rmask: u32,
192    /// The green mask
193    pub gmask: u32,
194    /// The blue mask
195    pub bmask: u32,
196    /// The alpha mask
197    pub amask: u32,
198}
199
200pub struct PixelFormat {
201    raw: *mut sys::SDL_PixelFormat,
202}
203
204impl_raw_accessors!((PixelFormat, *mut sys::SDL_PixelFormat));
205impl_raw_constructor!((PixelFormat, PixelFormat(raw: *mut sys::SDL_PixelFormat)));
206
207#[repr(i32)]
208#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
209pub enum PixelFormatEnum {
210    Unknown = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_UNKNOWN as i32,
211    Index1LSB = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX1LSB as i32,
212    Index1MSB = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX1MSB as i32,
213    Index4LSB = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX4LSB as i32,
214    Index4MSB = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX4MSB as i32,
215    Index8 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX8 as i32,
216    RGB332 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB332 as i32,
217    RGB444 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB444 as i32,
218    RGB555 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB555 as i32,
219    BGR555 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR555 as i32,
220    ARGB4444 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB4444 as i32,
221    RGBA4444 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA4444 as i32,
222    ABGR4444 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR4444 as i32,
223    BGRA4444 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA4444 as i32,
224    ARGB1555 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB1555 as i32,
225    RGBA5551 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA5551 as i32,
226    ABGR1555 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR1555 as i32,
227    BGRA5551 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA5551 as i32,
228    RGB565 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB565 as i32,
229    BGR565 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR565 as i32,
230    RGB24 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB24 as i32,
231    BGR24 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR24 as i32,
232    RGB888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB888 as i32,
233    RGBX8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBX8888 as i32,
234    BGR888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR888 as i32,
235    BGRX8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRX8888 as i32,
236    ARGB8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB8888 as i32,
237    RGBA8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA8888 as i32,
238    ABGR8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR8888 as i32,
239    BGRA8888 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA8888 as i32,
240    ARGB2101010 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB2101010 as i32,
241    YV12 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YV12 as i32,
242    IYUV = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_IYUV as i32,
243    YUY2 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YUY2 as i32,
244    UYVY = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_UYVY as i32,
245    YVYU = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YVYU as i32,
246    NV12 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_NV12 as i32,
247    NV21 = sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_NV21 as i32,
248}
249
250// Endianness-agnostic aliases for 32-bit formats
251#[cfg(target_endian = "big")]
252impl PixelFormatEnum {
253    pub const RGBA32: PixelFormatEnum = PixelFormatEnum::RGBA8888;
254    pub const ARGB32: PixelFormatEnum = PixelFormatEnum::ARGB8888;
255    pub const BGRA32: PixelFormatEnum = PixelFormatEnum::BGRA8888;
256    pub const ABGR32: PixelFormatEnum = PixelFormatEnum::ABGR8888;
257}
258
259#[cfg(target_endian = "little")]
260impl PixelFormatEnum {
261    pub const RGBA32: PixelFormatEnum = PixelFormatEnum::ABGR8888;
262    pub const ARGB32: PixelFormatEnum = PixelFormatEnum::BGRA8888;
263    pub const BGRA32: PixelFormatEnum = PixelFormatEnum::ARGB8888;
264    pub const ABGR32: PixelFormatEnum = PixelFormatEnum::RGBA8888;
265}
266
267impl PixelFormatEnum {
268    #[doc(alias = "SDL_MasksToPixelFormatEnum")]
269    pub fn from_masks(masks: PixelMasks) -> PixelFormatEnum {
270        unsafe {
271            let format = sys::SDL_MasksToPixelFormatEnum(
272                masks.bpp as i32,
273                masks.rmask,
274                masks.gmask,
275                masks.bmask,
276                masks.amask,
277            );
278            PixelFormatEnum::try_from(format as u32).unwrap()
279        }
280    }
281
282    #[doc(alias = "SDL_PixelFormatEnumToMasks")]
283    pub fn into_masks(self) -> Result<PixelMasks, String> {
284        let format: u32 = self as u32;
285        let mut bpp = 0;
286        let mut rmask = 0;
287        let mut gmask = 0;
288        let mut bmask = 0;
289        let mut amask = 0;
290        let result = unsafe {
291            sys::SDL_PixelFormatEnumToMasks(
292                format, &mut bpp, &mut rmask, &mut gmask, &mut bmask, &mut amask,
293            )
294        };
295        if result == sys::SDL_bool::SDL_FALSE {
296            // SDL_FALSE
297            Err(get_error())
298        } else {
299            Ok(PixelMasks {
300                bpp: bpp as u8,
301                rmask,
302                gmask,
303                bmask,
304                amask,
305            })
306        }
307    }
308
309    /// Calculates the total byte size of an image buffer, given its pitch
310    /// and height.
311    pub fn byte_size_from_pitch_and_height(self, pitch: usize, height: usize) -> usize {
312        match self {
313            PixelFormatEnum::YV12 | PixelFormatEnum::IYUV => {
314                // YUV is 4:2:0.
315                // `pitch` is the width of the Y component, and
316                // `height` is the height of the Y component.
317                // U and V have half the width and height of Y.
318                pitch * height + 2 * (pitch / 2 * height / 2)
319            }
320            PixelFormatEnum::NV12 | PixelFormatEnum::NV21 => {
321                // NV12 is 4:2:0.
322                // `pitch` is the width of the Y component, and
323                // `height` is the height of the Y component.
324                // U and V have half the width and height of Y.
325                pitch * height + 2 * (pitch / 2 * height / 2)
326            }
327            _ => pitch * height,
328        }
329    }
330
331    #[allow(clippy::match_same_arms)]
332    pub fn byte_size_of_pixels(self, num_of_pixels: usize) -> usize {
333        match self {
334            PixelFormatEnum::RGB332 => num_of_pixels,
335            PixelFormatEnum::RGB444
336            | PixelFormatEnum::RGB555
337            | PixelFormatEnum::BGR555
338            | PixelFormatEnum::ARGB4444
339            | PixelFormatEnum::RGBA4444
340            | PixelFormatEnum::ABGR4444
341            | PixelFormatEnum::BGRA4444
342            | PixelFormatEnum::ARGB1555
343            | PixelFormatEnum::RGBA5551
344            | PixelFormatEnum::ABGR1555
345            | PixelFormatEnum::BGRA5551
346            | PixelFormatEnum::RGB565
347            | PixelFormatEnum::BGR565 => num_of_pixels * 2,
348            PixelFormatEnum::RGB24 | PixelFormatEnum::BGR24 => num_of_pixels * 3,
349            PixelFormatEnum::RGB888
350            | PixelFormatEnum::RGBX8888
351            | PixelFormatEnum::BGR888
352            | PixelFormatEnum::BGRX8888
353            | PixelFormatEnum::ARGB8888
354            | PixelFormatEnum::RGBA8888
355            | PixelFormatEnum::ABGR8888
356            | PixelFormatEnum::BGRA8888
357            | PixelFormatEnum::ARGB2101010 => num_of_pixels * 4,
358            // YUV formats
359            // rounding error handled by image size constraints
360            PixelFormatEnum::YV12 | PixelFormatEnum::IYUV => num_of_pixels / 2 * 3,
361            PixelFormatEnum::YUY2 | PixelFormatEnum::UYVY | PixelFormatEnum::YVYU => {
362                num_of_pixels * 2
363            }
364            // rounding error handled by image size constraints
365            PixelFormatEnum::NV12 | PixelFormatEnum::NV21 => num_of_pixels / 2 * 3,
366            // Unsupported formats
367            PixelFormatEnum::Index8 => num_of_pixels,
368            PixelFormatEnum::Unknown
369            | PixelFormatEnum::Index1LSB
370            | PixelFormatEnum::Index1MSB
371            | PixelFormatEnum::Index4LSB
372            | PixelFormatEnum::Index4MSB => panic!("not supported format: {:?}", self),
373        }
374    }
375
376    #[allow(clippy::match_same_arms)]
377    pub fn byte_size_per_pixel(self) -> usize {
378        match self {
379            PixelFormatEnum::RGB332 => 1,
380            PixelFormatEnum::RGB444
381            | PixelFormatEnum::RGB555
382            | PixelFormatEnum::BGR555
383            | PixelFormatEnum::ARGB4444
384            | PixelFormatEnum::RGBA4444
385            | PixelFormatEnum::ABGR4444
386            | PixelFormatEnum::BGRA4444
387            | PixelFormatEnum::ARGB1555
388            | PixelFormatEnum::RGBA5551
389            | PixelFormatEnum::ABGR1555
390            | PixelFormatEnum::BGRA5551
391            | PixelFormatEnum::RGB565
392            | PixelFormatEnum::BGR565 => 2,
393            PixelFormatEnum::RGB24 | PixelFormatEnum::BGR24 => 3,
394            PixelFormatEnum::RGB888
395            | PixelFormatEnum::RGBX8888
396            | PixelFormatEnum::BGR888
397            | PixelFormatEnum::BGRX8888
398            | PixelFormatEnum::ARGB8888
399            | PixelFormatEnum::RGBA8888
400            | PixelFormatEnum::ABGR8888
401            | PixelFormatEnum::BGRA8888
402            | PixelFormatEnum::ARGB2101010 => 4,
403            // YUV formats
404            PixelFormatEnum::YV12 | PixelFormatEnum::IYUV => 1,
405            PixelFormatEnum::YUY2 | PixelFormatEnum::UYVY | PixelFormatEnum::YVYU => 2,
406            PixelFormatEnum::NV12 | PixelFormatEnum::NV21 => 1,
407            // Unsupported formats
408            PixelFormatEnum::Index8 => 1,
409            PixelFormatEnum::Unknown
410            | PixelFormatEnum::Index1LSB
411            | PixelFormatEnum::Index1MSB
412            | PixelFormatEnum::Index4LSB
413            | PixelFormatEnum::Index4MSB => panic!("not supported format: {:?}", self),
414        }
415    }
416
417    pub fn supports_alpha(self) -> bool {
418        use crate::pixels::PixelFormatEnum::*;
419        matches!(
420            self,
421            ARGB4444
422                | ARGB1555
423                | ARGB8888
424                | ARGB2101010
425                | ABGR4444
426                | ABGR1555
427                | ABGR8888
428                | BGRA4444
429                | BGRA5551
430                | BGRA8888
431                | RGBA4444
432                | RGBA5551
433                | RGBA8888
434        )
435    }
436}
437
438impl From<PixelFormat> for PixelFormatEnum {
439    fn from(pf: PixelFormat) -> PixelFormatEnum {
440        unsafe {
441            let sdl_pf = *pf.raw;
442            match PixelFormatEnum::try_from(sdl_pf.format) {
443                Ok(pfe) => pfe,
444                Err(()) => panic!("Unknown pixel format: {:?}", sdl_pf.format),
445            }
446        }
447    }
448}
449
450impl TryFrom<u32> for PixelFormatEnum {
451    type Error = ();
452
453    fn try_from(n: u32) -> Result<Self, Self::Error> {
454        use self::PixelFormatEnum::*;
455
456        Ok(match unsafe { transmute(n) } {
457            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_UNKNOWN => Unknown,
458            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX1LSB => Index1LSB,
459            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX1MSB => Index1MSB,
460            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX4LSB => Index4LSB,
461            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX4MSB => Index4MSB,
462            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_INDEX8 => Index8,
463            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB332 => RGB332,
464            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB444 => RGB444,
465            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB555 => RGB555,
466            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR555 => BGR555,
467            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB4444 => ARGB4444,
468            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA4444 => RGBA4444,
469            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR4444 => ABGR4444,
470            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA4444 => BGRA4444,
471            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB1555 => ARGB1555,
472            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA5551 => RGBA5551,
473            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR1555 => ABGR1555,
474            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA5551 => BGRA5551,
475            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB565 => RGB565,
476            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR565 => BGR565,
477            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB24 => RGB24,
478            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR24 => BGR24,
479            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGB888 => RGB888,
480            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBX8888 => RGBX8888,
481            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGR888 => BGR888,
482            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRX8888 => BGRX8888,
483            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB8888 => ARGB8888,
484            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_RGBA8888 => RGBA8888,
485            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ABGR8888 => ABGR8888,
486            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_BGRA8888 => BGRA8888,
487            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_ARGB2101010 => ARGB2101010,
488            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YV12 => YV12,
489            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_IYUV => IYUV,
490            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YUY2 => YUY2,
491            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_UYVY => UYVY,
492            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_YVYU => YVYU,
493            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_NV12 => NV12,
494            sys::SDL_PixelFormatEnum::SDL_PIXELFORMAT_NV21 => NV21,
495            _ => return Err(()),
496        })
497    }
498}
499
500impl TryFrom<PixelFormatEnum> for PixelFormat {
501    type Error = String;
502
503    #[doc(alias = "SDL_AllocFormat")]
504    fn try_from(pfe: PixelFormatEnum) -> Result<Self, Self::Error> {
505        unsafe {
506            let pf_ptr = sys::SDL_AllocFormat(pfe as u32);
507            if pf_ptr.is_null() {
508                Err(get_error())
509            } else {
510                Ok(PixelFormat::from_ll(pf_ptr))
511            }
512        }
513    }
514}
515
516// Just test a round-trip conversion from PixelFormat to
517// PixelFormatEnum and back.
518#[test]
519fn test_pixel_format_enum() {
520    let pixel_formats = vec![
521        PixelFormatEnum::RGB332,
522        PixelFormatEnum::RGB444,
523        PixelFormatEnum::RGB555,
524        PixelFormatEnum::BGR555,
525        PixelFormatEnum::ARGB4444,
526        PixelFormatEnum::RGBA4444,
527        PixelFormatEnum::ABGR4444,
528        PixelFormatEnum::BGRA4444,
529        PixelFormatEnum::ARGB1555,
530        PixelFormatEnum::RGBA5551,
531        PixelFormatEnum::ABGR1555,
532        PixelFormatEnum::BGRA5551,
533        PixelFormatEnum::RGB565,
534        PixelFormatEnum::BGR565,
535        PixelFormatEnum::RGB24,
536        PixelFormatEnum::BGR24,
537        PixelFormatEnum::RGB888,
538        PixelFormatEnum::RGBX8888,
539        PixelFormatEnum::BGR888,
540        PixelFormatEnum::BGRX8888,
541        PixelFormatEnum::ARGB8888,
542        PixelFormatEnum::RGBA8888,
543        PixelFormatEnum::ABGR8888,
544        PixelFormatEnum::BGRA8888,
545        PixelFormatEnum::ARGB2101010,
546        PixelFormatEnum::YV12,
547        PixelFormatEnum::IYUV,
548        PixelFormatEnum::YUY2,
549        PixelFormatEnum::UYVY,
550        PixelFormatEnum::YVYU,
551        PixelFormatEnum::NV12,
552        PixelFormatEnum::NV21,
553        PixelFormatEnum::Index8,
554        // These don't seem to be supported;
555        // the round-trip
556        //PixelFormatEnum::Unknown, PixelFormatEnum::Index1LSB,
557        //PixelFormatEnum::Index1MSB, PixelFormatEnum::Index4LSB,
558        //PixelFormatEnum::Index4MSB
559    ];
560
561    let _sdl_context = crate::sdl::init().unwrap();
562    for format in pixel_formats {
563        // If we don't support making a surface of a specific format,
564        // that's fine, just keep going the best we can.
565        if let Ok(surf) = super::surface::Surface::new(1, 1, format) {
566            let surf_format = surf.pixel_format();
567            assert_eq!(PixelFormatEnum::from(surf_format), format);
568        }
569    }
570}