sdl/
video.rs

1use libc::{c_float, c_int};
2use std::ffi::CString;
3use std::mem;
4use std::path::Path;
5use std::ptr;
6use std::slice;
7
8use get_error;
9use Rect;
10
11pub use self::Color::{RGB, RGBA};
12
13pub mod ll {
14    #![allow(non_camel_case_types)]
15
16    use std::ffi::c_char;
17
18    use Rect;
19
20    use libc::{c_float, c_int, c_uchar, c_uint, c_void, uint16_t, uint8_t};
21    use libc::{int32_t, uint32_t};
22
23    pub type SDL_Rect = Rect;
24
25    #[repr(C)]
26    #[derive(Copy, Clone)]
27    pub struct SDL_RWops {
28        pub seek: *mut uint8_t,
29        pub read: *mut uint8_t,
30        pub write: *mut uint8_t,
31        pub close: *mut uint8_t,
32        pub _type: uint32_t,
33        _hidden: [c_uchar; 24],
34    }
35
36    #[repr(C)]
37    #[derive(Copy, Clone)]
38    pub struct SDL_Surface {
39        pub flags: uint32_t,
40        pub format: *mut SDL_PixelFormat,
41        pub w: c_int,
42        pub h: c_int,
43        pub pitch: uint16_t,
44        pub pixels: *mut c_void,
45        pub offset: c_int,
46        pub hwdata: *mut c_void,
47        pub clip_rect: SDL_Rect,
48        pub unused1: uint32_t,
49        pub locked: uint32_t,
50        pub map: *mut c_void,
51        pub format_version: c_uint,
52        pub refcount: c_int,
53    }
54
55    #[repr(C)]
56    #[derive(Copy, Clone)]
57    pub struct SDL_Color {
58        pub r: uint8_t,
59        pub g: uint8_t,
60        pub b: uint8_t,
61        pub unused: uint8_t,
62    }
63
64    #[repr(C)]
65    #[derive(Copy, Clone)]
66    pub struct SDL_Palette {
67        pub ncolors: c_int,
68        pub colors: *mut SDL_Color,
69    }
70
71    #[allow(non_snake_case)]
72    #[repr(C)]
73    #[derive(Copy, Clone)]
74    pub struct SDL_PixelFormat {
75        pub palette: *mut SDL_Palette,
76        pub BitsPerPixel: uint8_t,
77        pub BytesPerPixel: uint8_t,
78        pub Rloss: uint8_t,
79        pub Gloss: uint8_t,
80        pub Bloss: uint8_t,
81        pub Aloss: uint8_t,
82        pub Rshift: uint8_t,
83        pub Gshift: uint8_t,
84        pub Bshift: uint8_t,
85        pub Ashift: uint8_t,
86        pub Rmask: uint32_t,
87        pub Gmask: uint32_t,
88        pub Bmask: uint32_t,
89        pub Amask: uint32_t,
90        pub colorkey: uint32_t,
91        pub alpha: uint8_t,
92    }
93
94    #[repr(C)]
95    #[derive(Copy, Clone)]
96    pub struct SDL_VideoInfo {
97        pub flags: uint32_t, // actually a set of packed fields
98        pub video_mem: uint32_t,
99        pub vfmt: *mut SDL_PixelFormat,
100        pub current_w: c_int,
101        pub current_h: c_int,
102    }
103
104    extern "C" {
105        pub fn SDL_CreateRGBSurface(
106            flags: uint32_t,
107            width: c_int,
108            height: c_int,
109            depth: c_int,
110            Rmask: uint32_t,
111            Gmask: uint32_t,
112            Bmask: uint32_t,
113            Amask: uint32_t,
114        ) -> *mut SDL_Surface;
115        pub fn SDL_CreateRGBSurfaceFrom(
116            pixels: *mut c_void,
117            width: c_int,
118            height: c_int,
119            depth: c_int,
120            pitch: c_int,
121            Rmask: uint32_t,
122            Gmask: uint32_t,
123            Bmask: uint32_t,
124            Amask: uint32_t,
125        ) -> *mut SDL_Surface;
126        pub fn SDL_FreeSurface(surface: *mut SDL_Surface);
127        pub fn SDL_MapRGB(
128            format: *const SDL_PixelFormat,
129            r: uint8_t,
130            g: uint8_t,
131            b: uint8_t,
132        ) -> uint32_t;
133        pub fn SDL_MapRGBA(
134            format: *const SDL_PixelFormat,
135            r: uint8_t,
136            g: uint8_t,
137            b: uint8_t,
138            a: uint8_t,
139        ) -> uint32_t;
140        pub fn SDL_GetRGB(
141            pixel: uint32_t,
142            fmt: *const SDL_PixelFormat,
143            r: *mut uint8_t,
144            g: *mut uint8_t,
145            b: *mut uint8_t,
146        );
147        pub fn SDL_GetRGBA(
148            pixel: uint32_t,
149            fmt: *const SDL_PixelFormat,
150            r: *mut uint8_t,
151            g: *mut uint8_t,
152            b: *mut uint8_t,
153            a: *mut uint8_t,
154        );
155        pub fn SDL_SetVideoMode(
156            width: c_int,
157            height: c_int,
158            bpp: c_int,
159            flags: uint32_t,
160        ) -> *mut SDL_Surface;
161        pub fn SDL_VideoModeOK(width: c_int, height: c_int, bpp: c_int, flags: uint32_t) -> c_int;
162        pub fn SDL_GetVideoInfo() -> *const SDL_VideoInfo;
163        pub fn SDL_GetVideoSurface() -> *mut SDL_Surface;
164        pub fn SDL_UpdateRect(
165            screen: *mut SDL_Surface,
166            x: int32_t,
167            y: int32_t,
168            w: uint32_t,
169            h: uint32_t,
170        );
171        pub fn SDL_UpdateRects(screen: *mut SDL_Surface, numrects: c_int, rects: *mut SDL_Rect);
172        pub fn SDL_SetColors(
173            surface: *mut SDL_Surface,
174            colors: *mut SDL_Color,
175            firstcolor: c_int,
176            ncolors: c_int,
177        ) -> c_int;
178        pub fn SDL_SetPalette(
179            surface: *mut SDL_Surface,
180            flags: c_int,
181            colors: *mut SDL_Color,
182            firstcolor: c_int,
183            ncolors: c_int,
184        ) -> c_int;
185        pub fn SDL_LockSurface(surface: *mut SDL_Surface) -> c_int;
186        pub fn SDL_UnlockSurface(surface: *mut SDL_Surface);
187        pub fn SDL_Flip(screen: *mut SDL_Surface) -> c_int;
188        pub fn SDL_ConvertSurface(
189            src: *mut SDL_Surface,
190            fmt: *mut SDL_PixelFormat,
191            flags: uint32_t,
192        ) -> *mut SDL_Surface;
193        pub fn SDL_DisplayFormat(surface: *mut SDL_Surface) -> *mut SDL_Surface;
194        pub fn SDL_DisplayFormatAlpha(surface: *mut SDL_Surface) -> *mut SDL_Surface;
195        pub fn SDL_SetColorKey(surface: *mut SDL_Surface, flag: uint32_t, key: uint32_t) -> c_int;
196        pub fn SDL_SetAlpha(surface: *mut SDL_Surface, flag: uint32_t, alpha: uint8_t) -> c_int;
197        pub fn SDL_SetClipRect(surface: *mut SDL_Surface, rect: *const SDL_Rect);
198        pub fn SDL_UpperBlit(
199            src: *mut SDL_Surface,
200            srcrect: *mut SDL_Rect,
201            dst: *mut SDL_Surface,
202            dstrect: *mut SDL_Rect,
203        ) -> c_int;
204        pub fn SDL_FillRect(
205            dst: *mut SDL_Surface,
206            dstrect: *mut SDL_Rect,
207            color: uint32_t,
208        ) -> c_int;
209        pub fn SDL_SetGamma(r: c_float, g: c_float, b: c_float) -> c_int;
210        pub fn SDL_SetGammaRamp(
211            r: *const uint16_t,
212            g: *const uint16_t,
213            b: *const uint16_t,
214        ) -> c_int;
215        pub fn SDL_GetGammaRamp(r: *mut uint16_t, g: *mut uint16_t, b: *mut uint16_t) -> c_int;
216        pub fn SDL_RWFromFile(file: *const c_char, mode: *const c_char) -> *mut SDL_RWops;
217        pub fn SDL_LoadBMP_RW(src: *mut SDL_RWops, freesrc: c_int) -> *mut SDL_Surface;
218        pub fn SDL_SaveBMP_RW(
219            surface: *mut SDL_Surface,
220            dst: *mut SDL_RWops,
221            freedst: c_int,
222        ) -> c_int;
223        pub fn SDL_GL_SwapBuffers();
224    }
225}
226
227#[derive(PartialEq)]
228pub struct Surface {
229    pub raw: *mut ll::SDL_Surface,
230    pub owned: bool,
231}
232
233fn wrap_surface(raw: *mut ll::SDL_Surface, owned: bool) -> Surface {
234    Surface {
235        raw: raw,
236        owned: owned,
237    }
238}
239
240impl Drop for Surface {
241    fn drop(&mut self) {
242        unsafe {
243            if self.owned {
244                ll::SDL_FreeSurface(self.raw);
245            }
246        }
247    }
248}
249
250#[derive(PartialEq, Copy, Clone)]
251pub struct Palette {
252    pub raw: *mut ll::SDL_Palette,
253}
254
255fn wrap_palette(palette: *mut ll::SDL_Palette) -> Option<Palette> {
256    if palette.is_null() {
257        None
258    } else {
259        Some(Palette { raw: palette })
260    }
261}
262
263pub type PaletteColors<'a> = slice::Iter<'a, ll::SDL_Color>;
264
265impl Palette {
266    pub fn colors<'a>(&'a self) -> PaletteColors<'a> {
267        let colors = unsafe { (*self.raw).colors } as *const ll::SDL_Color;
268        let ncolors = unsafe { (*self.raw).ncolors } as usize;
269        let colors: &'a [ll::SDL_Color] =
270            unsafe { mem::transmute(slice::from_raw_parts(&colors, ncolors)) };
271        colors.iter()
272    }
273}
274
275#[derive(PartialEq, Copy, Clone)]
276pub struct PixelFormat {
277    pub palette: Option<Palette>,
278    pub bpp: u8,
279    pub r_loss: u8,
280    pub g_loss: u8,
281    pub b_loss: u8,
282    pub a_loss: u8,
283    pub r_shift: u8,
284    pub g_shift: u8,
285    pub b_shift: u8,
286    pub a_shift: u8,
287    pub r_mask: u32,
288    pub g_mask: u32,
289    pub b_mask: u32,
290    pub a_mask: u32,
291    pub color_key: u32,
292    pub alpha: u8,
293}
294
295fn wrap_pixel_format(raw: *mut ll::SDL_PixelFormat) -> PixelFormat {
296    let fmt = &unsafe { *raw };
297    PixelFormat {
298        palette: wrap_palette(fmt.palette),
299        bpp: fmt.BitsPerPixel,
300        r_loss: fmt.Rloss,
301        g_loss: fmt.Gloss,
302        b_loss: fmt.Bloss,
303        a_loss: fmt.Aloss,
304        r_shift: fmt.Rshift,
305        g_shift: fmt.Gshift,
306        b_shift: fmt.Bshift,
307        a_shift: fmt.Ashift,
308        r_mask: fmt.Rmask,
309        g_mask: fmt.Gmask,
310        b_mask: fmt.Bmask,
311        a_mask: fmt.Amask,
312        color_key: fmt.colorkey,
313        alpha: fmt.alpha,
314    }
315}
316
317fn unwrap_pixel_format(fmt: &PixelFormat) -> ll::SDL_PixelFormat {
318    ll::SDL_PixelFormat {
319        palette: match fmt.palette {
320            None => ptr::null_mut(),
321            Some(palette) => palette.raw,
322        },
323        BitsPerPixel: fmt.bpp,
324        BytesPerPixel: fmt.bpp / 8,
325        Rloss: fmt.r_loss,
326        Gloss: fmt.g_loss,
327        Bloss: fmt.b_loss,
328        Aloss: fmt.a_loss,
329        Rshift: fmt.r_shift,
330        Gshift: fmt.g_shift,
331        Bshift: fmt.b_shift,
332        Ashift: fmt.a_shift,
333        Rmask: fmt.r_mask,
334        Gmask: fmt.g_mask,
335        Bmask: fmt.b_mask,
336        Amask: fmt.a_mask,
337        colorkey: fmt.color_key,
338        alpha: fmt.alpha,
339    }
340}
341
342#[derive(PartialEq, Eq, Copy, Clone)]
343pub enum Color {
344    RGB(u8, u8, u8),
345    RGBA(u8, u8, u8, u8),
346}
347
348impl ::rand::Rand for Color {
349    fn rand<R: ::rand::Rng>(rng: &mut R) -> Color {
350        if rng.gen() {
351            RGBA(rng.gen(), rng.gen(), rng.gen(), rng.gen())
352        } else {
353            RGB(rng.gen(), rng.gen(), rng.gen())
354        }
355    }
356}
357
358impl Color {
359    pub fn from_mapped(bit: u32, fmt: *const ll::SDL_PixelFormat) -> Color {
360        let mut r = 0;
361        let mut g = 0;
362        let mut b = 0;
363        let mut a = 0;
364
365        unsafe { ll::SDL_GetRGBA(bit, fmt, &mut r, &mut g, &mut b, &mut a) }
366
367        RGBA(r, g, b, a)
368    }
369
370    pub fn to_mapped(&self, fmt: *const ll::SDL_PixelFormat) -> u32 {
371        match *self {
372            RGB(r, g, b) => unsafe { ll::SDL_MapRGB(fmt, r, g, b) },
373            RGBA(r, g, b, a) => unsafe { ll::SDL_MapRGBA(fmt, r, g, b, a) },
374        }
375    }
376
377    pub fn from_struct(c: &ll::SDL_Color) -> Color {
378        RGB(c.r, c.g, c.b)
379    }
380
381    pub fn to_struct(&self) -> ll::SDL_Color {
382        match *self {
383            RGB(r, g, b) => ll::SDL_Color {
384                r: r,
385                g: g,
386                b: b,
387                unused: 0,
388            },
389            RGBA(r, g, b, _) => ll::SDL_Color {
390                r: r,
391                g: g,
392                b: b,
393                unused: 0,
394            },
395        }
396    }
397}
398
399#[derive(PartialEq, Eq, Copy, Clone)]
400pub enum SurfaceFlag {
401    SWSurface = 0x00000000,
402    HWSurface = 0x00000001,
403    AsyncBlit = 0x00000004,
404    SrcColorKey = 0x00001000,
405    SrcAlpha = 0x00010000,
406    RLEAccel = 0x00004000,
407}
408
409#[derive(PartialEq, Eq, Copy, Clone)]
410pub enum VideoFlag {
411    AnyFormat = 0x10000000,
412    HWPalette = 0x20000000,
413    DoubleBuf = 0x40000000,
414    Fullscreen = 0x80000000usize as isize, // 0x80000000 > INT_MAX on i686
415    OpenGL = 0x00000002,
416    OpenGLBlit = 0x0000000A,
417    Resizable = 0x00000010,
418    NoFrame = 0x00000020,
419}
420
421pub fn set_video_mode(
422    w: isize,
423    h: isize,
424    bpp: isize,
425    surface_flags: &[SurfaceFlag],
426    video_flags: &[VideoFlag],
427) -> Result<Surface, String> {
428    let flags = surface_flags
429        .iter()
430        .fold(0u32, |flags, &flag| flags | flag as u32);
431    let flags = video_flags
432        .iter()
433        .fold(flags, |flags, &flag| flags | flag as u32);
434
435    unsafe {
436        let raw = ll::SDL_SetVideoMode(w as c_int, h as c_int, bpp as c_int, flags);
437
438        if raw.is_null() {
439            Err(get_error())
440        } else {
441            Ok(wrap_surface(raw, false))
442        }
443    }
444}
445
446pub fn is_video_mode_ok(
447    w: isize,
448    h: isize,
449    bpp: isize,
450    surface_flags: &[SurfaceFlag],
451    video_flags: &[VideoFlag],
452) -> Option<isize> {
453    let flags = surface_flags
454        .iter()
455        .fold(0u32, |flags, &flag| flags | flag as u32);
456    let flags = video_flags
457        .iter()
458        .fold(flags, |flags, &flag| flags | flag as u32);
459
460    unsafe {
461        let bpp = ll::SDL_VideoModeOK(w as c_int, h as c_int, bpp as c_int, flags);
462
463        if bpp == 0 {
464            None
465        } else {
466            Some(bpp as isize)
467        }
468    }
469}
470
471#[derive(PartialEq, Eq, Copy, Clone)]
472pub enum VideoInfoFlag {
473    HWAvailable = 0x00000001,
474    WMAvailable = 0x00000002,
475    BlitHW = 0x00000200,
476    BlitHWColorkey = 0x00000400,
477    BlitHWAlpha = 0x00000800,
478    BlitSW = 0x00001000,
479    BlitSWColorkey = 0x00002000,
480    BlitSWAlpha = 0x00004000,
481    BlitFill = 0x00008000,
482}
483
484pub struct VideoInfo {
485    pub flags: Vec<VideoInfoFlag>,
486    pub width: isize,
487    pub height: isize,
488    pub format: PixelFormat,
489}
490
491fn wrap_video_info_flags(bitflags: u32) -> Vec<VideoInfoFlag> {
492    let flags = [
493        VideoInfoFlag::HWAvailable,
494        VideoInfoFlag::WMAvailable,
495        VideoInfoFlag::BlitHW,
496        VideoInfoFlag::BlitHWColorkey,
497        VideoInfoFlag::BlitHWAlpha,
498        VideoInfoFlag::BlitSW,
499        VideoInfoFlag::BlitSWColorkey,
500        VideoInfoFlag::BlitSWAlpha,
501        VideoInfoFlag::BlitFill,
502    ];
503
504    flags
505        .iter()
506        .filter_map(|&flag| {
507            if bitflags & (flag as u32) != 0 {
508                Some(flag)
509            } else {
510                None
511            }
512        })
513        .collect()
514}
515
516pub fn get_video_info() -> VideoInfo {
517    let raw = unsafe { ll::SDL_GetVideoInfo() };
518    VideoInfo {
519        flags: wrap_video_info_flags(unsafe { (*raw).flags } as u32),
520        width: unsafe { (*raw).current_w } as isize,
521        height: unsafe { (*raw).current_h } as isize,
522        format: wrap_pixel_format(unsafe { (*raw).vfmt }),
523    }
524}
525
526#[derive(Copy, Clone)]
527pub enum PaletteType {
528    Logical = 1,
529    Physical,
530}
531
532pub fn get_video_surface() -> Result<Surface, String> {
533    let raw = unsafe { ll::SDL_GetVideoSurface() };
534
535    if raw.is_null() {
536        Err(get_error())
537    } else {
538        Ok(wrap_surface(raw, false))
539    }
540}
541
542// TODO: get_video_modes, get_video_driver_name
543
544impl Surface {
545    pub fn new(
546        surface_flags: &[SurfaceFlag],
547        width: isize,
548        height: isize,
549        bpp: isize,
550        rmask: u32,
551        gmask: u32,
552        bmask: u32,
553        amask: u32,
554    ) -> Result<Surface, String> {
555        let flags = surface_flags
556            .iter()
557            .fold(0u32, |flags, flag| flags | *flag as u32);
558
559        unsafe {
560            let raw = ll::SDL_CreateRGBSurface(
561                flags,
562                width as c_int,
563                height as c_int,
564                bpp as c_int,
565                rmask,
566                gmask,
567                bmask,
568                amask,
569            );
570
571            if raw.is_null() {
572                Err(get_error())
573            } else {
574                Ok(Surface {
575                    raw: raw,
576                    owned: true,
577                })
578            }
579        }
580    }
581
582    pub fn from_bmp(path: &Path) -> Result<Surface, String> {
583        let cpath = CString::new(path.to_str().unwrap()).unwrap();
584        let mode = CString::new("rb".as_bytes()).unwrap();
585        let raw =
586            unsafe { ll::SDL_LoadBMP_RW(ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()), 1) };
587
588        if raw.is_null() {
589            Err(get_error())
590        } else {
591            Ok(wrap_surface(raw, true))
592        }
593    }
594
595    // TODO: from_data (hard because the pixel data has to stay alive)
596
597    pub fn get_width(&self) -> u16 {
598        unsafe { (*self.raw).w as u16 }
599    }
600
601    pub fn get_height(&self) -> u16 {
602        unsafe { (*self.raw).h as u16 }
603    }
604
605    pub fn get_size(&self) -> (u16, u16) {
606        (self.get_width(), self.get_height())
607    }
608
609    pub fn get_rect(&self) -> Rect {
610        Rect {
611            x: 0,
612            y: 0,
613            w: self.get_width(),
614            h: self.get_height(),
615        }
616    }
617
618    pub fn update_rect(&self, rect: &Rect) {
619        unsafe {
620            ll::SDL_UpdateRect(
621                self.raw,
622                rect.x as i32,
623                rect.y as i32,
624                rect.w as u32,
625                rect.h as u32,
626            );
627        }
628    }
629
630    pub fn update_rects(&self, rects: &[Rect]) {
631        unsafe {
632            ll::SDL_UpdateRects(
633                self.raw,
634                rects.len() as c_int,
635                mem::transmute(rects.as_ptr()),
636            );
637        }
638    }
639
640    pub fn set_colors(&self, colors: &[Color]) -> bool {
641        let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();
642
643        unsafe { ll::SDL_SetColors(self.raw, colors.as_mut_ptr(), 0, colors.len() as c_int) == 1 }
644    }
645
646    pub fn set_palette(&self, palettes: &[PaletteType], colors: &[Color]) -> bool {
647        let mut colors: Vec<_> = colors.iter().map(|color| color.to_struct()).collect();
648        let flags = palettes
649            .iter()
650            .fold(0 as c_int, |flags, &flag| flags | flag as c_int);
651
652        unsafe {
653            ll::SDL_SetPalette(
654                self.raw,
655                flags,
656                colors.as_mut_ptr(),
657                0,
658                colors.len() as c_int,
659            ) == 1
660        }
661    }
662
663    pub fn lock(&self) -> bool {
664        unsafe { ll::SDL_LockSurface(self.raw) == 0 }
665    }
666
667    /// Locks a surface so that the pixels can be directly accessed safely.
668    pub fn with_lock<F: Fn(&mut [u8]) -> bool>(&self, f: F) -> bool {
669        unsafe {
670            if ll::SDL_LockSurface(self.raw) != 0 {
671                panic!("could not lock surface");
672            }
673            let len = (*self.raw).pitch as usize * ((*self.raw).h as usize);
674            let pixels: &mut [u8] = mem::transmute(((*self.raw).pixels, len));
675            let rv = f(pixels);
676            ll::SDL_UnlockSurface(self.raw);
677            rv
678        }
679    }
680
681    pub fn unlock(&self) {
682        unsafe {
683            ll::SDL_UnlockSurface(self.raw);
684        }
685    }
686
687    pub fn flip(&self) -> bool {
688        unsafe { ll::SDL_Flip(self.raw) == 0 }
689    }
690
691    pub fn convert(&self, fmt: &PixelFormat, flags: &[SurfaceFlag]) -> Result<Surface, String> {
692        let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
693
694        let mut rawfmt = unwrap_pixel_format(fmt);
695
696        let new = unsafe { ll::SDL_ConvertSurface(self.raw, &mut rawfmt, flags) };
697        match new.is_null() {
698            true => Err(get_error()),
699            false => Ok(wrap_surface(new, true)),
700        }
701    }
702
703    pub fn display_format(&self) -> Result<Surface, String> {
704        let raw = unsafe { ll::SDL_DisplayFormat(self.raw) };
705
706        if raw.is_null() {
707            Err(get_error())
708        } else {
709            Ok(wrap_surface(raw, true))
710        }
711    }
712
713    pub fn display_format_alpha(&self) -> Result<Surface, String> {
714        let raw = unsafe { ll::SDL_DisplayFormatAlpha(self.raw) };
715
716        if raw.is_null() {
717            Err(get_error())
718        } else {
719            Ok(wrap_surface(raw, true))
720        }
721    }
722
723    pub fn save_bmp(&self, path: &Path) -> bool {
724        let cpath = CString::new(path.to_str().unwrap()).unwrap();
725        let mode = CString::new("wb".as_bytes()).unwrap();
726        unsafe {
727            ll::SDL_SaveBMP_RW(
728                self.raw,
729                ll::SDL_RWFromFile(cpath.as_ptr(), mode.as_ptr()),
730                1,
731            ) == 0
732        }
733    }
734
735    pub fn set_alpha(&self, flags: &[SurfaceFlag], alpha: u8) -> bool {
736        let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
737
738        unsafe { ll::SDL_SetAlpha(self.raw, flags, alpha) == 0 }
739    }
740
741    pub fn set_color_key(&self, flags: &[SurfaceFlag], color: Color) -> bool {
742        let flags = flags.iter().fold(0u32, |flags, &flag| flags | flag as u32);
743
744        unsafe {
745            ll::SDL_SetColorKey(
746                self.raw,
747                flags,
748                color.to_mapped((*self.raw).format as *const _),
749            ) == 0
750        }
751    }
752
753    pub fn set_clip_rect(&self, rect: &Rect) {
754        unsafe {
755            ll::SDL_SetClipRect(self.raw, rect);
756        }
757    }
758
759    pub fn get_clip_rect(&self) -> Rect {
760        let rect = Rect {
761            x: 0,
762            y: 0,
763            w: 0,
764            h: 0,
765        };
766
767        unsafe {
768            ll::SDL_SetClipRect(self.raw, mem::transmute(&rect));
769        }
770
771        rect
772    }
773
774    pub fn blit_rect(
775        &self,
776        src: &Surface,
777        src_rect: Option<Rect>,
778        dest_rect: Option<Rect>,
779    ) -> bool {
780        unsafe {
781            ll::SDL_UpperBlit(
782                src.raw,
783                match src_rect {
784                    Some(ref rect) => mem::transmute(rect),
785                    None => ptr::null_mut(),
786                },
787                self.raw,
788                match dest_rect {
789                    Some(ref rect) => mem::transmute(rect),
790                    None => ptr::null_mut(),
791                },
792            ) == 0
793        }
794    }
795
796    pub fn blit(&self, src: &Surface) -> bool {
797        self.blit_rect(src, None, None)
798    }
799
800    pub fn blit_at(&self, src: &Surface, x: i16, y: i16) -> bool {
801        let (w, h) = src.get_size();
802
803        self.blit_rect(
804            src,
805            None,
806            Some(Rect {
807                x: x,
808                y: y,
809                w: w,
810                h: h,
811            }),
812        )
813    }
814
815    pub fn fill_rect(&self, rect: Option<Rect>, color: Color) -> bool {
816        unsafe {
817            ll::SDL_FillRect(
818                self.raw,
819                match rect {
820                    Some(ref rect) => mem::transmute(rect),
821                    None => ptr::null_mut(),
822                },
823                color.to_mapped((*self.raw).format as *const _),
824            ) == 0
825        }
826    }
827
828    pub fn fill(&self, color: Color) -> bool {
829        self.fill_rect(None, color)
830    }
831
832    pub fn clear(&self) -> bool {
833        self.fill(RGB(0, 0, 0))
834    }
835}
836
837pub fn set_gamma(r: f32, g: f32, b: f32) -> bool {
838    unsafe { ll::SDL_SetGamma(r as c_float, g as c_float, b as c_float) != -1 }
839}
840
841pub fn set_gamma_ramp(r: Option<[u16; 256]>, g: Option<[u16; 256]>, b: Option<[u16; 256]>) -> bool {
842    unsafe {
843        ll::SDL_SetGammaRamp(
844            match r {
845                Some(r) => r.as_ptr(),
846                None => ptr::null(),
847            },
848            match g {
849                Some(g) => g.as_ptr(),
850                None => ptr::null(),
851            },
852            match b {
853                Some(b) => b.as_ptr(),
854                None => ptr::null(),
855            },
856        ) != -1
857    }
858}
859
860pub fn get_gamma_ramp() -> ([u16; 256], [u16; 256], [u16; 256]) {
861    let mut r = [0u16; 256];
862    let mut g = [0u16; 256];
863    let mut b = [0u16; 256];
864
865    unsafe {
866        ll::SDL_GetGammaRamp(r.as_mut_ptr(), g.as_mut_ptr(), b.as_mut_ptr());
867    }
868
869    (r, g, b)
870}
871
872pub fn swap_buffers() {
873    unsafe {
874        ll::SDL_GL_SwapBuffers();
875    }
876}
877
878// TODO: YUV