beryllium/
surface.rs

1use crate::{
2  error::{get_error, SdlError},
3  init::SdlInit,
4  Sdl,
5};
6use alloc::sync::Arc;
7use core::ptr::NonNull;
8use fermium::prelude::*;
9use pixel_formats::r8g8b8a8_Srgb;
10
11#[repr(C)]
12pub struct Surface {
13  pub(crate) surf: NonNull<SDL_Surface>,
14  pub(crate) parent: Arc<SdlInit>,
15}
16impl Drop for Surface {
17  #[inline]
18  fn drop(&mut self) {
19    unsafe { SDL_FreeSurface(self.surf.as_ptr()) };
20  }
21}
22impl Sdl {
23  #[inline]
24  pub fn create_surface_from(
25    &self, pixels: &[r8g8b8a8_Srgb], width: i32, height: i32,
26  ) -> Result<Surface, SdlError> {
27    if width <= 0
28      || height <= 0
29      || width.checked_mul(height).unwrap_or_default() as usize != pixels.len()
30    {
31      return Err(SdlError::new("illegal input dimensions"));
32    }
33    let depth = 32;
34    let pitch = width * 4;
35    const R_MASK: u32 = unsafe { core::mem::transmute(r8g8b8a8_Srgb { r: 255, g: 0, b: 0, a: 0 }) };
36    const G_MASK: u32 = unsafe { core::mem::transmute(r8g8b8a8_Srgb { g: 255, r: 0, b: 0, a: 0 }) };
37    const B_MASK: u32 = unsafe { core::mem::transmute(r8g8b8a8_Srgb { b: 255, g: 0, r: 0, a: 0 }) };
38    const A_MASK: u32 = unsafe { core::mem::transmute(r8g8b8a8_Srgb { a: 255, g: 0, b: 0, r: 0 }) };
39    let p = unsafe {
40      SDL_CreateRGBSurfaceFrom(
41        pixels.as_ptr() as *mut c_void,
42        width,
43        height,
44        depth,
45        pitch,
46        R_MASK,
47        G_MASK,
48        B_MASK,
49        A_MASK,
50      )
51    };
52    match NonNull::new(p) {
53      Some(surf) => Ok(Surface { surf, parent: self.init.clone() }),
54      None => Err(get_error()),
55    }
56  }
57}