sdl/
video.rs

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