From 443d116f49fe37ef0a56ac6d5ad03ba040f53c7f Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 12 Jul 2018 14:52:11 +0200 Subject: [PATCH 01/26] Added Vulkan support --- README.md | 49 ++++ sdl2-sys/sdl_bindings.rs | 549 ++++++++++++++++++++++++++++++++++++++- sdl2-sys/wrapper.h | 1 + src/sdl2/video.rs | 92 ++++++- 4 files changed, 676 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4e7c8126..dbdbf29a 100644 --- a/README.md +++ b/README.md @@ -459,6 +459,55 @@ fn main() { This method is useful when you don't care about sdl2's render capabilities, but you do care about its audio, controller and other neat features that sdl2 has. +# Vulkan + +To use Vulkan, you need a Vulkan library for Rust. This example uses the [Vulkano][vulkano] +library. Other libraries may use different data types for raw Vulkan object handles. The +procedure to interface SDL2's Vulkan functions with these will be different for each one. + +```rust +extern crate sdl2; +extern crate vulkano; + +use sdl2::event::Event; +use sdl2::keyboard::Keycode; +use std::ffi::CString; +use vulkano::VulkanObject; +use vulkano::instance::{Instance, RawInstanceExtensions}; +use vulkano::swapchain::Surface; + +fn main() { + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + + let window = video_subsystem.window("Window", 800, 600) + .vulkan() + .build() + .unwrap(); + + let instance_extensions = window.vulkan_instance_extensions().unwrap(); + let raw_instance_extensions = RawInstanceExtensions::new(instance_extensions.iter().map(|&v| CString::new(v).unwrap())); + let instance = Instance::new(None, raw_instance_extensions, None).unwrap(); + let surface_handle = window.vulkan_create_surface(instance.internal_object()).unwrap(); + let surface = unsafe { Surface::from_raw_surface(instance, surface_handle, window.context()) }; + + let mut event_pump = sdl_context.event_pump().unwrap(); + + 'running: loop { + for event in event_pump.poll_iter() { + match event { + Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { + break 'running + }, + _ => {} + } + } + ::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60)); + } +} + +``` + # When things go wrong Rust, and Rust-SDL2, are both still heavily in development, and you may run into teething issues when using this. Before panicking, check that you're using diff --git a/sdl2-sys/sdl_bindings.rs b/sdl2-sys/sdl_bindings.rs index 48975838..576fb452 100644 --- a/sdl2-sys/sdl_bindings.rs +++ b/sdl2-sys/sdl_bindings.rs @@ -41,7 +41,7 @@ pub const __STDC_ISO_10646__: u32 = 201706; pub const __STDC_NO_THREADS__: u32 = 1; pub const __GNU_LIBRARY__: u32 = 6; pub const __GLIBC__: u32 = 2; -pub const __GLIBC_MINOR__: u32 = 26; +pub const __GLIBC_MINOR__: u32 = 27; pub const _SYS_CDEFS_H: u32 = 1; pub const __glibc_c99_flexarr_available: u32 = 1; pub const __WORDSIZE: u32 = 64; @@ -168,10 +168,25 @@ pub const WNOWAIT: u32 = 16777216; pub const __WNOTHREAD: u32 = 536870912; pub const __WALL: u32 = 1073741824; pub const __WCLONE: u32 = 2147483648; +pub const __ENUM_IDTYPE_T: u32 = 1; pub const __W_CONTINUED: u32 = 65535; pub const __WCOREFLAG: u32 = 128; pub const __HAVE_FLOAT128: u32 = 0; pub const __HAVE_DISTINCT_FLOAT128: u32 = 0; +pub const __HAVE_FLOAT64X: u32 = 1; +pub const __HAVE_FLOAT64X_LONG_DOUBLE: u32 = 1; +pub const __HAVE_FLOAT16: u32 = 0; +pub const __HAVE_FLOAT32: u32 = 1; +pub const __HAVE_FLOAT64: u32 = 1; +pub const __HAVE_FLOAT32X: u32 = 1; +pub const __HAVE_FLOAT128X: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT16: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT32: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT64: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT32X: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT64X: u32 = 0; +pub const __HAVE_DISTINCT_FLOAT128X: u32 = 0; +pub const __HAVE_FLOATN_NOT_TYPEDEF: u32 = 0; pub const __ldiv_t_defined: u32 = 1; pub const __lldiv_t_defined: u32 = 1; pub const RAND_MAX: u32 = 2147483647; @@ -210,6 +225,8 @@ pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: u32 = 1; pub const __PTHREAD_MUTEX_HAVE_PREV: u32 = 1; pub const __have_pthread_attr_t: u32 = 1; pub const _ALLOCA_H: u32 = 1; +pub const _MM_HINT_ET0: u32 = 7; +pub const _MM_HINT_ET1: u32 = 6; pub const _MM_HINT_T0: u32 = 3; pub const _MM_HINT_T1: u32 = 2; pub const _MM_HINT_T2: u32 = 1; @@ -311,6 +328,8 @@ pub const SDL_HINT_VIDEO_X11_XVIDMODE: &'static [u8; 23usize] = b"SDL_VIDEO_X11_ pub const SDL_HINT_VIDEO_X11_XINERAMA: &'static [u8; 23usize] = b"SDL_VIDEO_X11_XINERAMA\0"; pub const SDL_HINT_VIDEO_X11_XRANDR: &'static [u8; 21usize] = b"SDL_VIDEO_X11_XRANDR\0"; pub const SDL_HINT_VIDEO_X11_NET_WM_PING: &'static [u8; 26usize] = b"SDL_VIDEO_X11_NET_WM_PING\0"; +pub const SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR: &'static [u8; 39usize] = + b"SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR\0"; pub const SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN: &'static [u8; 44usize] = b"SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN\0"; pub const SDL_HINT_WINDOWS_INTRESOURCE_ICON: &'static [u8; 29usize] = @@ -337,8 +356,11 @@ pub const SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS: &'static [u8; 34usize] = b"SDL_APPLE_TV_CONTROLLER_UI_EVENTS\0"; pub const SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION: &'static [u8; 35usize] = b"SDL_APPLE_TV_REMOTE_ALLOW_ROTATION\0"; +pub const SDL_HINT_IOS_HIDE_HOME_INDICATOR: &'static [u8; 28usize] = + b"SDL_IOS_HIDE_HOME_INDICATOR\0"; pub const SDL_HINT_ACCELEROMETER_AS_JOYSTICK: &'static [u8; 30usize] = b"SDL_ACCELEROMETER_AS_JOYSTICK\0"; +pub const SDL_HINT_TV_REMOTE_AS_JOYSTICK: &'static [u8; 26usize] = b"SDL_TV_REMOTE_AS_JOYSTICK\0"; pub const SDL_HINT_XINPUT_ENABLED: &'static [u8; 19usize] = b"SDL_XINPUT_ENABLED\0"; pub const SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING: &'static [u8; 36usize] = b"SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING\0"; @@ -377,6 +399,7 @@ pub const SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION: &'static [u8; 45usi pub const SDL_HINT_IME_INTERNAL_EDITING: &'static [u8; 25usize] = b"SDL_IME_INTERNAL_EDITING\0"; pub const SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH: &'static [u8; 37usize] = b"SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH\0"; +pub const SDL_HINT_RETURN_KEY_HIDES_IME: &'static [u8; 25usize] = b"SDL_RETURN_KEY_HIDES_IME\0"; pub const SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT: &'static [u8; 32usize] = b"SDL_EMSCRIPTEN_KEYBOARD_ELEMENT\0"; pub const SDL_HINT_NO_SIGNAL_HANDLERS: &'static [u8; 23usize] = b"SDL_NO_SIGNAL_HANDLERS\0"; @@ -386,6 +409,7 @@ pub const SDL_HINT_BMP_SAVE_LEGACY_FORMAT: &'static [u8; 27usize] = b"SDL_BMP_SA pub const SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING: &'static [u8; 34usize] = b"SDL_WINDOWS_DISABLE_THREAD_NAMING\0"; pub const SDL_HINT_RPI_VIDEO_LAYER: &'static [u8; 20usize] = b"SDL_RPI_VIDEO_LAYER\0"; +pub const SDL_HINT_VIDEO_DOUBLE_BUFFER: &'static [u8; 24usize] = b"SDL_VIDEO_DOUBLE_BUFFER\0"; pub const SDL_HINT_OPENGL_ES_DRIVER: &'static [u8; 21usize] = b"SDL_OPENGL_ES_DRIVER\0"; pub const SDL_HINT_AUDIO_RESAMPLING_MODE: &'static [u8; 26usize] = b"SDL_AUDIO_RESAMPLING_MODE\0"; pub const SDL_HINT_AUDIO_CATEGORY: &'static [u8; 19usize] = b"SDL_AUDIO_CATEGORY\0"; @@ -395,7 +419,7 @@ pub const SDL_INVALID_SHAPE_ARGUMENT: i32 = -2; pub const SDL_WINDOW_LACKS_SHAPE: i32 = -3; pub const SDL_MAJOR_VERSION: u32 = 2; pub const SDL_MINOR_VERSION: u32 = 0; -pub const SDL_PATCHLEVEL: u32 = 6; +pub const SDL_PATCHLEVEL: u32 = 8; pub const SDL_INIT_TIMER: u32 = 1; pub const SDL_INIT_AUDIO: u32 = 16; pub const SDL_INIT_VIDEO: u32 = 32; @@ -942,7 +966,6 @@ pub type __ssize_t = ::std::os::raw::c_long; pub type __syscall_slong_t = ::std::os::raw::c_long; pub type __syscall_ulong_t = ::std::os::raw::c_ulong; pub type __loff_t = __off64_t; -pub type __qaddr_t = *mut __quad_t; pub type __caddr_t = *mut ::std::os::raw::c_char; pub type __intptr_t = ::std::os::raw::c_long; pub type __socklen_t = ::std::os::raw::c_uint; @@ -971,21 +994,13 @@ pub enum SDL_bool { SDL_FALSE = 0, SDL_TRUE = 1, } -/// \brief A signed 8-bit integer type. pub type Sint8 = i8; -/// \brief An unsigned 8-bit integer type. pub type Uint8 = u8; -/// \brief A signed 16-bit integer type. pub type Sint16 = i16; -/// \brief An unsigned 16-bit integer type. pub type Uint16 = u16; -/// \brief A signed 32-bit integer type. pub type Sint32 = i32; -/// \brief An unsigned 32-bit integer type. pub type Uint32 = u32; -/// \brief A signed 64-bit integer type. pub type Sint64 = i64; -/// \brief An unsigned 64-bit integer type. pub type Uint64 = u64; pub type SDL_compile_time_assert_uint8 = [::std::os::raw::c_int; 1usize]; pub type SDL_compile_time_assert_sint8 = [::std::os::raw::c_int; 1usize]; @@ -1016,6 +1031,44 @@ extern "C" { extern "C" { pub fn SDL_free(mem: *mut ::std::os::raw::c_void); } +pub type SDL_malloc_func = + ::std::option::Option *mut ::std::os::raw::c_void>; +pub type SDL_calloc_func = ::std::option::Option< + unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut ::std::os::raw::c_void, +>; +pub type SDL_realloc_func = ::std::option::Option< + unsafe extern "C" fn(mem: *mut ::std::os::raw::c_void, size: usize) + -> *mut ::std::os::raw::c_void, +>; +pub type SDL_free_func = + ::std::option::Option; +extern "C" { + /// \brief Get the current set of SDL memory functions + pub fn SDL_GetMemoryFunctions( + malloc_func: *mut SDL_malloc_func, + calloc_func: *mut SDL_calloc_func, + realloc_func: *mut SDL_realloc_func, + free_func: *mut SDL_free_func, + ); +} +extern "C" { + /// \brief Replace SDL's memory allocation functions with a custom set + /// + /// \note If you are replacing SDL's memory functions, you should call + /// SDL_GetNumAllocations() and be very careful if it returns non-zero. + /// That means that your free function will be called with memory + /// allocated by the previous memory allocation functions. + pub fn SDL_SetMemoryFunctions( + malloc_func: SDL_malloc_func, + calloc_func: SDL_calloc_func, + realloc_func: SDL_realloc_func, + free_func: SDL_free_func, + ) -> ::std::os::raw::c_int; +} +extern "C" { + /// \brief Get the number of outstanding (unfreed) allocations + pub fn SDL_GetNumAllocations() -> ::std::os::raw::c_int; +} extern "C" { pub fn SDL_getenv(name: *const ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } @@ -1292,21 +1345,39 @@ extern "C" { extern "C" { pub fn SDL_acos(x: f64) -> f64; } +extern "C" { + pub fn SDL_acosf(x: f32) -> f32; +} extern "C" { pub fn SDL_asin(x: f64) -> f64; } +extern "C" { + pub fn SDL_asinf(x: f32) -> f32; +} extern "C" { pub fn SDL_atan(x: f64) -> f64; } +extern "C" { + pub fn SDL_atanf(x: f32) -> f32; +} extern "C" { pub fn SDL_atan2(x: f64, y: f64) -> f64; } +extern "C" { + pub fn SDL_atan2f(x: f32, y: f32) -> f32; +} extern "C" { pub fn SDL_ceil(x: f64) -> f64; } +extern "C" { + pub fn SDL_ceilf(x: f32) -> f32; +} extern "C" { pub fn SDL_copysign(x: f64, y: f64) -> f64; } +extern "C" { + pub fn SDL_copysignf(x: f32, y: f32) -> f32; +} extern "C" { pub fn SDL_cos(x: f64) -> f64; } @@ -1316,18 +1387,45 @@ extern "C" { extern "C" { pub fn SDL_fabs(x: f64) -> f64; } +extern "C" { + pub fn SDL_fabsf(x: f32) -> f32; +} extern "C" { pub fn SDL_floor(x: f64) -> f64; } +extern "C" { + pub fn SDL_floorf(x: f32) -> f32; +} +extern "C" { + pub fn SDL_fmod(x: f64, y: f64) -> f64; +} +extern "C" { + pub fn SDL_fmodf(x: f32, y: f32) -> f32; +} extern "C" { pub fn SDL_log(x: f64) -> f64; } +extern "C" { + pub fn SDL_logf(x: f32) -> f32; +} +extern "C" { + pub fn SDL_log10(x: f64) -> f64; +} +extern "C" { + pub fn SDL_log10f(x: f32) -> f32; +} extern "C" { pub fn SDL_pow(x: f64, y: f64) -> f64; } +extern "C" { + pub fn SDL_powf(x: f32, y: f32) -> f32; +} extern "C" { pub fn SDL_scalbn(x: f64, n: ::std::os::raw::c_int) -> f64; } +extern "C" { + pub fn SDL_scalbnf(x: f32, n: ::std::os::raw::c_int) -> f32; +} extern "C" { pub fn SDL_sin(x: f64) -> f64; } @@ -2482,6 +2580,15 @@ pub type SDL_AudioCallback = ::std::option::Option< ), >; /// The calculated values in this structure are calculated by SDL_OpenAudio(). +/// +/// For multi-channel audio, the default SDL channel mapping is: +/// 2: FL FR (stereo) +/// 3: FL FR LFE (2.1 surround) +/// 4: FL FR BL BR (quad) +/// 5: FL FR FC BL BR (quad + center) +/// 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR) +/// 7: FL FR FC LFE BC SL SR (6.1 surround) +/// 8: FL FR FC LFE BL BR SL SR (7.1 surround) #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct SDL_AudioSpec { @@ -2962,6 +3069,130 @@ extern "C" { /// \return 0 on success or -1 if \c cvt->buf is NULL. pub fn SDL_ConvertAudio(cvt: *mut SDL_AudioCVT) -> ::std::os::raw::c_int; } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _SDL_AudioStream { + _unused: [u8; 0], +} +pub type SDL_AudioStream = _SDL_AudioStream; +extern "C" { + /// Create a new audio stream + /// + /// \param src_format The format of the source audio + /// \param src_channels The number of channels of the source audio + /// \param src_rate The sampling rate of the source audio + /// \param dst_format The format of the desired audio output + /// \param dst_channels The number of channels of the desired audio output + /// \param dst_rate The sampling rate of the desired audio output + /// \return 0 on success, or -1 on error. + /// + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamFlush + /// \sa SDL_AudioStreamClear + /// \sa SDL_FreeAudioStream + pub fn SDL_NewAudioStream( + src_format: SDL_AudioFormat, + src_channels: Uint8, + src_rate: ::std::os::raw::c_int, + dst_format: SDL_AudioFormat, + dst_channels: Uint8, + dst_rate: ::std::os::raw::c_int, + ) -> *mut SDL_AudioStream; +} +extern "C" { + /// Add data to be converted/resampled to the stream + /// + /// \param stream The stream the audio data is being added to + /// \param buf A pointer to the audio data to add + /// \param len The number of bytes to write to the stream + /// \return 0 on success, or -1 on error. + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamFlush + /// \sa SDL_AudioStreamClear + /// \sa SDL_FreeAudioStream + pub fn SDL_AudioStreamPut( + stream: *mut SDL_AudioStream, + buf: *const ::std::os::raw::c_void, + len: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +extern "C" { + /// Get converted/resampled data from the stream + /// + /// \param stream The stream the audio is being requested from + /// \param buf A buffer to fill with audio data + /// \param len The maximum number of bytes to fill + /// \return The number of bytes read from the stream, or -1 on error + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamFlush + /// \sa SDL_AudioStreamClear + /// \sa SDL_FreeAudioStream + pub fn SDL_AudioStreamGet( + stream: *mut SDL_AudioStream, + buf: *mut ::std::os::raw::c_void, + len: ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} +extern "C" { + /// Get the number of converted/resampled bytes available. The stream may be + /// buffering data behind the scenes until it has enough to resample + /// correctly, so this number might be lower than what you expect, or even + /// be zero. Add more data or flush the stream if you need the data now. + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamFlush + /// \sa SDL_AudioStreamClear + /// \sa SDL_FreeAudioStream + pub fn SDL_AudioStreamAvailable(stream: *mut SDL_AudioStream) -> ::std::os::raw::c_int; +} +extern "C" { + /// Tell the stream that you're done sending data, and anything being buffered + /// should be converted/resampled and made available immediately. + /// + /// It is legal to add more data to a stream after flushing, but there will + /// be audio gaps in the output. Generally this is intended to signal the + /// end of input, so the complete output becomes available. + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamClear + /// \sa SDL_FreeAudioStream + pub fn SDL_AudioStreamFlush(stream: *mut SDL_AudioStream) -> ::std::os::raw::c_int; +} +extern "C" { + /// Clear any pending data in the stream without converting it + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamFlush + /// \sa SDL_FreeAudioStream + pub fn SDL_AudioStreamClear(stream: *mut SDL_AudioStream); +} +extern "C" { + /// Free an audio stream + /// + /// \sa SDL_NewAudioStream + /// \sa SDL_AudioStreamPut + /// \sa SDL_AudioStreamGet + /// \sa SDL_AudioStreamAvailable + /// \sa SDL_AudioStreamFlush + /// \sa SDL_AudioStreamClear + pub fn SDL_FreeAudioStream(stream: *mut SDL_AudioStream); +} extern "C" { /// This takes two audio buffers of the playing audio format and mixes /// them, performing addition, volume adjustment, and overflow clipping. @@ -3021,7 +3252,7 @@ extern "C" { /// \param dev The device ID to which we will queue audio. /// \param data The data to queue to the device for later playback. /// \param len The number of bytes (not samples!) to which (data) points. - /// \return zero on success, -1 on error. + /// \return 0 on success, or -1 on error. /// /// \sa SDL_GetQueuedAudioSize /// \sa SDL_ClearQueuedAudio @@ -3196,6 +3427,17 @@ pub type __v4si = [::std::os::raw::c_int; 4usize]; pub type __v4sf = [f32; 4usize]; pub type __m128 = [f32; 4usize]; pub type __v4su = [::std::os::raw::c_uint; 4usize]; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum idtype_t { + P_ALL = 0, + P_PID = 1, + P_PGID = 2, +} +pub type _Float32 = f32; +pub type _Float64 = f64; +pub type _Float32x = f64; +pub type _Float64x = f64; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct div_t { @@ -5372,6 +5614,7 @@ pub const SDL_PIXELFORMAT_UYVY: _bindgen_ty_6 = _bindgen_ty_6::SDL_PIXELFORMAT_U pub const SDL_PIXELFORMAT_YVYU: _bindgen_ty_6 = _bindgen_ty_6::SDL_PIXELFORMAT_YVYU; pub const SDL_PIXELFORMAT_NV12: _bindgen_ty_6 = _bindgen_ty_6::SDL_PIXELFORMAT_NV12; pub const SDL_PIXELFORMAT_NV21: _bindgen_ty_6 = _bindgen_ty_6::SDL_PIXELFORMAT_NV21; +pub const SDL_PIXELFORMAT_EXTERNAL_OES: _bindgen_ty_6 = _bindgen_ty_6::SDL_PIXELFORMAT_EXTERNAL_OES; #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum _bindgen_ty_6 { @@ -5420,6 +5663,8 @@ pub enum _bindgen_ty_6 { SDL_PIXELFORMAT_NV12 = 842094158, /// < Planar mode: Y + V/U interleaved (2 planes) SDL_PIXELFORMAT_NV21 = 825382478, + /// < Android video texture format + SDL_PIXELFORMAT_EXTERNAL_OES = 542328143, } #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -6312,6 +6557,19 @@ pub type SDL_blit = ::std::option::Option< dstrect: *mut SDL_Rect, ) -> ::std::os::raw::c_int, >; +#[repr(u32)] +/// \brief The formula used for converting between YUV and RGB +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum SDL_YUV_CONVERSION_MODE { + /// < Full range JPEG + SDL_YUV_CONVERSION_JPEG = 0, + /// < BT.601 (the default) + SDL_YUV_CONVERSION_BT601 = 1, + /// < BT.709 + SDL_YUV_CONVERSION_BT709 = 2, + /// < BT.601 for SD content, BT.709 for HD content + SDL_YUV_CONVERSION_AUTOMATIC = 3, +} extern "C" { /// Allocate and free an RGB surface. /// @@ -6703,6 +6961,21 @@ extern "C" { dstrect: *mut SDL_Rect, ) -> ::std::os::raw::c_int; } +extern "C" { + /// \brief Set the YUV conversion mode + pub fn SDL_SetYUVConversionMode(mode: SDL_YUV_CONVERSION_MODE); +} +extern "C" { + /// \brief Get the YUV conversion mode + pub fn SDL_GetYUVConversionMode() -> SDL_YUV_CONVERSION_MODE; +} +extern "C" { + /// \brief Get the YUV conversion mode, returning the correct mode for the resolution when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC + pub fn SDL_GetYUVConversionModeForResolution( + width: ::std::os::raw::c_int, + height: ::std::os::raw::c_int, + ) -> SDL_YUV_CONVERSION_MODE; +} /// \brief The structure that defines a display mode /// /// \sa SDL_GetNumDisplayModes() @@ -6825,7 +7098,9 @@ pub enum SDL_WindowFlags { SDL_WINDOW_FULLSCREEN_DESKTOP = 4097, /// < window not created by SDL SDL_WINDOW_FOREIGN = 2048, - /// < window should be created in high-DPI mode if supported + /// < window should be created in high-DPI mode if supported. + /// On macOS NSHighResolutionCapable must be set true in the + /// application's Info.plist for this to have any effect. SDL_WINDOW_ALLOW_HIGHDPI = 8192, /// < window has mouse captured (unrelated to INPUT_GRABBED) SDL_WINDOW_MOUSE_CAPTURE = 16384, @@ -7190,7 +7465,7 @@ extern "C" { /// If the window is created with any of the SDL_WINDOW_OPENGL or /// SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function /// (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the - /// corrensponding UnloadLibrary function is called by SDL_DestroyWindow(). + /// corresponding UnloadLibrary function is called by SDL_DestroyWindow(). /// /// If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver, /// SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail. @@ -9312,6 +9587,20 @@ pub enum SDL_JoystickPowerLevel { SDL_JOYSTICK_POWER_WIRED = 4, SDL_JOYSTICK_POWER_MAX = 5, } +extern "C" { + /// Locking for multi-threaded access to the joystick API + /// + /// If you are using the joystick API or handling events from multiple threads + /// you should use these locking functions to protect access to the joysticks. + /// + /// In particular, you are guaranteed that the joystick list won't change, so + /// the API functions that take a joystick index will be valid, and joystick + /// and game controller events will not be delivered. + pub fn SDL_LockJoysticks(); +} +extern "C" { + pub fn SDL_UnlockJoysticks(); +} extern "C" { /// Count the number of joysticks attached to the system right now pub fn SDL_NumJoysticks() -> ::std::os::raw::c_int; @@ -16423,6 +16712,28 @@ extern "C" { /// \return 0 on success, or -1 if the operation is not supported pub fn SDL_GL_UnbindTexture(texture: *mut SDL_Texture) -> ::std::os::raw::c_int; } +extern "C" { + /// \brief Get the CAMetalLayer associated with the given Metal renderer + /// + /// \param renderer The renderer to query + /// + /// \return CAMetalLayer* on success, or NULL if the renderer isn't a Metal renderer + /// + /// \sa SDL_RenderGetMetalCommandEncoder() + pub fn SDL_RenderGetMetalLayer(renderer: *mut SDL_Renderer) -> *mut ::std::os::raw::c_void; +} +extern "C" { + /// \brief Get the Metal command encoder for the current frame + /// + /// \param renderer The renderer to query + /// + /// \return id on success, or NULL if the renderer isn't a Metal renderer + /// + /// \sa SDL_RenderGetMetalLayer() + pub fn SDL_RenderGetMetalCommandEncoder( + renderer: *mut SDL_Renderer, + ) -> *mut ::std::os::raw::c_void; +} extern "C" { /// \brief Create a window that can be shaped with the specified position, dimensions, and flags. /// @@ -28967,6 +29278,216 @@ extern "C" { /// \endcode pub fn SDL_GetWindowWMInfo(window: *mut SDL_Window, info: *mut SDL_SysWMinfo) -> SDL_bool; } +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VkInstance_T { + _unused: [u8; 0], +} +pub type VkInstance = *mut VkInstance_T; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct VkSurfaceKHR_T { + _unused: [u8; 0], +} +pub type VkSurfaceKHR = *mut VkSurfaceKHR_T; +pub type SDL_vulkanInstance = VkInstance; +pub type SDL_vulkanSurface = VkSurfaceKHR; +extern "C" { + /// \brief Dynamically load a Vulkan loader library. + /// + /// \param [in] path The platform dependent Vulkan loader library name, or + /// \c NULL. + /// + /// \return \c 0 on success, or \c -1 if the library couldn't be loaded. + /// + /// If \a path is NULL SDL will use the value of the environment variable + /// \c SDL_VULKAN_LIBRARY, if set, otherwise it loads the default Vulkan + /// loader library. + /// + /// This should be called after initializing the video driver, but before + /// creating any Vulkan windows. If no Vulkan loader library is loaded, the + /// default library will be loaded upon creation of the first Vulkan window. + /// + /// \note It is fairly common for Vulkan applications to link with \a libvulkan + /// instead of explicitly loading it at run time. This will work with + /// SDL provided the application links to a dynamic library and both it + /// and SDL use the same search path. + /// + /// \note If you specify a non-NULL \c path, an application should retrieve all + /// of the Vulkan functions it uses from the dynamic library using + /// \c SDL_Vulkan_GetVkGetInstanceProcAddr() unless you can guarantee + /// \c path points to the same vulkan loader library the application + /// linked to. + /// + /// \note On Apple devices, if \a path is NULL, SDL will attempt to find + /// the vkGetInstanceProcAddr address within all the mach-o images of + /// the current process. This is because it is fairly common for Vulkan + /// applications to link with libvulkan (and historically MoltenVK was + /// provided as a static library). If it is not found then, on macOS, SDL + /// will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib, + /// \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order. + /// On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications + /// using a dynamic framework or .dylib must ensure it is included in its + /// application bundle. + /// + /// \note On non-Apple devices, application linking with a static libvulkan is + /// not supported. Either do not link to the Vulkan loader or link to a + /// dynamic library version. + /// + /// \note This function will fail if there are no working Vulkan drivers + /// installed. + /// + /// \sa SDL_Vulkan_GetVkGetInstanceProcAddr() + /// \sa SDL_Vulkan_UnloadLibrary() + pub fn SDL_Vulkan_LoadLibrary(path: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; +} +extern "C" { + /// \brief Get the address of the \c vkGetInstanceProcAddr function. + /// + /// \note This should be called after either calling SDL_Vulkan_LoadLibrary + /// or creating an SDL_Window with the SDL_WINDOW_VULKAN flag. + pub fn SDL_Vulkan_GetVkGetInstanceProcAddr() -> *mut ::std::os::raw::c_void; +} +extern "C" { + /// \brief Unload the Vulkan loader library previously loaded by + /// \c SDL_Vulkan_LoadLibrary(). + /// + /// \sa SDL_Vulkan_LoadLibrary() + pub fn SDL_Vulkan_UnloadLibrary(); +} +extern "C" { + /// \brief Get the names of the Vulkan instance extensions needed to create + /// a surface with \c SDL_Vulkan_CreateSurface(). + /// + /// \param [in] window Window for which the required Vulkan instance + /// extensions should be retrieved + /// \param [in,out] count pointer to an \c unsigned related to the number of + /// required Vulkan instance extensions + /// \param [out] names \c NULL or a pointer to an array to be filled with the + /// required Vulkan instance extensions + /// + /// \return \c SDL_TRUE on success, \c SDL_FALSE on error. + /// + /// If \a pNames is \c NULL, then the number of required Vulkan instance + /// extensions is returned in pCount. Otherwise, \a pCount must point to a + /// variable set to the number of elements in the \a pNames array, and on + /// return the variable is overwritten with the number of names actually + /// written to \a pNames. If \a pCount is less than the number of required + /// extensions, at most \a pCount structures will be written. If \a pCount + /// is smaller than the number of required extensions, \c SDL_FALSE will be + /// returned instead of \c SDL_TRUE, to indicate that not all the required + /// extensions were returned. + /// + /// \note The returned list of extensions will contain \c VK_KHR_surface + /// and zero or more platform specific extensions + /// + /// \note The extension names queried here must be enabled when calling + /// VkCreateInstance, otherwise surface creation will fail. + /// + /// \note \c window should have been created with the \c SDL_WINDOW_VULKAN flag. + /// + /// \code + /// unsigned int count; + /// // get count of required extensions + /// if(!SDL_Vulkan_GetInstanceExtensions(window, &count, NULL)) + /// handle_error(); + /// + /// static const char *const additionalExtensions[] = + /// { + /// VK_EXT_DEBUG_REPORT_EXTENSION_NAME, // example additional extension + /// }; + /// size_t additionalExtensionsCount = sizeof(additionalExtensions) / sizeof(additionalExtensions[0]); + /// size_t extensionCount = count + additionalExtensionsCount; + /// const char **names = malloc(sizeof(const char *) * extensionCount); + /// if(!names) + /// handle_error(); + /// + /// // get names of required extensions + /// if(!SDL_Vulkan_GetInstanceExtensions(window, &count, names)) + /// handle_error(); + /// + /// // copy additional extensions after required extensions + /// for(size_t i = 0; i < additionalExtensionsCount; i++) + /// names[i + count] = additionalExtensions[i]; + /// + /// VkInstanceCreateInfo instanceCreateInfo = {}; + /// instanceCreateInfo.enabledExtensionCount = extensionCount; + /// instanceCreateInfo.ppEnabledExtensionNames = names; + /// // fill in rest of instanceCreateInfo + /// + /// VkInstance instance; + /// // create the Vulkan instance + /// VkResult result = vkCreateInstance(&instanceCreateInfo, NULL, &instance); + /// free(names); + /// \endcode + /// + /// \sa SDL_Vulkan_CreateSurface() + pub fn SDL_Vulkan_GetInstanceExtensions( + window: *mut SDL_Window, + pCount: *mut ::std::os::raw::c_uint, + pNames: *mut *const ::std::os::raw::c_char, + ) -> SDL_bool; +} +extern "C" { + /// \brief Create a Vulkan rendering surface for a window. + /// + /// \param [in] window SDL_Window to which to attach the rendering surface. + /// \param [in] instance handle to the Vulkan instance to use. + /// \param [out] surface pointer to a VkSurfaceKHR handle to receive the + /// handle of the newly created surface. + /// + /// \return \c SDL_TRUE on success, \c SDL_FALSE on error. + /// + /// \code + /// VkInstance instance; + /// SDL_Window *window; + /// + /// // create instance and window + /// + /// // create the Vulkan surface + /// VkSurfaceKHR surface; + /// if(!SDL_Vulkan_CreateSurface(window, instance, &surface)) + /// handle_error(); + /// \endcode + /// + /// \note \a window should have been created with the \c SDL_WINDOW_VULKAN flag. + /// + /// \note \a instance should have been created with the extensions returned + /// by \c SDL_Vulkan_CreateSurface() enabled. + /// + /// \sa SDL_Vulkan_GetInstanceExtensions() + pub fn SDL_Vulkan_CreateSurface( + window: *mut SDL_Window, + instance: VkInstance, + surface: *mut VkSurfaceKHR, + ) -> SDL_bool; +} +extern "C" { + /// \brief Get the size of a window's underlying drawable in pixels (for use + /// with setting viewport, scissor & etc). + /// + /// \param window SDL_Window from which the drawable size should be queried + /// \param w Pointer to variable for storing the width in pixels, + /// may be NULL + /// \param h Pointer to variable for storing the height in pixels, + /// may be NULL + /// + /// This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI + /// drawable, i.e. the window was created with SDL_WINDOW_ALLOW_HIGHDPI on a + /// platform with high-DPI support (Apple calls this "Retina"), and not disabled + /// by the \c SDL_HINT_VIDEO_HIGHDPI_DISABLED hint. + /// + /// \note On macOS high-DPI support must be enabled for an application by + /// setting NSHighResolutionCapable to true in its Info.plist. + /// + /// \sa SDL_GetWindowSize() + /// \sa SDL_CreateWindow() + pub fn SDL_Vulkan_GetDrawableSize( + window: *mut SDL_Window, + w: *mut ::std::os::raw::c_int, + h: *mut ::std::os::raw::c_int, + ); +} pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/sdl2-sys/wrapper.h b/sdl2-sys/wrapper.h index ec2ef478..7ae5a3a3 100644 --- a/sdl2-sys/wrapper.h +++ b/sdl2-sys/wrapper.h @@ -1,2 +1,3 @@ #include #include +#include diff --git a/src/sdl2/video.rs b/src/sdl2/video.rs index cd314fb9..9022a97b 100644 --- a/src/sdl2/video.rs +++ b/src/sdl2/video.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_float, uint32_t, c_char}; +use libc::{c_int, c_uint, c_float, uint32_t, c_char}; use std::ffi::{CStr, CString, NulError}; use std::{mem, ptr, fmt}; use std::rc::Rc; @@ -19,6 +19,9 @@ use get_error; use sys; +type VkInstance = usize; +type VkSurfaceKHR = u64; + pub struct WindowSurfaceRef<'a>(&'a mut SurfaceRef, &'a Window); impl<'a> Deref for WindowSurfaceRef<'a> { @@ -807,6 +810,61 @@ impl VideoSubsystem { mem::transmute(interval) } } + + /// Loads the default Vulkan library. + /// + /// This should be done after initializing the video driver, but before creating any Vulkan windows. + /// If no Vulkan library is loaded, the default library will be loaded upon creation of the first Vulkan window. + /// + /// If a different library is already loaded, this function will return an error. + pub fn vulkan_load_library_default(&self) -> Result<(), String> { + unsafe { + if sys::SDL_Vulkan_LoadLibrary(ptr::null()) == 0 { + Ok(()) + } else { + Err(get_error()) + } + } + } + + /// Loads the Vulkan library using a platform-dependent Vulkan library name (usually a file path). + /// + /// This should be done after initializing the video driver, but before creating any Vulkan windows. + /// If no Vulkan library is loaded, the default library will be loaded upon creation of the first Vulkan window. + /// + /// If a different library is already loaded, this function will return an error. + pub fn vulkan_load_library>(&self, path: P) -> Result<(), String> { + unsafe { + // TODO: use OsStr::to_cstring() once it's stable + let path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); + if sys::SDL_Vulkan_LoadLibrary(path.as_ptr() as *const c_char) == 0 { + Ok(()) + } else { + Err(get_error()) + } + } + } + + /// Unloads the current Vulkan library. + /// + /// To completely unload the library, this should be called for every successful load of the + /// Vulkan library. + pub fn vulkan_unload_library(&self) { + unsafe { sys::SDL_Vulkan_UnloadLibrary(); } + } + + /// Gets the pointer to the + /// [`vkGetInstanceProcAddr`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html) + /// Vulkan function. This function can be called to retrieve the address of other Vulkan + /// functions. + pub fn vulkan_get_proc_address_function(&self) -> Result<*const (), String> { + let result = unsafe { sys::SDL_Vulkan_GetVkGetInstanceProcAddr() as *const () }; + if result.is_null() { + Err(get_error()) + } else { + Ok(result) + } + } } #[derive(Debug)] @@ -1070,6 +1128,31 @@ impl Window { unsafe { sys::SDL_GL_SwapWindow(self.context.raw) } } + /// Get the names of the Vulkan instance extensions needed to create a surface with `vulkan_create_surface`. + pub fn vulkan_instance_extensions(&self) -> Result, String> { + let mut count: c_uint = 0; + if unsafe { sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, ptr::null_mut()) } == sys::SDL_bool::SDL_FALSE { + return Err(get_error()); + } + let mut names: Vec<*const c_char> = vec![ptr::null(); count as usize]; + if unsafe { sys::SDL_Vulkan_GetInstanceExtensions(self.context.raw, &mut count, names.as_mut_ptr()) } == sys::SDL_bool::SDL_FALSE { + return Err(get_error()); + } + Ok(names.iter().map(|&val| unsafe { CStr::from_ptr(val) }.to_str().unwrap()).collect()) + } + + /// Create a Vulkan rendering surface for a window. + /// + /// The `VkInstance` must be created using a prior call to the `vkCreateInstance` function in the Vulkan library. + pub fn vulkan_create_surface(&self, instance: VkInstance) -> Result { + let mut surface: sys::VkSurfaceKHR = ptr::null_mut(); + if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance as *mut _, &mut surface) } == sys::SDL_bool::SDL_FALSE { + Err(get_error()) + } else { + Ok(surface as VkSurfaceKHR) + } + } + pub fn display_index(&self) -> Result { let result = unsafe { sys::SDL_GetWindowDisplayIndex(self.context.raw) }; if result < 0 { @@ -1205,6 +1288,13 @@ impl Window { (w as u32, h as u32) } + pub fn vulkan_drawable_size(&self) -> (u32, u32) { + let mut w: c_int = 0; + let mut h: c_int = 0; + unsafe { sys::SDL_Vulkan_GetDrawableSize(self.context.raw, &mut w, &mut h) }; + (w as u32, h as u32) + } + pub fn set_minimum_size(&mut self, width: u32, height: u32) -> Result<(), IntegerOrSdlError> { let w = try!(validate_int(width, "width")); From 83d7ba7e682f1bbb9a5dcb6e7f4ed50fa2c8267d Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 12 Jul 2018 15:01:25 +0200 Subject: [PATCH 02/26] Fixed some display problems in the readme --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dbdbf29a..eef7b814 100644 --- a/README.md +++ b/README.md @@ -461,9 +461,10 @@ its audio, controller and other neat features that sdl2 has. # Vulkan -To use Vulkan, you need a Vulkan library for Rust. This example uses the [Vulkano][vulkano] -library. Other libraries may use different data types for raw Vulkan object handles. The -procedure to interface SDL2's Vulkan functions with these will be different for each one. +To use Vulkan, you need a Vulkan library for Rust. This example uses the +[Vulkano](https://github.com/vulkano-rs/vulkano) library. Other libraries may use different data +types for raw Vulkan object handles. The procedure to interface SDL2's Vulkan functions with these +will be different for each one. ```rust extern crate sdl2; @@ -486,7 +487,9 @@ fn main() { .unwrap(); let instance_extensions = window.vulkan_instance_extensions().unwrap(); - let raw_instance_extensions = RawInstanceExtensions::new(instance_extensions.iter().map(|&v| CString::new(v).unwrap())); + let raw_instance_extensions = RawInstanceExtensions::new(instance_extensions.iter().map( + |&v| CString::new(v).unwrap() + )); let instance = Instance::new(None, raw_instance_extensions, None).unwrap(); let surface_handle = window.vulkan_create_surface(instance.internal_object()).unwrap(); let surface = unsafe { Surface::from_raw_surface(instance, surface_handle, window.context()) }; From 22c896e360d119f3dfcb208a8cc3171745b5a255 Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 12 Jul 2018 15:06:57 +0200 Subject: [PATCH 03/26] Added link to vkCreateInstance documentation --- src/sdl2/video.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sdl2/video.rs b/src/sdl2/video.rs index 9022a97b..c63b23b1 100644 --- a/src/sdl2/video.rs +++ b/src/sdl2/video.rs @@ -1143,7 +1143,9 @@ impl Window { /// Create a Vulkan rendering surface for a window. /// - /// The `VkInstance` must be created using a prior call to the `vkCreateInstance` function in the Vulkan library. + /// The `VkInstance` must be created using a prior call to the + /// [`vkCreateInstance`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCreateInstance.html) + /// function in the Vulkan library. pub fn vulkan_create_surface(&self, instance: VkInstance) -> Result { let mut surface: sys::VkSurfaceKHR = ptr::null_mut(); if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance as *mut _, &mut surface) } == sys::SDL_bool::SDL_FALSE { From 0a313da48502fb66fa8b1223c6259e0f0a15d8ed Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 12 Jul 2018 16:54:42 +0200 Subject: [PATCH 04/26] Use plain integers for Vulkan handle types in auto-generated bindings --- sdl2-sys/sdl_bindings.rs | 6 ++++-- sdl2-sys/wrapper.h | 10 ++++++++++ src/sdl2/video.rs | 9 ++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/sdl2-sys/sdl_bindings.rs b/sdl2-sys/sdl_bindings.rs index 576fb452..dd7ad950 100644 --- a/sdl2-sys/sdl_bindings.rs +++ b/sdl2-sys/sdl_bindings.rs @@ -29283,13 +29283,11 @@ extern "C" { pub struct VkInstance_T { _unused: [u8; 0], } -pub type VkInstance = *mut VkInstance_T; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct VkSurfaceKHR_T { _unused: [u8; 0], } -pub type VkSurfaceKHR = *mut VkSurfaceKHR_T; pub type SDL_vulkanInstance = VkInstance; pub type SDL_vulkanSurface = VkSurfaceKHR; extern "C" { @@ -29488,6 +29486,10 @@ extern "C" { h: *mut ::std::os::raw::c_int, ); } +///
+pub type VkInstance = usize; +///
+pub type VkSurfaceKHR = u64; pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/sdl2-sys/wrapper.h b/sdl2-sys/wrapper.h index 7ae5a3a3..8412a434 100644 --- a/sdl2-sys/wrapper.h +++ b/sdl2-sys/wrapper.h @@ -1,3 +1,13 @@ #include #include #include + +/** + *
+ */ +typedef uintptr_t VkInstance_int; + +/** + *
+ */ +typedef uint64_t VkSurfaceKHR_int; diff --git a/src/sdl2/video.rs b/src/sdl2/video.rs index c63b23b1..20cd7f5f 100644 --- a/src/sdl2/video.rs +++ b/src/sdl2/video.rs @@ -18,9 +18,8 @@ use get_error; use sys; +pub use sys::{VkInstance, VkSurfaceKHR}; -type VkInstance = usize; -type VkSurfaceKHR = u64; pub struct WindowSurfaceRef<'a>(&'a mut SurfaceRef, &'a Window); @@ -1147,11 +1146,11 @@ impl Window { /// [`vkCreateInstance`](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkCreateInstance.html) /// function in the Vulkan library. pub fn vulkan_create_surface(&self, instance: VkInstance) -> Result { - let mut surface: sys::VkSurfaceKHR = ptr::null_mut(); - if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance as *mut _, &mut surface) } == sys::SDL_bool::SDL_FALSE { + let mut surface: VkSurfaceKHR = 0; + if unsafe { sys::SDL_Vulkan_CreateSurface(self.context.raw, instance, &mut surface) } == sys::SDL_bool::SDL_FALSE { Err(get_error()) } else { - Ok(surface as VkSurfaceKHR) + Ok(surface) } } From 0ca64698e97776ef1754da97b4856bc6ef9190ad Mon Sep 17 00:00:00 2001 From: Matthew Collins Date: Sun, 19 Aug 2018 23:39:26 +0100 Subject: [PATCH 05/26] Fix a segfault when `get_callback` panics --- src/sdl2/audio.rs | 63 ++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/src/sdl2/audio.rs b/src/sdl2/audio.rs index c4bc2612..ca020dee 100644 --- a/src/sdl2/audio.rs +++ b/src/sdl2/audio.rs @@ -373,13 +373,15 @@ extern "C" fn audio_callback_marshall use std::slice::from_raw_parts_mut; use std::mem::size_of; unsafe { - let cb_userdata: &mut CB = &mut *(userdata as *mut CB); + let cb_userdata: &mut Option = &mut *(userdata as *mut _); let buf: &mut [CB::Channel] = from_raw_parts_mut( stream as *mut CB::Channel, len as usize / size_of::() ); - cb_userdata.callback(buf); + if let Some(cb) = cb_userdata { + cb.callback(buf); + } } } @@ -394,14 +396,13 @@ pub struct AudioSpecDesired { } impl AudioSpecDesired { - fn convert_to_ll(freq: F, channels: C, samples: S, userdata: *mut CB) -> sys::SDL_AudioSpec + fn convert_to_ll(freq: F, channels: C, samples: S, userdata: *mut Option) -> sys::SDL_AudioSpec where CB: AudioCallback, F: Into>, C: Into>, S: Into>, { - use std::mem::transmute; let freq = freq.into(); let channels = channels.into(); @@ -413,22 +414,20 @@ impl AudioSpecDesired { // A value of 0 means "fallback" or "default". - unsafe { - sys::SDL_AudioSpec { - freq: freq.unwrap_or(0), - format: ::audio_format().to_ll(), - channels: channels.unwrap_or(0), - silence: 0, - samples: samples.unwrap_or(0), - padding: 0, - size: 0, - callback: Some(audio_callback_marshall:: - as extern "C" fn - (arg1: *mut c_void, - arg2: *mut uint8_t, - arg3: c_int)), - userdata: transmute(userdata) - } + sys::SDL_AudioSpec { + freq: freq.unwrap_or(0), + format: ::audio_format().to_ll(), + channels: channels.unwrap_or(0), + silence: 0, + samples: samples.unwrap_or(0), + padding: 0, + size: 0, + callback: Some(audio_callback_marshall:: + as extern "C" fn + (arg1: *mut c_void, + arg2: *mut uint8_t, + arg3: c_int)), + userdata: userdata as *mut _, } } @@ -596,7 +595,7 @@ pub struct AudioDevice { device_id: AudioDeviceID, spec: AudioSpec, /// Store the callback to keep it alive for the entire duration of `AudioDevice`. - userdata: Box + userdata: Box> } impl AudioDevice { @@ -607,14 +606,8 @@ impl AudioDevice { D: Into>, { - // SDL_OpenAudioDevice needs a userdata pointer, but we can't initialize the - // callback without the obtained AudioSpec. - // Create an uninitialized box that will be initialized after SDL_OpenAudioDevice. - let userdata: *mut CB = unsafe { - let b: Box = Box::new(mem::uninitialized()); - mem::transmute(b) - }; - let desired = AudioSpecDesired::convert_to_ll(spec.freq, spec.channels, spec.samples, userdata); + let mut userdata: Box> = Box::new(None); + let desired = AudioSpecDesired::convert_to_ll(spec.freq, spec.channels, spec.samples, &mut *userdata); let mut obtained = unsafe { mem::uninitialized::() }; unsafe { @@ -636,10 +629,8 @@ impl AudioDevice { id => { let device_id = AudioDeviceID::PlaybackDevice(id); let spec = AudioSpec::convert_from_ll(obtained); - let mut userdata: Box = mem::transmute(userdata); - let garbage = mem::replace(&mut userdata as &mut CB, get_callback(spec)); - mem::forget(garbage); + *userdata = Some(get_callback(spec)); Ok(AudioDevice { subsystem: a.clone(), @@ -713,7 +704,7 @@ impl AudioDevice { /// but the callback data will be dropped. pub fn close_and_get_callback(self) -> CB { drop(self.device_id); - *self.userdata + self.userdata.expect("Missing callback") } } @@ -725,11 +716,11 @@ pub struct AudioDeviceLockGuard<'a, CB> where CB: AudioCallback, CB: 'a { impl<'a, CB: AudioCallback> Deref for AudioDeviceLockGuard<'a, CB> { type Target = CB; - fn deref(&self) -> &CB { &self.device.userdata } + fn deref(&self) -> &CB { (*self.device.userdata).as_ref().expect("Missing callback") } } impl<'a, CB: AudioCallback> DerefMut for AudioDeviceLockGuard<'a, CB> { - fn deref_mut(&mut self) -> &mut CB { &mut self.device.userdata } + fn deref_mut(&mut self) -> &mut CB { (*self.device.userdata).as_mut().expect("Missing callback") } } impl<'a, CB: AudioCallback> Drop for AudioDeviceLockGuard<'a, CB> { @@ -835,7 +826,7 @@ mod test { assert_eq!(new_buffer.len(), new_buffer_expected.len(), "capacity must be exactly equal to twice the original vec size"); // // this has been commented, see https://discourse.libsdl.org/t/change-of-behavior-in-audiocvt-sdl-convertaudio-from-2-0-5-to-2-0-6/24682 - // // to maybe re-enable it someday + // // to maybe re-enable it someday // assert_eq!(new_buffer, new_buffer_expected); } } From a0734fd3d8ed70bdfafb9d29338d2c23d983dd99 Mon Sep 17 00:00:00 2001 From: Matthew Collins Date: Sun, 19 Aug 2018 23:48:58 +0100 Subject: [PATCH 06/26] Fix undefined behavior with AudioStatus's FromPrimitive Transmuting from a value not in the enum is undefined, plus transmuting is generally not great to do. --- src/sdl2/audio.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/sdl2/audio.rs b/src/sdl2/audio.rs index ca020dee..6c87f0b0 100644 --- a/src/sdl2/audio.rs +++ b/src/sdl2/audio.rs @@ -60,7 +60,6 @@ use std::ops::{Deref, DerefMut}; use std::path::Path; use std::marker::PhantomData; use std::mem; -use std::mem::transmute; use std::ptr; use AudioSubsystem; @@ -209,12 +208,16 @@ pub enum AudioStatus { impl FromPrimitive for AudioStatus { fn from_i64(n: i64) -> Option { use self::AudioStatus::*; - let n = n as u32; - Some( match unsafe { transmute::(n) } { - sys::SDL_AudioStatus::SDL_AUDIO_STOPPED => Stopped, - sys::SDL_AudioStatus::SDL_AUDIO_PLAYING => Playing, - sys::SDL_AudioStatus::SDL_AUDIO_PAUSED => Paused, + const STOPPED: i64 = sys::SDL_AudioStatus::SDL_AUDIO_STOPPED as i64; + const PLAYING: i64 = sys::SDL_AudioStatus::SDL_AUDIO_PLAYING as i64; + const PAUSED: i64 = sys::SDL_AudioStatus::SDL_AUDIO_PAUSED as i64; + + Some(match n { + STOPPED => Stopped, + PLAYING => Playing, + PAUSED => Paused, + _ => return None, }) } From a6df5914f10d7ff7dadf0152e1592daf3dcc0703 Mon Sep 17 00:00:00 2001 From: DefinitelyNotRobot Date: Wed, 22 Aug 2018 19:12:26 +0800 Subject: [PATCH 07/26] Add missing window_id field to Event::DropFile --- src/sdl2/event.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sdl2/event.rs b/src/sdl2/event.rs index b1f40498..0d7dc8df 100644 --- a/src/sdl2/event.rs +++ b/src/sdl2/event.rs @@ -691,6 +691,7 @@ pub enum Event { DropFile { timestamp: u32, + window_id: u32, filename: String }, @@ -1573,6 +1574,7 @@ impl Event { Event::DropFile { timestamp: event.timestamp, + window_id: event.windowID, filename: text } } From a60c146d702168b2dfa24a82906cbf67d6f18723 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 22 Aug 2018 16:37:36 -0400 Subject: [PATCH 08/26] common: impl Clone and PartialEq for IntegerOrSdlError --- src/sdl2/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl2/common.rs b/src/sdl2/common.rs index 88a73dae..7eeae915 100644 --- a/src/sdl2/common.rs +++ b/src/sdl2/common.rs @@ -3,7 +3,7 @@ use std::fmt; /// A given integer was so big that its representation as a C integer would be /// negative. -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub enum IntegerOrSdlError { IntegerOverflows(&'static str, u32), SdlError(String) From 16b84eaf8e6b88e5cb3fa5d66874996023793faa Mon Sep 17 00:00:00 2001 From: Stephen Date: Sun, 9 Sep 2018 22:22:43 -0700 Subject: [PATCH 09/26] Make getting-started example copy-paste friendly Make getting-started example copy-paste friendly by adding "extern crate sdl2;" line. When I was starting to read the docs, the first thing I did was copy-paste this example into a file to play with it but without this line, it doesn't compile (easy enough to fix, but wanted to fix it at the source). From reading the contributing guidelines, this appears to be small enough/documentation only, so I didn't think it required a changelog update. --- src/sdl2/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sdl2/lib.rs b/src/sdl2/lib.rs index 69f58976..83deb0a5 100644 --- a/src/sdl2/lib.rs +++ b/src/sdl2/lib.rs @@ -1,6 +1,8 @@ //! # Getting started //! //! ```rust,no_run +//! extern crate sdl2; +//! //! use sdl2::pixels::Color; //! use sdl2::event::Event; //! use sdl2::keyboard::Keycode; From 14ead0b8b1c333b8f9a982f926c16c15fc800577 Mon Sep 17 00:00:00 2001 From: Reynisdrangar Date: Sat, 7 Jul 2018 11:56:08 -0600 Subject: [PATCH 10/26] Extend travis build matrix to include bundled/static Doubles the number of builds, unfortunately, but it should cover all the common linkage scenarios, except for macos frameworks, which I'm not sure I know enough about to handle. Also autoformats travis.yml and splits the SDL archive extraction and installation out to a shell script --- .travis.yml | 66 +++++++++++++++------------------- scripts/travis-install-sdl2.sh | 19 ++++++++++ 2 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 scripts/travis-install-sdl2.sh diff --git a/.travis.yml b/.travis.yml index 9d12f0a2..4d386611 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,47 +1,37 @@ language: rust sudo: required rust: -- beta -- nightly -- stable + - beta + - nightly + - stable os: -- linux -- osx + - linux + - osx +env: + matrix: + - CI_BUILD_FEATURES="bundled" + - CI_BUILD_FEATURES="gfx image ttf mixer" + global: + - RUST_TEST_THREADS=1 + - TRAVIS_CARGO_NIGHTLY_FEATURE="" + - LD_LIBRARY_PATH: "/usr/local/lib" + - secure: MJhmVnQ2IM7+sVmc3vU4ndKOcQgLLeHUPW3qaQBQHKQmvoswCwQK60N17uSgWn1Ln8teqvSRHq4KclIjdMHI+VuQXJHQKHDgjcYbHxwmc3AM1Whnp0XB44ksKUmD109BGWSfZQxzF+6dA+YNOQ+mti+bpydMu8n2FMVjA/SXwQ8= + install: -- wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -O sdl2.tar.gz -- tar xzf sdl2.tar.gz -- pushd SDL2-* && ./configure && make && sudo make install && popd -- wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz -- wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz -- wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz -- wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download -- tar xzf SDL2_ttf-*.tar.gz -- tar xzf SDL2_image-*.tar.gz -- tar xzf SDL2_mixer-*.tar.gz -- tar xzf SDL2_gfx-*.tar.gz -- pushd SDL2_ttf-* && ./configure && make && sudo make install && popd -- pushd SDL2_image-* && ./configure && make && sudo make install && popd -- pushd SDL2_mixer-* && ./configure && make && sudo make install && popd -- pushd SDL2_gfx-* && ./autogen.sh && ./configure && make && sudo make install && popd + - if [[ $CI_BUILD_FEATURES != *"bundled"* ]]; then bash scripts/travis-install-sdl2.sh; fi before_script: -- shopt -s expand_aliases -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then alias pip=pip2; fi -- | - pip install 'travis-cargo<0.2' --user && - export PATH=$HOME/.local/bin:$PATH && - export PATH=~/Library/Python/2.7/bin:$PATH + - shopt -s expand_aliases + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then alias pip=pip2; fi + - | + pip install 'travis-cargo<0.2' --user && + export PATH=$HOME/.local/bin:$PATH && + export PATH=~/Library/Python/2.7/bin:$PATH script: -- | - travis-cargo build -- --features "gfx image ttf mixer" && - travis-cargo build -- --examples --features "gfx image ttf mixer" && - travis-cargo test -- --features "gfx image ttf mixer" && - travis-cargo --only stable doc -- --features "gfx image ttf mixer" + - | + travis-cargo build -- --features "${CI_BUILD_FEATURES}" && + travis-cargo build -- --examples --features "${CI_BUILD_FEATURES}" && + travis-cargo test -- --features "${CI_BUILD_FEATURES}" && + travis-cargo --only stable doc -- --features "${CI_BUILD_FEATURES}" after_success: -- travis-cargo --only stable doc-upload -env: - global: - - RUST_TEST_THREADS=1 - - TRAVIS_CARGO_NIGHTLY_FEATURE="" - - LD_LIBRARY_PATH: "/usr/local/lib" - - secure: MJhmVnQ2IM7+sVmc3vU4ndKOcQgLLeHUPW3qaQBQHKQmvoswCwQK60N17uSgWn1Ln8teqvSRHq4KclIjdMHI+VuQXJHQKHDgjcYbHxwmc3AM1Whnp0XB44ksKUmD109BGWSfZQxzF+6dA+YNOQ+mti+bpydMu8n2FMVjA/SXwQ8= + - travis-cargo --only stable doc-upload diff --git a/scripts/travis-install-sdl2.sh b/scripts/travis-install-sdl2.sh new file mode 100644 index 00000000..a6f42b5f --- /dev/null +++ b/scripts/travis-install-sdl2.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -xueo pipefail + +wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -O sdl2.tar.gz +tar xzf sdl2.tar.gz +pushd SDL2-* && ./configure && make && sudo make install && popd +wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz +wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz +wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz +wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download +tar xzf SDL2_ttf-*.tar.gz +tar xzf SDL2_image-*.tar.gz +tar xzf SDL2_mixer-*.tar.gz +tar xzf SDL2_gfx-*.tar.gz +pushd SDL2_ttf-* && ./configure && make && sudo make install && popd +pushd SDL2_image-* && ./configure && make && sudo make install && popd +pushd SDL2_mixer-* && ./configure && make && sudo make install && popd +pushd SDL2_gfx-* && ./autogen.sh && ./configure && make && sudo make install && popd From 0472c00dd9d29236afad7722fcdf57ed0d801e5b Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 22 Sep 2018 15:02:49 -0400 Subject: [PATCH 11/26] Lock bundled SDL2 builds to 2.0.5 --- sdl2-sys/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index 5b182008..0359e96f 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -20,10 +20,10 @@ use std::path::{Path, PathBuf}; use std::{io, fs, env}; // corresponds to the headers that we have in sdl2-sys/SDL2-{version} -const SDL2_HEADERS_BUNDLED_VERSION: &str = "2.0.8"; +const SDL2_HEADERS_BUNDLED_VERSION: &str = "2.0.5"; // means the lastest stable version that can be downloaded from SDL2's source -const LASTEST_SDL2_VERSION: &str = "2.0.8"; +const LASTEST_SDL2_VERSION: &str = "2.0.5"; #[cfg(feature = "bindgen")] macro_rules! add_msvc_includes_to_bindings { From e5100d17c2023ecb3acc6edc7c13f304bf60b529 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 22 Sep 2018 15:37:02 -0400 Subject: [PATCH 12/26] Fix a test in audio.rs Assert that stereo buffers are *at least* twice the original size, rather than more than twice the size. --- src/sdl2/audio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl2/audio.rs b/src/sdl2/audio.rs index c4bc2612..88942bcc 100644 --- a/src/sdl2/audio.rs +++ b/src/sdl2/audio.rs @@ -829,7 +829,7 @@ mod test { assert!(cvt.is_conversion_needed()); // since we're going from mono to stereo, our capacity must be at least twice the original (255) vec size - assert!(cvt.capacity(255) > 255*2, "capacity must be able to hold the converted audio sample"); + assert!(cvt.capacity(255) >= 255*2, "capacity must be able to hold the converted audio sample"); let new_buffer = cvt.convert(buffer); assert_eq!(new_buffer.len(), new_buffer_expected.len(), "capacity must be exactly equal to twice the original vec size"); From c33715bf5fb02668d31720bec00dd21b73802791 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 22 Sep 2018 17:21:36 -0400 Subject: [PATCH 13/26] "Install" Windows dynamic libraries Windows binaries don't embed library search paths, so tests were failing for being unable to find sdl2.dll. This commit adds some logic to copy that DLL into a known-good location. --- sdl2-sys/build.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index 5b182008..b5f8a45e 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -281,14 +281,59 @@ fn link_sdl2(target_os: &str) { } } +fn find_cargo_target_dir() -> PathBuf { + // Infer the top level cargo target dir from the OUT_DIR by searching + // upwards until we get to $CARGO_TARGET_DIR/build/ (which is always one + // level up from the deepest directory containing our package name) + let pkg_name = env::var("CARGO_PKG_NAME").unwrap(); + let mut out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + loop { + { + let final_path_segment = out_dir.file_name().unwrap(); + if final_path_segment.to_string_lossy().contains(&pkg_name) { + break; + } + } + if !out_dir.pop() { + panic!("Malformed build path: {}", out_dir.to_string_lossy()); + } + } + out_dir.pop(); + out_dir.pop(); + out_dir +} + +fn copy_dynamic_libraries(sdl2_compiled_path: &PathBuf, target_os: &str) { + // Windows binaries do not embed library search paths, so successfully + // linking the DLL isn't sufficient to find it at runtime -- it must be + // either on PATH or in the current working directory when we run binaries + // linked against it. In other words, to run the test suite we need to + // copy sdl2.dll out of its build tree and down to the top level cargo + // binary output directory. + if target_os.contains("windows") { + let sdl2_dll_name = "sdl2.dll"; + let sdl2_bin_path = sdl2_compiled_path.join("bin"); + let target_path = find_cargo_target_dir(); + + let src_dll_path = sdl2_bin_path.join(sdl2_dll_name); + let dst_dll_path = target_path.join(sdl2_dll_name); + + fs::copy(&src_dll_path, &dst_dll_path) + .expect(&format!("Failed to copy SDL2 dynamic library from {} to {}", + src_dll_path.to_string_lossy(), + dst_dll_path.to_string_lossy())); + } +} + fn main() { let target = env::var("TARGET").expect("Cargo build scripts always have TARGET"); let host = env::var("HOST").expect("Cargo build scripts always have HOST"); let target_os = get_os_from_triple(target.as_str()).unwrap(); + let sdl2_compiled_path; #[cfg(feature = "bundled")] { let sdl2_source_path = download_sdl2(); - let sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os); + sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os); let sdl2_downloaded_include_path = sdl2_source_path.join("include"); let sdl2_compiled_lib_path = sdl2_compiled_path.join("lib"); @@ -311,6 +356,10 @@ fn main() { } link_sdl2(target_os); + + #[cfg(all(feature = "bundled", not(feature = "static-link")))] { + copy_dynamic_libraries(&sdl2_compiled_path, target_os); + } } #[cfg(not(feature = "bindgen"))] From 7ed0ab1a96ec423fc3121747fef17507d4965dbf Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 22 Sep 2018 21:08:35 -0400 Subject: [PATCH 14/26] Fix a missing-type bug --- sdl2-sys/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index b5f8a45e..343f1506 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -330,7 +330,7 @@ fn main() { let host = env::var("HOST").expect("Cargo build scripts always have HOST"); let target_os = get_os_from_triple(target.as_str()).unwrap(); - let sdl2_compiled_path; + let sdl2_compiled_path: PathBuf; #[cfg(feature = "bundled")] { let sdl2_source_path = download_sdl2(); sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os); From 73514508420b8bb5fe5a5a10c2a14aa78909f451 Mon Sep 17 00:00:00 2001 From: johnthagen Date: Wed, 26 Sep 2018 19:23:19 -0400 Subject: [PATCH 15/26] Bump to latest version of SDL2_mixer in CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9d12f0a2..5443fde4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ install: - pushd SDL2-* && ./configure && make && sudo make install && popd - wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz - wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz -- wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz +- wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.2.tar.gz - wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download - tar xzf SDL2_ttf-*.tar.gz - tar xzf SDL2_image-*.tar.gz From 5da894bd43f58fb831b9732ce6350f9c4f0cb38b Mon Sep 17 00:00:00 2001 From: Reynisdrangar Date: Sat, 7 Jul 2018 11:56:08 -0600 Subject: [PATCH 16/26] Extend travis build matrix to include bundled/static Doubles the number of builds, unfortunately, but it should cover all the common linkage scenarios, except for macos frameworks, which I'm not sure I know enough about to handle. Also autoformats travis.yml and splits the SDL archive extraction and installation out to a shell script --- .travis.yml | 66 +++++++++++++++------------------- scripts/travis-install-sdl2.sh | 19 ++++++++++ 2 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 scripts/travis-install-sdl2.sh diff --git a/.travis.yml b/.travis.yml index 5443fde4..4d386611 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,47 +1,37 @@ language: rust sudo: required rust: -- beta -- nightly -- stable + - beta + - nightly + - stable os: -- linux -- osx + - linux + - osx +env: + matrix: + - CI_BUILD_FEATURES="bundled" + - CI_BUILD_FEATURES="gfx image ttf mixer" + global: + - RUST_TEST_THREADS=1 + - TRAVIS_CARGO_NIGHTLY_FEATURE="" + - LD_LIBRARY_PATH: "/usr/local/lib" + - secure: MJhmVnQ2IM7+sVmc3vU4ndKOcQgLLeHUPW3qaQBQHKQmvoswCwQK60N17uSgWn1Ln8teqvSRHq4KclIjdMHI+VuQXJHQKHDgjcYbHxwmc3AM1Whnp0XB44ksKUmD109BGWSfZQxzF+6dA+YNOQ+mti+bpydMu8n2FMVjA/SXwQ8= + install: -- wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -O sdl2.tar.gz -- tar xzf sdl2.tar.gz -- pushd SDL2-* && ./configure && make && sudo make install && popd -- wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz -- wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz -- wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.2.tar.gz -- wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download -- tar xzf SDL2_ttf-*.tar.gz -- tar xzf SDL2_image-*.tar.gz -- tar xzf SDL2_mixer-*.tar.gz -- tar xzf SDL2_gfx-*.tar.gz -- pushd SDL2_ttf-* && ./configure && make && sudo make install && popd -- pushd SDL2_image-* && ./configure && make && sudo make install && popd -- pushd SDL2_mixer-* && ./configure && make && sudo make install && popd -- pushd SDL2_gfx-* && ./autogen.sh && ./configure && make && sudo make install && popd + - if [[ $CI_BUILD_FEATURES != *"bundled"* ]]; then bash scripts/travis-install-sdl2.sh; fi before_script: -- shopt -s expand_aliases -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then alias pip=pip2; fi -- | - pip install 'travis-cargo<0.2' --user && - export PATH=$HOME/.local/bin:$PATH && - export PATH=~/Library/Python/2.7/bin:$PATH + - shopt -s expand_aliases + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then alias pip=pip2; fi + - | + pip install 'travis-cargo<0.2' --user && + export PATH=$HOME/.local/bin:$PATH && + export PATH=~/Library/Python/2.7/bin:$PATH script: -- | - travis-cargo build -- --features "gfx image ttf mixer" && - travis-cargo build -- --examples --features "gfx image ttf mixer" && - travis-cargo test -- --features "gfx image ttf mixer" && - travis-cargo --only stable doc -- --features "gfx image ttf mixer" + - | + travis-cargo build -- --features "${CI_BUILD_FEATURES}" && + travis-cargo build -- --examples --features "${CI_BUILD_FEATURES}" && + travis-cargo test -- --features "${CI_BUILD_FEATURES}" && + travis-cargo --only stable doc -- --features "${CI_BUILD_FEATURES}" after_success: -- travis-cargo --only stable doc-upload -env: - global: - - RUST_TEST_THREADS=1 - - TRAVIS_CARGO_NIGHTLY_FEATURE="" - - LD_LIBRARY_PATH: "/usr/local/lib" - - secure: MJhmVnQ2IM7+sVmc3vU4ndKOcQgLLeHUPW3qaQBQHKQmvoswCwQK60N17uSgWn1Ln8teqvSRHq4KclIjdMHI+VuQXJHQKHDgjcYbHxwmc3AM1Whnp0XB44ksKUmD109BGWSfZQxzF+6dA+YNOQ+mti+bpydMu8n2FMVjA/SXwQ8= + - travis-cargo --only stable doc-upload diff --git a/scripts/travis-install-sdl2.sh b/scripts/travis-install-sdl2.sh new file mode 100644 index 00000000..aa80ec3a --- /dev/null +++ b/scripts/travis-install-sdl2.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -xueo pipefail + +wget https://www.libsdl.org/release/SDL2-2.0.8.tar.gz -O sdl2.tar.gz +tar xzf sdl2.tar.gz +pushd SDL2-* && ./configure && make && sudo make install && popd +wget -q https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.14.tar.gz +wget -q https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.1.tar.gz +wget -q https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.2.tar.gz +wget -q -O SDL2_gfx-1.0.1.tar.gz https://sourceforge.net/projects/sdl2gfx/files/SDL2_gfx-1.0.1.tar.gz/download +tar xzf SDL2_ttf-*.tar.gz +tar xzf SDL2_image-*.tar.gz +tar xzf SDL2_mixer-*.tar.gz +tar xzf SDL2_gfx-*.tar.gz +pushd SDL2_ttf-* && ./configure && make && sudo make install && popd +pushd SDL2_image-* && ./configure && make && sudo make install && popd +pushd SDL2_mixer-* && ./configure && make && sudo make install && popd +pushd SDL2_gfx-* && ./autogen.sh && ./configure && make && sudo make install && popd From 1f48ab10c925392a69f0037a538b66f7422f8ff4 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 22 Sep 2018 15:37:02 -0400 Subject: [PATCH 17/26] Fix a test in audio.rs Assert that stereo buffers are *at least* twice the original size, rather than more than twice the size. --- src/sdl2/audio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl2/audio.rs b/src/sdl2/audio.rs index c4bc2612..88942bcc 100644 --- a/src/sdl2/audio.rs +++ b/src/sdl2/audio.rs @@ -829,7 +829,7 @@ mod test { assert!(cvt.is_conversion_needed()); // since we're going from mono to stereo, our capacity must be at least twice the original (255) vec size - assert!(cvt.capacity(255) > 255*2, "capacity must be able to hold the converted audio sample"); + assert!(cvt.capacity(255) >= 255*2, "capacity must be able to hold the converted audio sample"); let new_buffer = cvt.convert(buffer); assert_eq!(new_buffer.len(), new_buffer_expected.len(), "capacity must be exactly equal to twice the original vec size"); From 172729cfc5ad683d19215df45b4d759711ccdc10 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sun, 23 Sep 2018 19:41:07 -0400 Subject: [PATCH 18/26] Add unidiff to the build deps list for bundled builds --- sdl2-sys/Cargo.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index 31eeeeb0..9f218262 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -39,6 +39,10 @@ optional = true version = "0.2" optional = true +[build-dependencies.unidiff] +version = "0.2.1" +optional = true + [build-dependencies] cfg-if = "0.1" @@ -49,7 +53,7 @@ use-pkgconfig = ["pkg-config"] use-bindgen = ["bindgen"] static-link = [] use_mac_framework = [] -bundled = ["cmake", "reqwest", "tar", "flate2"] +bundled = ["cmake", "reqwest", "tar", "flate2", "unidiff"] mixer = [] image = [] ttf = [] From 5d860dbd22b2a18d3d9a11b3339164c56d3b2d08 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sun, 23 Sep 2018 19:42:26 -0400 Subject: [PATCH 19/26] Pull in and use the SDL2 2.0.8 patch Using some very poorly tested file I/O code, it should be noted. --- sdl2-sys/build.rs | 108 ++++++++++++++++++ .../SDL2-2.0.8-4234-mac-os-dylib-fix.patch | 44 +++++++ 2 files changed, 152 insertions(+) create mode 100644 sdl2-sys/patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index 343f1506..27e1371f 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -12,6 +12,8 @@ extern crate tar; extern crate flate2; #[cfg(feature="bundled")] extern crate reqwest; +#[cfg(feature="bundled")] +extern crate unidiff; #[macro_use] extern crate cfg_if; @@ -112,6 +114,111 @@ fn download_sdl2() -> PathBuf { sdl2_build_path } +// apply patches to sdl2 source +#[cfg(feature = "bundled")] +fn patch_sdl2(sdl2_source_path: &Path) { + let patches: Vec<(&str, &'static str)> = vec![ + ("SDL2-2.0.8-4234-mac-os-dylib-fix.patch", + include_str!("patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch")), + ]; + let sdl_version = format!("SDL2-{}", LASTEST_SDL2_VERSION); + + for patch in &patches { + // Only apply patches that apply to the current version of SDL2 + if !patch.0.starts_with(&sdl_version) { + continue; + } + let mut patch_set = unidiff::PatchSet::new(); + patch_set.parse(patch.1).expect("Error parsing diff"); + + for modified_file in patch_set.modified_files() { + use std::io::{Write, BufRead}; + + let file_path = sdl2_source_path.join(modified_file.path()); + let old_path = sdl2_source_path.join(format!("{}_old", modified_file.path())); + fs::rename(&file_path, &old_path) + .expect(&format!( + "Rename of {} to {} failed", + file_path.to_string_lossy(), + old_path.to_string_lossy())); + + let dst_file = fs::File::create(file_path).unwrap(); + let mut dst_buf = io::BufWriter::new(dst_file); + let old_file = fs::File::open(old_path).unwrap(); + let mut old_buf = io::BufReader::new(old_file); + let mut cursor = 0; + + for (i, hunk) in modified_file.into_iter().enumerate() { + // Write old lines from cursor to the start of this hunk. + let num_lines = hunk.source_start - cursor - 1; + for _ in 0..num_lines { + let mut line = String::new(); + old_buf.read_line(&mut line).unwrap(); + dst_buf.write_all(line.as_bytes()).unwrap(); + } + cursor += num_lines; + + // Skip lines in old_file, and verify that what we expect to + // replace is present in the old_file. + for expected_line in hunk.source_lines() { + let mut actual_line = String::new(); + old_buf.read_line(&mut actual_line).unwrap(); + actual_line.pop(); // Remove the trailing newline. + if expected_line.value != actual_line { + panic!("Can't apply patch; mismatch between expected and actual in hunk {}", i); + } + } + cursor += hunk.source_length; + + // Write the new lines into the destination. + for line in hunk.target_lines() { + dst_buf.write_all(line.value.as_bytes()).unwrap(); + dst_buf.write_all(b"\n").unwrap(); + } + } + + // Write all remaining lines from the old file into the new. + for line in old_buf.lines() { + dst_buf.write_all(&line.unwrap().into_bytes()).unwrap(); + dst_buf.write_all(b"\n").unwrap(); + } + } + // TODO: This is entirely untested code. There are likely bugs here, and + // this really should be part of the unidiff library, not a function + // defined here. Hopefully this gets moved somewhere else before it + // bites someone. + for removed_file in patch_set.removed_files() { + fs::remove_file(sdl2_source_path.join(removed_file.path())) + .expect( + &format!("Failed to remove file {} from {}", + removed_file.path(), + sdl2_source_path.to_string_lossy())); + } + // TODO: This is entirely untested code. There are likely bugs here, and + // this really should be part of the unidiff library, not a function + // defined here. Hopefully this gets moved somewhere else before it + // bites someone. + for added_file in patch_set.added_files() { + use std::io::Write; + + // This should be superfluous. I don't know how a new file would + // ever have more than one hunk. + assert!(added_file.len() == 1); + let file_path = sdl2_source_path.join(added_file.path()); + let mut dst_file = fs::File::create(&file_path) + .expect(&format!( + "Failed to create file {}", + file_path.to_string_lossy())); + let mut dst_buf = io::BufWriter::new(&dst_file); + + for line in added_file.into_iter().nth(0).unwrap().target_lines() { + dst_buf.write_all(line.value.as_bytes()).unwrap(); + dst_buf.write_all(b"\n").unwrap(); + } + } + } +} + // compile a shared or static lib depending on the feature #[cfg(feature = "bundled")] fn compile_sdl2(sdl2_build_path: &Path, target_os: &str) -> PathBuf { @@ -333,6 +440,7 @@ fn main() { let sdl2_compiled_path: PathBuf; #[cfg(feature = "bundled")] { let sdl2_source_path = download_sdl2(); + patch_sdl2(sdl2_source_path.as_path()); sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os); let sdl2_downloaded_include_path = sdl2_source_path.join("include"); diff --git a/sdl2-sys/patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch b/sdl2-sys/patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch new file mode 100644 index 00000000..5f05f5ce --- /dev/null +++ b/sdl2-sys/patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch @@ -0,0 +1,44 @@ +# HG changeset patch +# User Drew Pirrone-Brusse +# Date 1537744393 14400 +# Sun Sep 23 19:13:13 2018 -0400 +# Node ID b66fb83b6897137c1c2b857ee5490e602f8c31b0 +# Parent f1084c419f33610cf274e309a8b2798d2ae665c7 +Correct the name of the SDL shared library in CMake for Mac OS + +diff -r f1084c419f33 -r b66fb83b6897 CMakeLists.txt +--- a/CMakeLists.txt Thu Mar 01 08:26:10 2018 -0800 ++++ b/CMakeLists.txt Sun Sep 23 19:13:13 2018 -0400 +@@ -1704,7 +1704,9 @@ + if(SDL_SHARED) + add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES}) + if(APPLE) +- set_target_properties(SDL2 PROPERTIES MACOSX_RPATH 1) ++ set_target_properties(SDL2 PROPERTIES ++ MACOSX_RPATH 1 ++ OUTPUT_NAME "SDL2-${LT_RELEASE}") + elseif(UNIX AND NOT ANDROID) + set_target_properties(SDL2 PROPERTIES + VERSION ${LT_VERSION} +@@ -1810,16 +1812,14 @@ + + if(NOT (WINDOWS OR CYGWIN)) + if(SDL_SHARED) +- if (APPLE) +- set(SOEXT "dylib") +- else() +- set(SOEXT "so") +- endif() ++ set(SOEXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) # ".so", ".dylib", etc. ++ get_target_property(SONAME SDL2 OUTPUT_NAME) + if(NOT ANDROID) + install(CODE " + execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink +- \"libSDL2-2.0.${SOEXT}\" \"libSDL2.${SOEXT}\")") +- install(FILES ${SDL2_BINARY_DIR}/libSDL2.${SOEXT} DESTINATION "lib${LIB_SUFFIX}") ++ \"lib${SONAME}${SOPOSTFIX}${SOEXT}\" \"libSDL2${SOPOSTFIX}${SOEXT}\")" ++ WORKING_DIR "${SDL2_BINARY_DIR}") ++ install(FILES ${SDL2_BINARY_DIR}/libSDL2${SOPOSTFIX}${SOEXT} DESTINATION "lib${LIB_SUFFIX}") + endif() + endif() + if(FREEBSD) From 765d56459441ab12d6c662a357ef479d62e49114 Mon Sep 17 00:00:00 2001 From: Drew Pirrone-Brusse Date: Sat, 29 Sep 2018 14:11:38 -0400 Subject: [PATCH 20/26] Improve number and content of comments --- sdl2-sys/build.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index 27e1371f..0ba03a0f 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -117,20 +117,32 @@ fn download_sdl2() -> PathBuf { // apply patches to sdl2 source #[cfg(feature = "bundled")] fn patch_sdl2(sdl2_source_path: &Path) { + // vector of <(patch_file_name, patch_file_contents)> let patches: Vec<(&str, &'static str)> = vec![ - ("SDL2-2.0.8-4234-mac-os-dylib-fix.patch", - include_str!("patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch")), + // This patch fixes a CMake installation bug introduced in SDL2 2.0.4 on + // the Mac OS platform. Without this patch, the libSDL2.dylib generated + // during the SDL2 build phase will be overwritten by a symlink pointing + // to nothing. A variation of this patch was accepted upstream and + // should be included in SDL2 2.0.9. + // https://bugzilla.libsdl.org/show_bug.cgi?id=4234 + ("SDL2-2.0.8-4234-mac-os-dylib-fix.patch", include_str!("patches/SDL2-2.0.8-4234-mac-os-dylib-fix.patch")), ]; let sdl_version = format!("SDL2-{}", LASTEST_SDL2_VERSION); for patch in &patches { - // Only apply patches that apply to the current version of SDL2 + // Only apply patches whose file name is prefixed with the currently + // targeted version of SDL2. if !patch.0.starts_with(&sdl_version) { continue; } let mut patch_set = unidiff::PatchSet::new(); patch_set.parse(patch.1).expect("Error parsing diff"); + // For every modified file, copy the existing file to _old, + // open a new copy of . and fill the new file with a + // combination of the unmodified contents, and the patched sections. + // TOOD: This code is untested (save for the immediate application), and + // probably belongs in the unidiff (or similar) package. for modified_file in patch_set.modified_files() { use std::io::{Write, BufRead}; @@ -183,6 +195,7 @@ fn patch_sdl2(sdl2_source_path: &Path) { dst_buf.write_all(b"\n").unwrap(); } } + // For every removed file, simply delete the original. // TODO: This is entirely untested code. There are likely bugs here, and // this really should be part of the unidiff library, not a function // defined here. Hopefully this gets moved somewhere else before it @@ -194,6 +207,8 @@ fn patch_sdl2(sdl2_source_path: &Path) { removed_file.path(), sdl2_source_path.to_string_lossy())); } + // For every new file, copy the entire contents of the patched file into + // a newly created . // TODO: This is entirely untested code. There are likely bugs here, and // this really should be part of the unidiff library, not a function // defined here. Hopefully this gets moved somewhere else before it From c5a8a700037e8eed2f2037cf8b277cfe4a4f9c63 Mon Sep 17 00:00:00 2001 From: Cobrand Date: Tue, 9 Oct 2018 11:53:05 +0000 Subject: [PATCH 21/26] Update changelog & bump to 0.32 --- Cargo.toml | 8 ++++---- README.md | 6 +++--- changelog.md | 45 ++++++++++++++++++++++++++++++++++++++------- sdl2-sys/Cargo.toml | 6 +++--- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0418964a..32c2e1c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,11 @@ name = "sdl2" description = "SDL2 bindings for Rust" repository = "https://github.com/Rust-SDL2/rust-sdl2" documentation = "https://rust-sdl2.github.io/rust-sdl2/sdl2/" -version = "0.31.0" +version = "0.32.0-beta" license = "MIT" authors = [ "Tony Aldridge ", "Cobrand "] -keywords = ["SDL", "windowing", "graphics", "api"] -categories = ["rendering","games","api-bindings","game-engines","multimedia"] +keywords = ["SDL", "windowing", "graphics", "api", "engine", "2d"] +categories = ["rendering","api-bindings","game-engines","multimedia"] [lib] @@ -27,7 +27,7 @@ default-features = false [dependencies.sdl2-sys] path = "sdl2-sys" -version = "0.31.0" +version = "0.32.0" [dependencies.c_vec] version = ">= 1.0, <= 1.3" diff --git a/README.md b/README.md index eef7b814..8a7ad58f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Bindings for SDL2 in Rust -### [Changelog for 0.31](changelog.md#v031) +### [Changelog for 0.32](changelog.md#v032) # Overview @@ -257,7 +257,7 @@ download through Crates.io: ```toml [dependencies] - sdl2 = "0.31" + sdl2 = "0.32" ``` Alternatively, pull it from GitHub to obtain the latest version from master @@ -278,7 +278,7 @@ adding this instead: ```toml [dependencies.sdl2] - version = "0.31" + version = "0.32" default-features = false features = ["ttf","image","gfx","mixer"] ``` diff --git a/changelog.md b/changelog.md index f96fe3c9..05f9315c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,16 +1,47 @@ In this file will be listed the changes, especially the breaking ones that one should be careful of when upgrading from a version of rust-sdl2 to another. -### v0.31.1 +### v0.32 -[PR #737](https://github.com/Rust-SDL2/rust-sdl2/pull/737) -* Fix `ClipboardUtil::set_clipboard_text` to return an Ok when it went well. +[PR #790](https://github.com/Rust-SDL2/rust-sdl2/pull/790): Added missing `window_id` field to `Event::DropFile` -[PR #733](https://github.com/Rust-SDL2/rust-sdl2/pull/733) -* Add `video::border_size -> Result<(u16, u16, u16, u16), String>` equivalent of `SDL_GetWindowBorderSize()` +[PR #789](https://github.com/Rust-SDL2/rust-sdl2/pull/789): Audio Safety Fixes -[PR #732](https://github.com/Rust-SDL2/rust-sdl2/pull/732) -* Implemented `From<(u8, u8, u8)>` and `From<(u8, u8, u8, u8)>` for `pixels::Color`. +[PR #785](https://github.com/Rust-SDL2/rust-sdl2/pull/785): Vulkan Support + +[PR #782](https://github.com/Rust-SDL2/rust-sdl2/pull/782) +* Move ffi of features (mixer, ...) into `sys` +* Updated SDL2's default version to 2.0.8 + +[PR #780](https://github.com/Rust-SDL2/rust-sdl2/pull/780): Fixed a panic in `keyboard::Mod` + +[PR #775](https://github.com/Rust-SDL2/rust-sdl2/pull/775): Added `get_platform` + +[PR #774](https://github.com/Rust-SDL2/rust-sdl2/pull/774): `add_timer` is now must_use + +[PR #764](https://github.com/Rust-SDL2/rust-sdl2/pull/764): impl `Hash` for `Point` and `Rect` + +[PR #763](https://github.com/Rust-SDL2/rust-sdl2/pull/763): Allow `-sys` to build for `windows-gnu` target + +[PR #751](https://github.com/Rust-SDL2/rust-sdl2/pull/751): +**Breaking change** `gl_setswap_interval` now returns a `Result` instead of a `bool`. + +[PR #759](https://github.com/Rust-SDL2/rust-sdl2/pull/759): Expose Joystick power level + +[PR #751](https://github.com/Rust-SDL2/rust-sdl2/pull/751) +* Fix memory leak in `filesystem::base_path()` +* Fix memory leak on `ClipboardUtil::clipboard_text()` + +[PR #740](https://github.com/Rust-SDL2/rust-sdl2/pull/740): Implement Debug for Event + +[PR #737](https://github.com/Rust-SDL2/rust-sdl2/pull/737): +Fix `ClipboardUtil::set_clipboard_text` to return an Ok when it went well. + +[PR #733](https://github.com/Rust-SDL2/rust-sdl2/pull/733): +Add `video::border_size -> Result<(u16, u16, u16, u16), String>` equivalent of `SDL_GetWindowBorderSize()` + +[PR #732](https://github.com/Rust-SDL2/rust-sdl2/pull/732): +Implemented `From<(u8, u8, u8)>` and `From<(u8, u8, u8, u8)>` for `pixels::Color`. `Canvas.set_draw_color` can now be called with tuples or other types which implements `Into` [PR #279](https://github.com/Rust-SDL2/rust-sdl2/pull/729) diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index 9f218262..a7cb9fb0 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -2,11 +2,11 @@ name = "sdl2-sys" description = "Raw SDL2 bindings for Rust, used internally rust-sdl2" -repository = "https://github.com/AngryLawyer/rust-sdl2" -version = "0.31.0" +repository = "https://github.com/rust-sdl2/rust-sdl2" +version = "0.32.0" authors = ["Tony Aldridge "] keywords = ["SDL", "windowing", "graphics", "ffi"] -categories = ["rendering","games","external-ffi-bindings","game-engines","multimedia"] +categories = ["rendering","external-ffi-bindings","game-engines","multimedia"] license = "MIT" links = "SDL2" build = "build.rs" From 078d916a311e99fb71465fd182671e69686fb22f Mon Sep 17 00:00:00 2001 From: Cobrand Date: Tue, 9 Oct 2018 22:42:12 +0000 Subject: [PATCH 22/26] Remove keywords --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 32c2e1c6..134abf26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ documentation = "https://rust-sdl2.github.io/rust-sdl2/sdl2/" version = "0.32.0-beta" license = "MIT" authors = [ "Tony Aldridge ", "Cobrand "] -keywords = ["SDL", "windowing", "graphics", "api", "engine", "2d"] +keywords = ["SDL", "windowing", "graphics", "api", "engine"] categories = ["rendering","api-bindings","game-engines","multimedia"] [lib] From a51ad1aaf8ab53fb00f17e72cdf9eddc7298ff14 Mon Sep 17 00:00:00 2001 From: Cobrand Date: Wed, 10 Oct 2018 00:01:09 +0000 Subject: [PATCH 23/26] Update dependencies --- Cargo.toml | 6 +++--- sdl2-sys/Cargo.toml | 16 ++++++++-------- sdl2-sys/build.rs | 12 ++++++++---- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 134abf26..b069e418 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,9 @@ path = "src/sdl2/lib.rs" [dependencies] bitflags = "0.7" -libc = "0.2" -rand = "0.3" -lazy_static="0.2" +libc = "^0.2" +rand = "^0.5" +lazy_static = "^1" [dependencies.num] version = "0.1" diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index a7cb9fb0..5e89a6fd 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -16,35 +16,35 @@ name = "sdl2_sys" path = "src/lib.rs" [build-dependencies.bindgen] -version = "0.35" +version = "^0.42" optional = true [build-dependencies.pkg-config] -version = "0.3.9" +version = "^0.3" optional = true [build-dependencies.cmake] -version = "0.1" +version = "^0.1" optional = true [build-dependencies.reqwest] -version = "0.7" +version = "^0.9" optional = true [build-dependencies.tar] -version = "0.4" +version = "^0.4" optional = true [build-dependencies.flate2] -version = "0.2" +version = "^1" optional = true [build-dependencies.unidiff] -version = "0.2.1" +version = "^0.2" optional = true [build-dependencies] -cfg-if = "0.1" +cfg-if = "^0.1" [features] diff --git a/sdl2-sys/build.rs b/sdl2-sys/build.rs index 38042e55..3931f254 100644 --- a/sdl2-sys/build.rs +++ b/sdl2-sys/build.rs @@ -43,9 +43,13 @@ fn download_to(url: &str, mut dest: T) { use io::BufRead; let resp = reqwest::get(url).expect(&format!("Failed to GET resource: {:?}", url)); - let size = resp.headers() - .get::() - .map(|ct_len| **ct_len) + let size: u32 = resp.headers() + .get(reqwest::header::CONTENT_LENGTH) + .and_then(|cl| { + cl.to_str().ok().and_then(|cl| { + cl.parse::().ok() + }) + }) .unwrap_or(0); if !resp.status().is_success() { panic!("Download request failed with status: {:?}", resp.status()) } if size == 0 { panic!("Size of content was returned was 0") } @@ -107,7 +111,7 @@ fn download_sdl2() -> PathBuf { let reader = flate2::read::GzDecoder::new( fs::File::open(&sdl2_archive_path).unwrap() - ).unwrap(); + ); let mut ar = tar::Archive::new(reader); ar.unpack(&out_dir).unwrap(); From f60c28b086db177aa378219a5bda9908619ddf0c Mon Sep 17 00:00:00 2001 From: Cobrand Date: Wed, 10 Oct 2018 00:07:53 +0000 Subject: [PATCH 24/26] Bump sdl2 & sdl2-sys versions --- Cargo.toml | 4 ++-- sdl2-sys/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b069e418..727b6b4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ name = "sdl2" description = "SDL2 bindings for Rust" repository = "https://github.com/Rust-SDL2/rust-sdl2" documentation = "https://rust-sdl2.github.io/rust-sdl2/sdl2/" -version = "0.32.0-beta" +version = "0.32.0-beta.2" license = "MIT" authors = [ "Tony Aldridge ", "Cobrand "] keywords = ["SDL", "windowing", "graphics", "api", "engine"] @@ -27,7 +27,7 @@ default-features = false [dependencies.sdl2-sys] path = "sdl2-sys" -version = "0.32.0" +version = "0.32.1" [dependencies.c_vec] version = ">= 1.0, <= 1.3" diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index 5e89a6fd..5d01d784 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -3,7 +3,7 @@ name = "sdl2-sys" description = "Raw SDL2 bindings for Rust, used internally rust-sdl2" repository = "https://github.com/rust-sdl2/rust-sdl2" -version = "0.32.0" +version = "0.32.1" authors = ["Tony Aldridge "] keywords = ["SDL", "windowing", "graphics", "ffi"] categories = ["rendering","external-ffi-bindings","game-engines","multimedia"] From d2eb21b1cb202f0ae8ed212355373430c592d303 Mon Sep 17 00:00:00 2001 From: C Jones Date: Mon, 15 Oct 2018 12:40:50 -0400 Subject: [PATCH 25/26] Add load_mappings_from_read and load_mappings_from_rw This refactors load_mappings to provide load_mappings_from_rw, and then implements the existing load_mappings on top of those. This allows for loading mappings in cases where there's not a real file path available, like with virtual filesystems for resource handling. --- src/sdl2/controller.rs | 48 ++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/sdl2/controller.rs b/src/sdl2/controller.rs index f3825762..9974e8a8 100644 --- a/src/sdl2/controller.rs +++ b/src/sdl2/controller.rs @@ -2,6 +2,7 @@ use libc::c_char; use std::error; use std::ffi::{CString, CStr, NulError}; use std::fmt; +use std::io; use std::path::Path; use rwops::RWops; @@ -17,6 +18,7 @@ use sys; pub enum AddMappingError { InvalidMapping(NulError), InvalidFilePath(String), + ReadError(String), SdlError(String), } @@ -27,7 +29,8 @@ impl fmt::Display for AddMappingError { match *self { InvalidMapping(ref e) => write!(f, "Null error: {}", e), InvalidFilePath(ref value) => write!(f, "Invalid file path ({})", value), - SdlError(ref e) => write!(f, "SDL error: {}", e) + ReadError(ref e) => write!(f, "Read error: {}", e), + SdlError(ref e) => write!(f, "SDL error: {}", e), } } } @@ -39,6 +42,7 @@ impl error::Error for AddMappingError { match *self { InvalidMapping(_) => "invalid mapping", InvalidFilePath(_) => "invalid file path", + ReadError(_) => "read error", SdlError(ref e) => e, } } @@ -110,7 +114,7 @@ impl GameControllerSubsystem { == sys::SDL_ENABLE as i32 } } - /// Add a new mapping from a mapping string + /// Add a new controller input mapping from a mapping string. pub fn add_mapping(&self, mapping: &str) -> Result { use self::AddMappingError::*; @@ -128,24 +132,36 @@ impl GameControllerSubsystem { } } - /// Load mappings from a file - pub fn load_mappings>(&self, path: P) - -> Result { + /// Load controller input mappings from a file. + pub fn load_mappings>(&self, path: P) -> Result { use self::AddMappingError::*; - let file = match RWops::from_file(path, "r") { - Ok(f) => f, - Err(s) => return Err(InvalidFilePath(s)) - }; - - let result = unsafe { sys::SDL_GameControllerAddMappingsFromRW(file.raw(), 0) }; - - match result { - -1 => Err(SdlError(get_error())), - _ => Ok(result) - } + let rw = RWops::from_file(path, "r").map_err(InvalidFilePath)?; + self.load_mappings_from_rw(rw) } + /// Load controller input mappings from a [`Read`](std::io::Read) object. + pub fn load_mappings_from_read( + &self, + read: &mut R, + ) -> Result { + use self::AddMappingError::*; + + let mut buffer = Vec::with_capacity(1024); + let rw = RWops::from_read(read, &mut buffer).map_err(ReadError)?; + self.load_mappings_from_rw(rw) + } + + /// Load controller input mappings from an SDL [`RWops`] object. + pub fn load_mappings_from_rw<'a>(&self, rw: RWops<'a>) -> Result { + use self::AddMappingError::*; + + let result = unsafe { sys::SDL_GameControllerAddMappingsFromRW(rw.raw(), 0) }; + match result { + -1 => Err(SdlError(get_error())), + _ => Ok(result), + } + } pub fn mapping_for_guid(&self, guid: joystick::Guid) -> Result { let c_str = unsafe { sys::SDL_GameControllerMappingForGUID(guid.raw()) }; From cfced74f15aff369a7c304e35cad2e4a7ee85a57 Mon Sep 17 00:00:00 2001 From: Cobrand Date: Mon, 15 Oct 2018 17:31:20 +0000 Subject: [PATCH 26/26] Fix audio whitenoise example --- examples/audio-whitenoise.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/audio-whitenoise.rs b/examples/audio-whitenoise.rs index 287798e4..471e7dbc 100644 --- a/examples/audio-whitenoise.rs +++ b/examples/audio-whitenoise.rs @@ -16,7 +16,7 @@ impl AudioCallback for MyCallback { // Generate white noise for x in out.iter_mut() { - *x = (rng.next_f32()*2.0 - 1.0) * self.volume; + *x = (rng.gen_range(0.0, 2.0) - 1.0) * self.volume; } } }