Don't force the surface to take ownership of the window (#991)

* Don't force the surface to take ownership of the window

* Update changelog
This commit is contained in:
Andrew Hickman 2018-07-28 14:14:37 +01:00 committed by Pierre Krieger
parent 67ace6b1c5
commit 1d521d35d2
2 changed files with 71 additions and 33 deletions

View File

@ -3,6 +3,8 @@
- Use dynamically loaded `libvulkan` like on other platforms instead of linking to MoltenVK on macOS - Use dynamically loaded `libvulkan` like on other platforms instead of linking to MoltenVK on macOS
- Updated winit to version 0.16. - Updated winit to version 0.16.
- Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination - Allow custom implementations of `RenderPassDesc` to specify `VK_SUBPASS_EXTERNAL` as a dependency source or destination
- Added `vulkano_win::create_vk_surface` which allows creating a surface safely without taking ownership of
the window.
# Version 0.9.0 (2018-03-13) # Version 0.9.0 (2018-03-13)

View File

@ -8,10 +8,12 @@ extern crate cocoa;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate metal_rs as metal; extern crate metal_rs as metal;
use std::borrow::Borrow;
use std::error; use std::error;
use std::fmt; use std::fmt;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use std::ptr; use std::ptr;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use vulkano::instance::Instance; use vulkano::instance::Instance;
@ -53,16 +55,29 @@ pub fn required_extensions() -> InstanceExtensions {
} }
} }
/// Create a surface from the window type `W`. The surface borrows the window
/// to prevent it from being dropped before the surface.
pub fn create_vk_surface<W>(
window: W, instance: Arc<Instance>,
) -> Result<Arc<Surface<W>>, SurfaceCreationError>
where
W: SafeBorrow<winit::Window>,
{
unsafe { winit_to_surface(instance, window) }
}
pub trait VkSurfaceBuild { pub trait VkSurfaceBuild {
fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) fn build_vk_surface(
-> Result<Arc<Surface<winit::Window>>, CreationError>; self, events_loop: &EventsLoop, instance: Arc<Instance>,
) -> Result<Arc<Surface<winit::Window>>, CreationError>;
} }
impl VkSurfaceBuild for WindowBuilder { impl VkSurfaceBuild for WindowBuilder {
fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) fn build_vk_surface(
-> Result<Arc<Surface<winit::Window>>, CreationError> { self, events_loop: &EventsLoop, instance: Arc<Instance>,
) -> Result<Arc<Surface<winit::Window>>, CreationError> {
let window = self.build(events_loop)?; let window = self.build(events_loop)?;
Ok(unsafe { winit_to_surface(instance, window) }?) Ok(create_vk_surface(window, instance)?)
} }
} }
@ -115,55 +130,65 @@ impl From<WindowCreationError> for CreationError {
} }
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window) unsafe fn winit_to_surface<W: SafeBorrow<winit::Window>>(
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> { instance: Arc<Instance>, win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::os::android::WindowExt; use winit::os::android::WindowExt;
Surface::from_anativewindow(instance, win.get_native_window(), win) Surface::from_anativewindow(instance, win.borrow().get_native_window(), win)
} }
#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))] #[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window) unsafe fn winit_to_surface<W: SafeBorrow<winit::Window>>(
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> { instance: Arc<Instance>, win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::os::unix::WindowExt; use winit::os::unix::WindowExt;
match (win.get_wayland_display(), win.get_wayland_surface()) { match (
(Some(display), Some(surface)) => Surface::from_wayland(instance, win.borrow().get_wayland_display(),
display, win.borrow().get_wayland_surface(),
surface, ) {
win), (Some(display), Some(surface)) => Surface::from_wayland(instance, display, surface, win),
_ => { _ => {
// No wayland display found, check if we can use xlib. // No wayland display found, check if we can use xlib.
// If not, we use xcb. // If not, we use xcb.
if instance.loaded_extensions().khr_xlib_surface { if instance.loaded_extensions().khr_xlib_surface {
Surface::from_xlib(instance, Surface::from_xlib(
win.get_xlib_display().unwrap(), instance,
win.get_xlib_window().unwrap() as _, win.borrow().get_xlib_display().unwrap(),
win) win.borrow().get_xlib_window().unwrap() as _,
win,
)
} else { } else {
Surface::from_xcb(instance, Surface::from_xcb(
win.get_xcb_connection().unwrap(), instance,
win.get_xlib_window().unwrap() as _, win.borrow().get_xcb_connection().unwrap(),
win) win.borrow().get_xlib_window().unwrap() as _,
win,
)
} }
}, },
} }
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window) unsafe fn winit_to_surface<W: SafeBorrow<winit::Window>>(
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> { instance: Arc<Instance>, win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::os::windows::WindowExt; use winit::os::windows::WindowExt;
Surface::from_hwnd(instance, Surface::from_hwnd(
ptr::null() as *const (), // FIXME instance,
win.get_hwnd(), ptr::null() as *const (), // FIXME
win) win.borrow().get_hwnd(),
win,
)
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window) unsafe fn winit_to_surface<W: SafeBorrow<winit::Window>>(
-> Result<Arc<Surface<winit::Window>>, SurfaceCreationError> { instance: Arc<Instance>, win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
use winit::os::macos::WindowExt; use winit::os::macos::WindowExt;
let wnd: cocoa_id = mem::transmute(win.get_nswindow()); let wnd: cocoa_id = mem::transmute(win.borrow().get_nswindow());
let layer = CoreAnimationLayer::new(); let layer = CoreAnimationLayer::new();
@ -177,5 +202,16 @@ unsafe fn winit_to_surface(instance: Arc<Instance>, win: winit::Window)
view.setLayer(mem::transmute(layer.as_ref())); // Bombs here with out of memory view.setLayer(mem::transmute(layer.as_ref())); // Bombs here with out of memory
view.setWantsLayer(YES); view.setWantsLayer(YES);
Surface::from_macos_moltenvk(instance, win.get_nsview() as *const (), win) Surface::from_macos_moltenvk(instance, win.borrow().get_nsview() as *const (), win)
} }
/// An alternative to `Borrow<T>` with the requirement that all calls to
/// `borrow` return the same object.
pub unsafe trait SafeBorrow<T>: Borrow<T> {}
unsafe impl<T> SafeBorrow<T> for T {}
unsafe impl<'a, T> SafeBorrow<T> for &'a T {}
unsafe impl<'a, T> SafeBorrow<T> for &'a mut T {}
unsafe impl<T> SafeBorrow<T> for Rc<T> {}
unsafe impl<T> SafeBorrow<T> for Arc<T> {}
unsafe impl<T> SafeBorrow<T> for Box<T> {}