mirror of
https://github.com/encounter/rust-sdl2.git
synced 2026-07-10 21:18:41 -07:00
Make SurfaceRef 0 bytes
In PR #435, I made `SDL_Surface` a DST. This is actually invalid because the resulting pointer `*mut SDL_Surface` became a fat pointer (i.e. 16 bytes instead of 8 on 64-bit targets). Unsized types (as opposed to dynamically sized types) in Rust aren't currently possible. To prevent partial swapping and memory corruption with `std::mem::swap()`, the structure is 0 bytes. This shouldn't cause any problems, as `SurfaceRef` is always a reference to SDL-owned memory.
This commit is contained in:
@@ -33,10 +33,7 @@ pub struct SDL_Surface {
|
||||
pub lock_data: *mut c_void,
|
||||
pub clip_rect: SDL_Rect,
|
||||
pub map: *mut SDL_BlitMap,
|
||||
pub refcount: c_int,
|
||||
|
||||
// Make the type a DST. The size of the struct could change in later SDL2 releases.
|
||||
pub _unsized: [()]
|
||||
pub refcount: c_int
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
+33
-20
@@ -31,7 +31,17 @@ impl<'a> Drop for Surface<'a> {
|
||||
/// This type is used whenever Surfaces need to be borrowed from the SDL library, without concern
|
||||
/// for freeing the Surface.
|
||||
pub struct SurfaceRef {
|
||||
raw: ll::SDL_Surface
|
||||
// It's nothing! (it gets transmuted to SDL_Surface later).
|
||||
// The empty private field is need to a) make `std::mem::swap()` copy nothing instead of
|
||||
// clobbering two surfaces (SDL_Surface's size could change in the future),
|
||||
// and b) prevent user initialization of this type.
|
||||
_raw: ()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_surface_ref_size() {
|
||||
// `SurfaceRef` must be 0 bytes.
|
||||
assert_eq!(::std::mem::size_of::<SurfaceRef>(), 0);
|
||||
}
|
||||
|
||||
impl<'a> Deref for Surface<'a> {
|
||||
@@ -105,9 +115,7 @@ impl<'a> Surface<'a> {
|
||||
let raw = ll::SDL_CreateRGBSurface(0, width as c_int, height as c_int,
|
||||
masks.bpp as c_int, masks.rmask, masks.gmask, masks.bmask, masks.amask);
|
||||
|
||||
// As of writing, is_null() doesn't work on pointers with unsized types.
|
||||
|
||||
if (raw as *mut ()).is_null() {
|
||||
if raw.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
Ok(Surface {
|
||||
@@ -137,7 +145,7 @@ impl<'a> Surface<'a> {
|
||||
data.as_mut_ptr() as *mut _, width as c_int, height as c_int,
|
||||
masks.bpp as c_int, pitch as c_int, masks.rmask, masks.gmask, masks.bmask, masks.amask);
|
||||
|
||||
if (raw as *mut ()).is_null() {
|
||||
if raw.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
Ok(Surface {
|
||||
@@ -154,7 +162,7 @@ impl<'a> Surface<'a> {
|
||||
ll::SDL_LoadBMP_RW(rwops.raw(), 0)
|
||||
};
|
||||
|
||||
if (raw as *mut ()).is_null() {
|
||||
if raw.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
Ok(Surface {
|
||||
@@ -186,16 +194,21 @@ impl SurfaceRef {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn raw_ref(&self) -> &ll::SDL_Surface {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> u32 {
|
||||
self.raw.w as u32
|
||||
self.raw_ref().w as u32
|
||||
}
|
||||
|
||||
pub fn get_height(&self) -> u32 {
|
||||
self.raw.h as u32
|
||||
self.raw_ref().h as u32
|
||||
}
|
||||
|
||||
pub fn get_pitch(&self) -> u32 {
|
||||
self.raw.pitch as u32
|
||||
self.raw_ref().pitch as u32
|
||||
}
|
||||
|
||||
pub fn get_size(&self) -> (u32, u32) {
|
||||
@@ -208,7 +221,7 @@ impl SurfaceRef {
|
||||
|
||||
pub fn get_pixel_format(&self) -> pixels::PixelFormat {
|
||||
unsafe {
|
||||
pixels::PixelFormat::from_ll(self.raw.format)
|
||||
pixels::PixelFormat::from_ll(self.raw_ref().format)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +230,8 @@ impl SurfaceRef {
|
||||
unsafe {
|
||||
if ll::SDL_LockSurface(self.raw()) != 0 { panic!("could not lock surface"); }
|
||||
|
||||
let raw_pixels = self.raw.pixels as *const _;
|
||||
let len = self.raw.pitch as usize * (self.raw.h as usize);
|
||||
let raw_pixels = self.raw_ref().pixels as *const _;
|
||||
let len = self.raw_ref().pitch as usize * (self.raw_ref().h as usize);
|
||||
let pixels = ::std::slice::from_raw_parts(raw_pixels, len);
|
||||
let rv = f(pixels);
|
||||
ll::SDL_UnlockSurface(self.raw());
|
||||
@@ -231,8 +244,8 @@ impl SurfaceRef {
|
||||
unsafe {
|
||||
if ll::SDL_LockSurface(self.raw()) != 0 { panic!("could not lock surface"); }
|
||||
|
||||
let raw_pixels = self.raw.pixels as *mut _;
|
||||
let len = self.raw.pitch as usize * (self.raw.h as usize);
|
||||
let raw_pixels = self.raw_ref().pixels as *mut _;
|
||||
let len = self.raw_ref().pitch as usize * (self.raw_ref().h as usize);
|
||||
let pixels = ::std::slice::from_raw_parts_mut(raw_pixels, len);
|
||||
let rv = f(pixels);
|
||||
ll::SDL_UnlockSurface(self.raw());
|
||||
@@ -247,8 +260,8 @@ impl SurfaceRef {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let raw_pixels = self.raw.pixels as *const _;
|
||||
let len = self.raw.pitch as usize * (self.raw.h as usize);
|
||||
let raw_pixels = self.raw_ref().pixels as *const _;
|
||||
let len = self.raw_ref().pitch as usize * (self.raw_ref().h as usize);
|
||||
|
||||
Some(::std::slice::from_raw_parts(raw_pixels, len))
|
||||
}
|
||||
@@ -262,8 +275,8 @@ impl SurfaceRef {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let raw_pixels = self.raw.pixels as *mut _;
|
||||
let len = self.raw.pitch as usize * (self.raw.h as usize);
|
||||
let raw_pixels = self.raw_ref().pixels as *mut _;
|
||||
let len = self.raw_ref().pitch as usize * (self.raw_ref().h as usize);
|
||||
|
||||
Some(::std::slice::from_raw_parts_mut(raw_pixels, len))
|
||||
}
|
||||
@@ -273,7 +286,7 @@ impl SurfaceRef {
|
||||
/// Returns true if the Surface needs to be locked before accessing the Surface pixels.
|
||||
pub fn must_lock(&self) -> bool {
|
||||
// Implements the SDL_MUSTLOCK macro.
|
||||
(self.raw.flags & ll::SDL_RLEACCEL) != 0
|
||||
(self.raw_ref().flags & ll::SDL_RLEACCEL) != 0
|
||||
}
|
||||
|
||||
pub fn save_bmp_rw(&self, rwops: &mut RWops) -> SdlResult<()> {
|
||||
@@ -481,7 +494,7 @@ impl SurfaceRef {
|
||||
// SDL_ConvertSurface takes a flag as the last parameter, which should be 0 by the docs.
|
||||
let surface_ptr = unsafe { ll::SDL_ConvertSurface(self.raw(), format.raw(), 0u32) };
|
||||
|
||||
if (surface_ptr as *mut ()).is_null() {
|
||||
if surface_ptr.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
unsafe { Ok(Surface::from_ll(surface_ptr)) }
|
||||
|
||||
+2
-2
@@ -819,7 +819,7 @@ impl<'a> WindowProperties<'a> {
|
||||
pub fn get_surface(&self) -> SdlResult<&SurfaceRef> {
|
||||
let raw = unsafe { ll::SDL_GetWindowSurface(self.raw) };
|
||||
|
||||
if (raw as *mut ()).is_null() {
|
||||
if raw.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
unsafe { Ok(SurfaceRef::from_ll(raw)) }
|
||||
@@ -829,7 +829,7 @@ impl<'a> WindowProperties<'a> {
|
||||
pub fn get_surface_mut(&mut self) -> SdlResult<&mut SurfaceRef> {
|
||||
let raw = unsafe { ll::SDL_GetWindowSurface(self.raw) };
|
||||
|
||||
if (raw as *mut ()).is_null() {
|
||||
if raw.is_null() {
|
||||
Err(get_error())
|
||||
} else {
|
||||
unsafe { Ok(SurfaceRef::from_ll_mut(raw)) }
|
||||
|
||||
Reference in New Issue
Block a user