Merge pull request #1 from Rust-SDL2/master

Merge from upstream
This commit is contained in:
DefinitelyNotRobot
2018-10-27 15:43:50 +08:00
committed by GitHub
16 changed files with 1102 additions and 149 deletions
+28 -38
View File
@@ -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
+7 -7
View File
@@ -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.2"
license = "MIT"
authors = [ "Tony Aldridge <tony@angry-lawyer.com>", "Cobrand <cobrandw@gmail.com>"]
keywords = ["SDL", "windowing", "graphics", "api"]
categories = ["rendering","games","api-bindings","game-engines","multimedia"]
keywords = ["SDL", "windowing", "graphics", "api", "engine"]
categories = ["rendering","api-bindings","game-engines","multimedia"]
[lib]
@@ -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"
@@ -27,7 +27,7 @@ default-features = false
[dependencies.sdl2-sys]
path = "sdl2-sys"
version = "0.31.0"
version = "0.32.1"
[dependencies.c_vec]
version = ">= 1.0, <= 1.3"
+55 -3
View File
@@ -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"]
```
@@ -459,6 +459,58 @@ 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](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;
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
+38 -7
View File
@@ -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<pixels::Color>`
[PR #279](https://github.com/Rust-SDL2/rust-sdl2/pull/729)
+1 -1
View File
@@ -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;
}
}
}
+19
View File
@@ -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
+15 -11
View File
@@ -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.1"
authors = ["Tony Aldridge <tony@angry-lawyer.com>"]
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"
@@ -16,31 +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"
optional = true
[build-dependencies]
cfg-if = "0.1"
cfg-if = "^0.1"
[features]
@@ -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 = []
+183 -7
View File
@@ -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;
@@ -20,10 +22,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 {
@@ -41,9 +43,13 @@ fn download_to<T: io::Write>(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::<reqwest::header::ContentLength>()
.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::<u32>().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") }
@@ -105,13 +111,133 @@ 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();
sdl2_build_path
}
// 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![
// 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 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 <file_name>_old,
// open a new copy of <file_name>. 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};
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();
}
}
// 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
// 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()));
}
// For every new file, copy the entire contents of the patched file into
// a newly created <file_name>.
// 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 {
@@ -281,14 +407,60 @@ 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: PathBuf;
#[cfg(feature = "bundled")] {
let sdl2_source_path = download_sdl2();
let sdl2_compiled_path = compile_sdl2(sdl2_source_path.as_path(), target_os);
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");
let sdl2_compiled_lib_path = sdl2_compiled_path.join("lib");
@@ -311,6 +483,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"))]
@@ -0,0 +1,44 @@
# HG changeset patch
# User Drew Pirrone-Brusse <drew.pirrone.brusse@gmail.com>
# 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)
+537 -14
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -1,2 +1,13 @@
#include <SDL.h>
#include <SDL_syswm.h>
#include <SDL_vulkan.h>
/**
* <div rustbindgen replaces="VkInstance"></div>
*/
typedef uintptr_t VkInstance_int;
/**
* <div rustbindgen replaces="VkSurfaceKHR"></div>
*/
typedef uint64_t VkSurfaceKHR_int;
+37 -43
View File
@@ -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<AudioStatus> {
use self::AudioStatus::*;
let n = n as u32;
Some( match unsafe { transmute::<u32, sys::SDL_AudioStatus>(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,
})
}
@@ -373,13 +376,15 @@ extern "C" fn audio_callback_marshall<CB: AudioCallback>
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<CB> = &mut *(userdata as *mut _);
let buf: &mut [CB::Channel] = from_raw_parts_mut(
stream as *mut CB::Channel,
len as usize / size_of::<CB::Channel>()
);
cb_userdata.callback(buf);
if let Some(cb) = cb_userdata {
cb.callback(buf);
}
}
}
@@ -394,14 +399,13 @@ pub struct AudioSpecDesired {
}
impl AudioSpecDesired {
fn convert_to_ll<CB, F, C, S>(freq: F, channels: C, samples: S, userdata: *mut CB) -> sys::SDL_AudioSpec
fn convert_to_ll<CB, F, C, S>(freq: F, channels: C, samples: S, userdata: *mut Option<CB>) -> sys::SDL_AudioSpec
where
CB: AudioCallback,
F: Into<Option<i32>>,
C: Into<Option<u8>>,
S: Into<Option<u16>>,
{
use std::mem::transmute;
let freq = freq.into();
let channels = channels.into();
@@ -413,22 +417,20 @@ impl AudioSpecDesired {
// A value of 0 means "fallback" or "default".
unsafe {
sys::SDL_AudioSpec {
freq: freq.unwrap_or(0),
format: <CB::Channel as AudioFormatNum>::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::<CB>
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: <CB::Channel as AudioFormatNum>::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::<CB>
as extern "C" fn
(arg1: *mut c_void,
arg2: *mut uint8_t,
arg3: c_int)),
userdata: userdata as *mut _,
}
}
@@ -596,7 +598,7 @@ pub struct AudioDevice<CB: AudioCallback> {
device_id: AudioDeviceID,
spec: AudioSpec,
/// Store the callback to keep it alive for the entire duration of `AudioDevice`.
userdata: Box<CB>
userdata: Box<Option<CB>>
}
impl<CB: AudioCallback> AudioDevice<CB> {
@@ -607,14 +609,8 @@ impl<CB: AudioCallback> AudioDevice<CB> {
D: Into<Option<&'a str>>,
{
// 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<CB> = Box::new(mem::uninitialized());
mem::transmute(b)
};
let desired = AudioSpecDesired::convert_to_ll(spec.freq, spec.channels, spec.samples, userdata);
let mut userdata: Box<Option<CB>> = Box::new(None);
let desired = AudioSpecDesired::convert_to_ll(spec.freq, spec.channels, spec.samples, &mut *userdata);
let mut obtained = unsafe { mem::uninitialized::<sys::SDL_AudioSpec>() };
unsafe {
@@ -636,10 +632,8 @@ impl<CB: AudioCallback> AudioDevice<CB> {
id => {
let device_id = AudioDeviceID::PlaybackDevice(id);
let spec = AudioSpec::convert_from_ll(obtained);
let mut userdata: Box<CB> = 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 +707,7 @@ impl<CB: AudioCallback> AudioDevice<CB> {
/// 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 +719,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> {
@@ -829,13 +823,13 @@ 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");
// // 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);
}
}
+1 -1
View File
@@ -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)
+32 -16
View File
@@ -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<MappingStatus, AddMappingError> {
use self::AddMappingError::*;
@@ -128,24 +132,36 @@ impl GameControllerSubsystem {
}
}
/// Load mappings from a file
pub fn load_mappings<P: AsRef<Path>>(&self, path: P)
-> Result<i32, AddMappingError> {
/// Load controller input mappings from a file.
pub fn load_mappings<P: AsRef<Path>>(&self, path: P) -> Result<i32, AddMappingError> {
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<R: io::Read>(
&self,
read: &mut R,
) -> Result<i32, AddMappingError> {
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<i32, AddMappingError> {
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<String, String> {
let c_str = unsafe { sys::SDL_GameControllerMappingForGUID(guid.raw()) };
+2
View File
@@ -1,6 +1,8 @@
//! # Getting started
//!
//! ```rust,no_run
//! extern crate sdl2;
//!
//! use sdl2::pixels::Color;
//! use sdl2::event::Event;
//! use sdl2::keyboard::Keycode;
+92 -1
View File
@@ -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;
@@ -18,6 +18,8 @@ use get_error;
use sys;
pub use sys::{VkInstance, VkSurfaceKHR};
pub struct WindowSurfaceRef<'a>(&'a mut SurfaceRef, &'a Window);
@@ -807,6 +809,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<P: AsRef<::std::path::Path>>(&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 +1127,33 @@ 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<Vec<&'static str>, 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`](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<VkSurfaceKHR, String> {
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)
}
}
pub fn display_index(&self) -> Result<i32, String> {
let result = unsafe { sys::SDL_GetWindowDisplayIndex(self.context.raw) };
if result < 0 {
@@ -1205,6 +1289,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"));