sys-info = "0.5"
[target.'cfg(unix)'.dependencies]
-xcb = "0.8"
+xcb = {version = "0.8", features = ["shm"]}
+libc = "0.2"
+errno = "0.2"
[build-dependencies]
bindgen = "0.40"
use std::os::raw::c_char;
use std::ptr::null;
use std::ptr::null_mut;
+use std::ptr::NonNull;
use std::slice;
use std::str::FromStr;
+use swapchain::{SurfaceImplementation, SurfacePlatform, Swapchain};
use sys_info;
use uuid;
#[cfg(unix)]
| api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES
| api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2
| api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES
+ | api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR
| api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES
| api::VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
| api::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
| api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2
| api::VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2
| api::VK_STRUCTURE_TYPE_SUBMIT_INFO
+ | api::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
| api::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR
| api::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET => true,
_ => false,
instance: api::VkInstance,
_allocator: *const api::VkAllocationCallbacks,
) {
- OwnedHandle::from(instance);
+ if !instance.is_null() {
+ OwnedHandle::from(instance);
+ }
}
#[allow(non_snake_case)]
device: api::VkDevice,
_allocator: *const api::VkAllocationCallbacks,
) {
- OwnedHandle::from(device);
+ if !device.is_null() {
+ OwnedHandle::from(device);
+ }
}
unsafe fn enumerate_extension_properties(
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroySurfaceKHR(
_instance: api::VkInstance,
- _surface: api::VkSurfaceKHR,
- _pAllocator: *const api::VkAllocationCallbacks,
+ surface: api::VkSurfaceKHR,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ if !surface.is_null() {
+ let surface = SharedHandle::from(surface);
+ match surface.platform {
+ api::VK_ICD_WSI_PLATFORM_MIR => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_MIR")
+ }
+ api::VK_ICD_WSI_PLATFORM_WAYLAND => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_WAYLAND")
+ }
+ api::VK_ICD_WSI_PLATFORM_WIN32 => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_WIN32")
+ }
+ api::VK_ICD_WSI_PLATFORM_XCB => {
+ Box::from_raw(surface.take().get().unwrap().as_ptr() as *mut api::VkIcdSurfaceXcb);
+ }
+ api::VK_ICD_WSI_PLATFORM_XLIB => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_XLIB")
+ }
+ api::VK_ICD_WSI_PLATFORM_ANDROID => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_ANDROID")
+ }
+ api::VK_ICD_WSI_PLATFORM_MACOS => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_MACOS")
+ }
+ api::VK_ICD_WSI_PLATFORM_IOS => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_IOS")
+ }
+ api::VK_ICD_WSI_PLATFORM_DISPLAY => {
+ panic!("unimplemented platform: VK_ICD_WSI_PLATFORM_DISPLAY")
+ }
+ platform => panic!("unknown VkSurfaceKHR platform: {:?}", platform),
+ }
+ }
}
#[allow(non_snake_case)]
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
- _physicalDevice: api::VkPhysicalDevice,
- _surface: api::VkSurfaceKHR,
- _pSurfaceCapabilities: *mut api::VkSurfaceCapabilitiesKHR,
+ physical_device: api::VkPhysicalDevice,
+ surface: api::VkSurfaceKHR,
+ surface_capabilities: *mut api::VkSurfaceCapabilitiesKHR,
) -> api::VkResult {
- unimplemented!()
+ let mut surface_capabilities_2 = api::VkSurfaceCapabilities2KHR {
+ sType: api::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
+ pNext: null_mut(),
+ surfaceCapabilities: mem::zeroed(),
+ };
+ match vkGetPhysicalDeviceSurfaceCapabilities2KHR(
+ physical_device,
+ &api::VkPhysicalDeviceSurfaceInfo2KHR {
+ sType: api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+ pNext: null(),
+ surface: surface,
+ },
+ &mut surface_capabilities_2,
+ ) {
+ api::VK_SUCCESS => {
+ *surface_capabilities = surface_capabilities_2.surfaceCapabilities;
+ api::VK_SUCCESS
+ }
+ error => error,
+ }
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkGetPhysicalDeviceSurfaceFormatsKHR(
- _physicalDevice: api::VkPhysicalDevice,
- _surface: api::VkSurfaceKHR,
- _pSurfaceFormatCount: *mut u32,
- _pSurfaceFormats: *mut api::VkSurfaceFormatKHR,
+ _physical_device: api::VkPhysicalDevice,
+ surface: api::VkSurfaceKHR,
+ surface_format_count: *mut u32,
+ surface_formats: *mut api::VkSurfaceFormatKHR,
) -> api::VkResult {
- unimplemented!()
+ let surface_implementation = SurfacePlatform::from(SharedHandle::from(surface).platform)
+ .unwrap()
+ .get_surface_implementation();
+ let returned_surface_formats = match surface_implementation.get_surface_formats(surface) {
+ Ok(returned_surface_formats) => returned_surface_formats,
+ Err(result) => return result,
+ };
+ enumerate_helper(
+ surface_format_count,
+ surface_formats,
+ returned_surface_formats.iter(),
+ |a, b| *a = *b,
+ )
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkGetPhysicalDeviceSurfacePresentModesKHR(
- _physicalDevice: api::VkPhysicalDevice,
- _surface: api::VkSurfaceKHR,
- _pPresentModeCount: *mut u32,
- _pPresentModes: *mut api::VkPresentModeKHR,
+ _physical_device: api::VkPhysicalDevice,
+ surface: api::VkSurfaceKHR,
+ present_mode_count: *mut u32,
+ present_modes: *mut api::VkPresentModeKHR,
) -> api::VkResult {
- unimplemented!()
+ let surface_implementation = SurfacePlatform::from(SharedHandle::from(surface).platform)
+ .unwrap()
+ .get_surface_implementation();
+ let returned_present_modes = match surface_implementation.get_present_modes(surface) {
+ Ok(returned_present_modes) => returned_present_modes,
+ Err(result) => return result,
+ };
+ enumerate_helper(
+ present_mode_count,
+ present_modes,
+ returned_present_modes.iter(),
+ |a, b| *a = *b,
+ )
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateSwapchainKHR(
- _device: api::VkDevice,
- _pCreateInfo: *const api::VkSwapchainCreateInfoKHR,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pSwapchain: *mut api::VkSwapchainKHR,
+ device: api::VkDevice,
+ create_info: *const api::VkSwapchainCreateInfoKHR,
+ _allocator: *const api::VkAllocationCallbacks,
+ swapchain: *mut api::VkSwapchainKHR,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ device_group_swapchain_create_info: api::VkDeviceGroupSwapchainCreateInfoKHR = api::VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR,
+ }
+ let ref create_info = *create_info;
+ let device_group_swapchain_create_info = if device_group_swapchain_create_info.is_null() {
+ None
+ } else {
+ Some(&*device_group_swapchain_create_info)
+ };
+ *swapchain = Handle::null();
+ let platform = SurfacePlatform::from(SharedHandle::from(create_info.surface).platform).unwrap();
+ match platform
+ .get_surface_implementation()
+ .build(create_info, device_group_swapchain_create_info)
+ {
+ Ok(new_swapchain) => {
+ *swapchain = OwnedHandle::<api::VkSwapchainKHR>::new(new_swapchain).take();
+ api::VK_SUCCESS
+ }
+ Err(error) => error,
+ }
}
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkDestroySwapchainKHR(
_device: api::VkDevice,
- _swapchain: api::VkSwapchainKHR,
- _pAllocator: *const api::VkAllocationCallbacks,
+ swapchain: api::VkSwapchainKHR,
+ _allocator: *const api::VkAllocationCallbacks,
) {
- unimplemented!()
+ if !swapchain.is_null() {
+ OwnedHandle::from(swapchain);
+ }
}
#[allow(non_snake_case)]
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkGetPhysicalDeviceSurfaceCapabilities2KHR(
- _physicalDevice: api::VkPhysicalDevice,
- _pSurfaceInfo: *const api::VkPhysicalDeviceSurfaceInfo2KHR,
- _pSurfaceCapabilities: *mut api::VkSurfaceCapabilities2KHR,
+ _physical_device: api::VkPhysicalDevice,
+ surface_info: *const api::VkPhysicalDeviceSurfaceInfo2KHR,
+ surface_capabilities: *mut api::VkSurfaceCapabilities2KHR,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ surface_info,
+ root = api::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
+ }
+ let ref surface_info = *surface_info;
+ parse_next_chain_mut!{
+ surface_capabilities,
+ root = api::VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
+ }
+ let ref mut surface_capabilities = *surface_capabilities;
+ let surface_implementation =
+ SurfacePlatform::from(SharedHandle::from(surface_info.surface).platform)
+ .unwrap()
+ .get_surface_implementation();
+ match surface_implementation.get_capabilities(surface_info.surface) {
+ Ok(capabilities) => {
+ surface_capabilities.surfaceCapabilities = capabilities;
+ api::VK_SUCCESS
+ }
+ Err(result) => result,
+ }
}
#[allow(non_snake_case)]
#[allow(non_snake_case)]
pub unsafe extern "system" fn vkCreateXcbSurfaceKHR(
_instance: api::VkInstance,
- _pCreateInfo: *const api::VkXcbSurfaceCreateInfoKHR,
- _pAllocator: *const api::VkAllocationCallbacks,
- _pSurface: *mut api::VkSurfaceKHR,
+ create_info: *const api::VkXcbSurfaceCreateInfoKHR,
+ _allocator: *const api::VkAllocationCallbacks,
+ surface: *mut api::VkSurfaceKHR,
) -> api::VkResult {
- unimplemented!()
+ parse_next_chain_const!{
+ create_info,
+ root = api::VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
+ }
+ let ref create_info = *create_info;
+ let new_surface = Box::new(api::VkIcdSurfaceXcb {
+ base: api::VkIcdSurfaceBase {
+ platform: api::VK_ICD_WSI_PLATFORM_XCB,
+ },
+ connection: create_info.connection,
+ window: create_info.window,
+ });
+ *surface = api::VkSurfaceKHR::new(NonNull::new(
+ Box::into_raw(new_surface) as *mut api::VkIcdSurfaceBase
+ ));
+ api::VK_SUCCESS
}
#[cfg(unix)]
use std::ops::DerefMut;
use std::ptr::null_mut;
use std::ptr::NonNull;
+use swapchain::Swapchain;
#[repr(C)]
pub struct DispatchableType<T> {
value: T,
}
-impl<T> DispatchableType<T> {}
-
impl<T> From<T> for DispatchableType<T> {
fn from(v: T) -> Self {
Self {
}
}
-pub trait Handle: Copy + Eq + fmt::Debug {
- type Value;
- fn get(&self) -> Option<NonNull<Self::Value>>;
- fn new(v: Option<NonNull<Self::Value>>) -> Self;
+pub trait HandleAllocFree: Handle {
unsafe fn allocate<T: Into<Self::Value>>(v: T) -> Self {
Self::new(Some(NonNull::new_unchecked(Box::into_raw(Box::new(
v.into(),
unsafe fn free(self) {
Box::from_raw(self.get().unwrap().as_ptr());
}
+}
+
+pub trait Handle: Copy + Eq + fmt::Debug {
+ type Value;
+ fn get(&self) -> Option<NonNull<Self::Value>>;
+ fn new(v: Option<NonNull<Self::Value>>) -> Self;
fn null() -> Self {
Self::new(None)
}
impl<T> fmt::Debug for DispatchableHandle<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("DispatchableHandle")
- .field(&self.get().map(|v| v.as_ptr()).unwrap_or(null_mut()))
+ .field(
+ &self
+ .get()
+ .map(|v| v.as_ptr())
+ .unwrap_or(null_mut::<*mut ()>() as *mut _),
+ )
.finish()
}
}
}
#[repr(transparent)]
-pub struct OwnedHandle<T: Handle>(T);
+pub struct OwnedHandle<T: HandleAllocFree>(T);
-impl<T: Handle> OwnedHandle<T> {
+impl<T: HandleAllocFree> OwnedHandle<T> {
pub fn new<I: Into<T::Value>>(v: I) -> Self {
unsafe { OwnedHandle(T::allocate(v)) }
}
}
}
-impl<T: Handle> Deref for OwnedHandle<T> {
+impl<T: HandleAllocFree> Deref for OwnedHandle<T> {
type Target = T::Value;
fn deref(&self) -> &T::Value {
unsafe { &*self.0.get().unwrap().as_ptr() }
}
}
-impl<T: Handle> DerefMut for OwnedHandle<T> {
+impl<T: HandleAllocFree> DerefMut for OwnedHandle<T> {
fn deref_mut(&mut self) -> &mut T::Value {
unsafe { &mut *self.0.get().unwrap().as_ptr() }
}
}
-impl<T: Handle> Drop for OwnedHandle<T> {
+impl<T: HandleAllocFree> Drop for OwnedHandle<T> {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe {
}
}
-impl<T: Handle> fmt::Debug for OwnedHandle<T>
+impl<T: HandleAllocFree> fmt::Debug for OwnedHandle<T>
where
T::Value: fmt::Debug,
{
pub type VkInstance = DispatchableHandle<Instance>;
+impl HandleAllocFree for VkInstance {}
+
pub type VkPhysicalDevice = DispatchableHandle<PhysicalDevice>;
+impl HandleAllocFree for VkPhysicalDevice {}
+
pub type VkDevice = DispatchableHandle<Device>;
+impl HandleAllocFree for VkDevice {}
+
pub type VkQueue = DispatchableHandle<Queue>;
+impl HandleAllocFree for VkQueue {}
+
pub struct CommandBuffer {}
pub type VkCommandBuffer = DispatchableHandle<CommandBuffer>;
+impl HandleAllocFree for VkCommandBuffer {}
+
pub struct Semaphore {}
pub type VkSemaphore = NondispatchableHandle<Semaphore>;
+impl HandleAllocFree for VkSemaphore {}
+
pub struct Fence {}
pub type VkFence = NondispatchableHandle<Fence>;
+impl HandleAllocFree for VkFence {}
+
pub struct DeviceMemory {}
pub type VkDeviceMemory = NondispatchableHandle<DeviceMemory>;
+impl HandleAllocFree for VkDeviceMemory {}
+
pub struct Buffer {}
pub type VkBuffer = NondispatchableHandle<Buffer>;
+impl HandleAllocFree for VkBuffer {}
+
pub struct Image {}
pub type VkImage = NondispatchableHandle<Image>;
+impl HandleAllocFree for VkImage {}
+
pub struct Event {}
pub type VkEvent = NondispatchableHandle<Event>;
+impl HandleAllocFree for VkEvent {}
+
pub struct QueryPool {}
pub type VkQueryPool = NondispatchableHandle<QueryPool>;
+impl HandleAllocFree for VkQueryPool {}
+
pub struct BufferView {}
pub type VkBufferView = NondispatchableHandle<BufferView>;
+impl HandleAllocFree for VkBufferView {}
+
pub struct ImageView {}
pub type VkImageView = NondispatchableHandle<ImageView>;
+impl HandleAllocFree for VkImageView {}
+
pub struct ShaderModule {}
pub type VkShaderModule = NondispatchableHandle<ShaderModule>;
+impl HandleAllocFree for VkShaderModule {}
+
pub struct PipelineCache {}
pub type VkPipelineCache = NondispatchableHandle<PipelineCache>;
+impl HandleAllocFree for VkPipelineCache {}
+
pub struct PipelineLayout {}
pub type VkPipelineLayout = NondispatchableHandle<PipelineLayout>;
+impl HandleAllocFree for VkPipelineLayout {}
+
pub struct RenderPass {}
pub type VkRenderPass = NondispatchableHandle<RenderPass>;
+impl HandleAllocFree for VkRenderPass {}
+
pub struct Pipeline {}
pub type VkPipeline = NondispatchableHandle<Pipeline>;
+impl HandleAllocFree for VkPipeline {}
+
pub struct DescriptorSetLayout {}
pub type VkDescriptorSetLayout = NondispatchableHandle<DescriptorSetLayout>;
+impl HandleAllocFree for VkDescriptorSetLayout {}
+
pub struct Sampler {}
pub type VkSampler = NondispatchableHandle<Sampler>;
+impl HandleAllocFree for VkSampler {}
+
pub struct DescriptorPool {}
pub type VkDescriptorPool = NondispatchableHandle<DescriptorPool>;
+impl HandleAllocFree for VkDescriptorPool {}
+
pub struct DescriptorSet {}
pub type VkDescriptorSet = NondispatchableHandle<DescriptorSet>;
+impl HandleAllocFree for VkDescriptorSet {}
+
pub struct Framebuffer {}
pub type VkFramebuffer = NondispatchableHandle<Framebuffer>;
+impl HandleAllocFree for VkFramebuffer {}
+
pub struct CommandPool {}
pub type VkCommandPool = NondispatchableHandle<CommandPool>;
+impl HandleAllocFree for VkCommandPool {}
+
pub struct SamplerYcbcrConversion {}
pub type VkSamplerYcbcrConversion = NondispatchableHandle<SamplerYcbcrConversion>;
+impl HandleAllocFree for VkSamplerYcbcrConversion {}
+
pub struct DescriptorUpdateTemplate {}
pub type VkDescriptorUpdateTemplate = NondispatchableHandle<DescriptorUpdateTemplate>;
-pub struct SurfaceKHR {}
+impl HandleAllocFree for VkDescriptorUpdateTemplate {}
+
+pub type VkSurfaceKHR = NondispatchableHandle<api::VkIcdSurfaceBase>;
-pub type VkSurfaceKHR = NondispatchableHandle<SurfaceKHR>;
+// HandleAllocFree specifically not implemented for VkSurfaceKHR
-pub struct SwapchainKHR {}
+pub type VkSwapchainKHR = NondispatchableHandle<Box<Swapchain>>;
-pub type VkSwapchainKHR = NondispatchableHandle<SwapchainKHR>;
+impl HandleAllocFree for VkSwapchainKHR {}
pub struct DisplayKHR {}
pub type VkDisplayKHR = NondispatchableHandle<DisplayKHR>;
+impl HandleAllocFree for VkDisplayKHR {}
+
pub struct DisplayModeKHR {}
pub type VkDisplayModeKHR = NondispatchableHandle<DisplayModeKHR>;
+impl HandleAllocFree for VkDisplayModeKHR {}
+
pub struct DebugReportCallbackEXT {}
pub type VkDebugReportCallbackEXT = NondispatchableHandle<DebugReportCallbackEXT>;
+impl HandleAllocFree for VkDebugReportCallbackEXT {}
+
pub struct DebugUtilsMessengerEXT {}
pub type VkDebugUtilsMessengerEXT = NondispatchableHandle<DebugUtilsMessengerEXT>;
+impl HandleAllocFree for VkDebugUtilsMessengerEXT {}
+
pub struct ValidationCacheEXT {}
pub type VkValidationCacheEXT = NondispatchableHandle<ValidationCacheEXT>;
+
+impl HandleAllocFree for VkValidationCacheEXT {}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+use api;
+
+pub enum SupportedTilings {
+ Any,
+ LinearOnly,
+}
+
+pub struct ImageDescriptor {
+ pub supported_tilings: SupportedTilings,
+ pub format: api::VkFormat,
+ pub extents: api::VkExtent3D,
+ pub mip_levels: u32,
+}
// Copyright 2018 Jacob Lifshay
#[macro_use]
extern crate enum_map;
+#[cfg(unix)]
+extern crate errno;
+#[cfg(unix)]
+extern crate libc;
extern crate sys_info;
extern crate uuid;
#[cfg(unix)]
mod api;
mod api_impl;
mod handle;
+mod image;
+#[cfg(unix)]
+mod shm;
+mod swapchain;
+#[cfg(unix)]
+mod xcb_swapchain;
use std::ffi::CStr;
use std::os::raw::c_char;
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+use errno;
+use libc;
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::ops::DerefMut;
+use std::os::raw::c_int;
+use std::ptr::null_mut;
+use std::slice;
+
+#[derive(Debug)]
+pub struct SharedMemorySegment {
+ id: c_int,
+ size: usize,
+ _phantom_data: PhantomData<*mut u8>,
+}
+
+unsafe impl Send for SharedMemorySegment {}
+unsafe impl Sync for SharedMemorySegment {}
+
+impl SharedMemorySegment {
+ pub unsafe fn new(id: c_int, size: usize) -> Self {
+ assert_ne!(size, 0);
+ assert_ne!(id, -1);
+ SharedMemorySegment {
+ id,
+ size,
+ _phantom_data: PhantomData,
+ }
+ }
+ pub unsafe fn create_with_flags(size: usize, flags: c_int) -> Result<Self, errno::Errno> {
+ match libc::shmget(libc::IPC_PRIVATE, size, flags) {
+ -1 => Err(errno::errno()),
+ id => Ok(Self::new(id, size)),
+ }
+ }
+ pub fn create(size: usize) -> Result<Self, errno::Errno> {
+ unsafe { Self::create_with_flags(size, libc::IPC_CREAT | libc::IPC_EXCL | 0o666) }
+ }
+ pub fn map(&self) -> Result<MappedSharedMemorySegment, errno::Errno> {
+ unsafe {
+ let memory = libc::shmat(self.id, null_mut(), 0);
+ if memory == !0usize as *mut _ {
+ Err(errno::errno())
+ } else {
+ Ok(MappedSharedMemorySegment {
+ memory: memory as *mut u8,
+ size: self.size,
+ })
+ }
+ }
+ }
+}
+
+impl Drop for SharedMemorySegment {
+ fn drop(&mut self) {
+ unsafe {
+ libc::shmctl(self.id, libc::IPC_RMID, null_mut());
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct MappedSharedMemorySegment {
+ memory: *mut u8,
+ size: usize,
+}
+
+impl MappedSharedMemorySegment {
+ unsafe fn get(&self) -> *mut [u8] {
+ slice::from_raw_parts_mut(self.memory, self.size)
+ }
+}
+
+unsafe impl Send for MappedSharedMemorySegment {}
+unsafe impl Sync for MappedSharedMemorySegment {}
+
+impl Deref for MappedSharedMemorySegment {
+ type Target = [u8];
+ fn deref(&self) -> &[u8] {
+ unsafe { &*self.get() }
+ }
+}
+
+impl DerefMut for MappedSharedMemorySegment {
+ fn deref_mut(&mut self) -> &mut [u8] {
+ unsafe { &mut *self.get() }
+ }
+}
+
+impl Drop for MappedSharedMemorySegment {
+ fn drop(&mut self) {
+ unsafe {
+ libc::shmdt(self.memory as *const _);
+ }
+ }
+}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+use api;
+use std::any::Any;
+use std::borrow::Cow;
+use std::error::Error;
+use std::fmt::{self, Debug};
+#[cfg(unix)]
+use xcb_swapchain::XcbSurfaceImplementation;
+
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Enum)]
+#[allow(non_camel_case_types)]
+pub enum SurfacePlatform {
+ VK_ICD_WSI_PLATFORM_MIR,
+ VK_ICD_WSI_PLATFORM_WAYLAND,
+ VK_ICD_WSI_PLATFORM_WIN32,
+ VK_ICD_WSI_PLATFORM_XCB,
+ VK_ICD_WSI_PLATFORM_XLIB,
+ VK_ICD_WSI_PLATFORM_ANDROID,
+ VK_ICD_WSI_PLATFORM_MACOS,
+ VK_ICD_WSI_PLATFORM_IOS,
+ VK_ICD_WSI_PLATFORM_DISPLAY,
+}
+
+#[derive(Debug)]
+pub struct UnknownSurfacePlatform(pub api::VkIcdWsiPlatform);
+
+impl fmt::Display for UnknownSurfacePlatform {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "unknown surface platform {:?}", self.0)
+ }
+}
+
+impl Error for UnknownSurfacePlatform {}
+
+impl SurfacePlatform {
+ pub fn from(platform: api::VkIcdWsiPlatform) -> Result<Self, UnknownSurfacePlatform> {
+ match platform {
+ api::VK_ICD_WSI_PLATFORM_MIR => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_MIR),
+ api::VK_ICD_WSI_PLATFORM_WAYLAND => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_WAYLAND),
+ api::VK_ICD_WSI_PLATFORM_WIN32 => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_WIN32),
+ api::VK_ICD_WSI_PLATFORM_XCB => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_XCB),
+ api::VK_ICD_WSI_PLATFORM_XLIB => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_XLIB),
+ api::VK_ICD_WSI_PLATFORM_ANDROID => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_ANDROID),
+ api::VK_ICD_WSI_PLATFORM_MACOS => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_MACOS),
+ api::VK_ICD_WSI_PLATFORM_IOS => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_IOS),
+ api::VK_ICD_WSI_PLATFORM_DISPLAY => Ok(SurfacePlatform::VK_ICD_WSI_PLATFORM_DISPLAY),
+ platform => Err(UnknownSurfacePlatform(platform)),
+ }
+ }
+ pub fn get_surface_implementation(self) -> Cow<'static, dyn SurfaceImplementation> {
+ #[cfg(unix)]
+ const XCB_SURFACE_IMPLEMENTATION: XcbSurfaceImplementation = XcbSurfaceImplementation;
+ match self {
+ #[cfg(unix)]
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_XCB => Cow::Borrowed(&XCB_SURFACE_IMPLEMENTATION),
+ _ => Cow::Owned(FallbackSurfaceImplementation(self).duplicate()),
+ }
+ }
+}
+
+impl From<SurfacePlatform> for api::VkIcdWsiPlatform {
+ fn from(platform: SurfacePlatform) -> api::VkIcdWsiPlatform {
+ match platform {
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_MIR => api::VK_ICD_WSI_PLATFORM_MIR,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_WAYLAND => api::VK_ICD_WSI_PLATFORM_WAYLAND,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_WIN32 => api::VK_ICD_WSI_PLATFORM_WIN32,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_XCB => api::VK_ICD_WSI_PLATFORM_XCB,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_XLIB => api::VK_ICD_WSI_PLATFORM_XLIB,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_ANDROID => api::VK_ICD_WSI_PLATFORM_ANDROID,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_MACOS => api::VK_ICD_WSI_PLATFORM_MACOS,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_IOS => api::VK_ICD_WSI_PLATFORM_IOS,
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_DISPLAY => api::VK_ICD_WSI_PLATFORM_DISPLAY,
+ }
+ }
+}
+
+pub trait Swapchain: Any + Sync + Send + Debug {}
+
+pub trait SurfaceImplementation: Any + Sync + Send + Debug {
+ fn get_platform(&self) -> SurfacePlatform;
+ unsafe fn get_surface_formats(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkSurfaceFormatKHR]>, api::VkResult>;
+ unsafe fn get_present_modes(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkPresentModeKHR]>, api::VkResult>;
+ unsafe fn get_capabilities(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<api::VkSurfaceCapabilitiesKHR, api::VkResult>;
+ unsafe fn build(
+ &self,
+ create_info: &api::VkSwapchainCreateInfoKHR,
+ device_group_create_info: Option<&api::VkDeviceGroupSwapchainCreateInfoKHR>,
+ ) -> Result<Box<Swapchain>, api::VkResult>;
+ fn duplicate(&self) -> Box<dyn SurfaceImplementation>;
+}
+
+impl ToOwned for dyn SurfaceImplementation {
+ type Owned = Box<dyn SurfaceImplementation>;
+ fn to_owned(&self) -> Box<dyn SurfaceImplementation> {
+ self.duplicate()
+ }
+}
+
+#[derive(Debug)]
+pub struct FallbackSurfaceImplementation(SurfacePlatform);
+
+impl FallbackSurfaceImplementation {
+ pub fn report_error(&self) -> ! {
+ panic!(
+ "there is no surface implementation for {:?}",
+ self.get_platform()
+ )
+ }
+}
+
+impl SurfaceImplementation for FallbackSurfaceImplementation {
+ fn get_platform(&self) -> SurfacePlatform {
+ self.0
+ }
+ unsafe fn get_surface_formats(
+ &self,
+ _surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkSurfaceFormatKHR]>, api::VkResult> {
+ self.report_error()
+ }
+ unsafe fn get_present_modes(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkPresentModeKHR]>, api::VkResult> {
+ self.report_error()
+ }
+ unsafe fn get_capabilities(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<api::VkSurfaceCapabilitiesKHR, api::VkResult> {
+ self.report_error()
+ }
+ unsafe fn build(
+ &self,
+ _create_info: &api::VkSwapchainCreateInfoKHR,
+ _device_group_create_info: Option<&api::VkDeviceGroupSwapchainCreateInfoKHR>,
+ ) -> Result<Box<Swapchain>, api::VkResult> {
+ self.report_error()
+ }
+ fn duplicate(&self) -> Box<dyn SurfaceImplementation> {
+ Box::new(FallbackSurfaceImplementation(self.0))
+ }
+}
--- /dev/null
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+use api;
+use handle::Handle;
+use image::{ImageDescriptor, SupportedTilings};
+use libc;
+use std::borrow::Cow;
+use std::mem;
+use std::ops::{Deref, DerefMut};
+use std::os::raw::c_char;
+use std::ptr::null_mut;
+use std::ptr::NonNull;
+use swapchain::{SurfaceImplementation, SurfacePlatform, Swapchain};
+use xcb;
+
+#[derive(Debug)]
+pub struct XcbSwapchain {}
+
+impl Swapchain for XcbSwapchain {}
+
+struct ReplyObject<T>(NonNull<T>);
+
+impl<T> ReplyObject<T> {
+ unsafe fn from(v: *mut T) -> Option<Self> {
+ NonNull::new(v).map(ReplyObject)
+ }
+}
+
+impl<T> Deref for ReplyObject<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ unsafe { self.0.as_ref() }
+ }
+}
+
+impl<T> DerefMut for ReplyObject<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { self.0.as_mut() }
+ }
+}
+
+impl<T> Drop for ReplyObject<T> {
+ fn drop(&mut self) {
+ unsafe {
+ libc::free(self.0.as_ptr() as *mut libc::c_void);
+ }
+ }
+}
+
+struct ServerObject<Id: 'static + Copy> {
+ id: Id,
+ connection: *mut xcb::ffi::xcb_connection_t,
+ free_fn: unsafe extern "C" fn(connection: *mut xcb::ffi::xcb_connection_t, id: Id)
+ -> xcb::ffi::xcb_void_cookie_t,
+}
+
+impl<Id: 'static + Copy> ServerObject<Id> {
+ fn get(&self) -> Id {
+ self.id
+ }
+}
+
+impl<Id: 'static + Copy> Drop for ServerObject<Id> {
+ fn drop(&mut self) {
+ unsafe {
+ (self.free_fn)(self.connection, self.id);
+ }
+ }
+}
+
+type Gc = ServerObject<xcb::ffi::xcb_gcontext_t>;
+
+unsafe fn create_gc(
+ id: xcb::ffi::xcb_gcontext_t,
+ connection: *mut xcb::ffi::xcb_connection_t,
+) -> Gc {
+ ServerObject {
+ id,
+ connection,
+ free_fn: xcb::ffi::xcb_free_gc,
+ }
+}
+
+type Pixmap = ServerObject<xcb::ffi::xcb_pixmap_t>;
+
+unsafe fn create_pixmap(
+ id: xcb::ffi::xcb_pixmap_t,
+ connection: *mut xcb::ffi::xcb_connection_t,
+) -> Pixmap {
+ ServerObject {
+ id,
+ connection,
+ free_fn: xcb::ffi::xcb_free_pixmap,
+ }
+}
+
+type ShmSeg = ServerObject<xcb::ffi::shm::xcb_shm_seg_t>;
+
+unsafe fn create_shm_seg(
+ id: xcb::ffi::shm::xcb_shm_seg_t,
+ connection: *mut xcb::ffi::xcb_connection_t,
+) -> ShmSeg {
+ ServerObject {
+ id,
+ connection,
+ free_fn: xcb::ffi::shm::xcb_shm_detach,
+ }
+}
+
+enum SurfaceFormatGroup {
+ B8G8R8A8,
+}
+
+enum SwapchainSetupError {
+ BadSurface,
+ NoSupport,
+}
+
+unsafe fn query_extension(
+ connection: *mut xcb::ffi::xcb_connection_t,
+ extension_name: &str,
+) -> xcb::ffi::xcb_query_extension_cookie_t {
+ let len = extension_name.len() as u16;
+ assert_eq!(len as usize, extension_name.len());
+ xcb::ffi::xcb_query_extension(connection, len, extension_name.as_ptr() as *const c_char)
+}
+
+pub const MAX_SWAPCHAIN_IMAGE_COUNT: u32 = 16;
+
+struct SwapchainSetupFirstStage {
+ gc: Gc,
+ shm_supported: bool,
+ window_depth: u8,
+ surface_format_group: SurfaceFormatGroup,
+ present_modes: &'static [api::VkPresentModeKHR],
+ capabilities: api::VkSurfaceCapabilitiesKHR,
+ shared_present_capabilities: Option<api::VkSharedPresentSurfaceCapabilitiesKHR>,
+ image_pixel_size: usize,
+ scanline_alignment: usize,
+ shm_version: Option<xcb::ffi::shm::xcb_shm_query_version_cookie_t>,
+ image_descriptor: ImageDescriptor,
+}
+
+impl SwapchainSetupFirstStage {
+ unsafe fn new(
+ connection: *mut xcb::ffi::xcb_connection_t,
+ window: xcb::ffi::xcb_window_t,
+ is_full_setup: bool,
+ ) -> Result<Self, SwapchainSetupError> {
+ let has_mit_shm = query_extension(connection, "MIT-SHM");
+ let geometry = xcb::ffi::xcb_get_geometry(connection, window);
+ let window_attributes = xcb::ffi::xcb_get_window_attributes(connection, window);
+ let tree = xcb::ffi::xcb_query_tree(connection, window);
+ let gc = xcb::ffi::xcb_generate_id(connection);
+ xcb::ffi::xcb_create_gc(
+ connection,
+ gc,
+ window,
+ xcb::ffi::XCB_GC_GRAPHICS_EXPOSURES,
+ [0].as_ptr(),
+ );
+ let gc = create_gc(gc, connection);
+ let has_mit_shm = ReplyObject::from(xcb::ffi::xcb_query_extension_reply(
+ connection,
+ has_mit_shm,
+ null_mut(),
+ ));
+ let shm_supported = has_mit_shm.map(|v| v.present != 0).unwrap_or(false);
+ let shm_version = if is_full_setup && shm_supported {
+ Some(xcb::ffi::shm::xcb_shm_query_version(connection))
+ } else {
+ None
+ };
+ let geometry = ReplyObject::from(xcb::ffi::xcb_get_geometry_reply(
+ connection,
+ geometry,
+ null_mut(),
+ ))
+ .ok_or(SwapchainSetupError::BadSurface)?;
+ let image_extent = api::VkExtent2D {
+ width: geometry.width as u32,
+ height: geometry.height as u32,
+ };
+ mem::drop(geometry);
+ let window_attributes = ReplyObject::from(xcb::ffi::xcb_get_window_attributes_reply(
+ connection,
+ window_attributes,
+ null_mut(),
+ ))
+ .ok_or(SwapchainSetupError::BadSurface)?;
+ let window_visual_id = window_attributes.visual;
+ mem::drop(window_attributes);
+ let tree = ReplyObject::from(xcb::ffi::xcb_query_tree_reply(connection, tree, null_mut()))
+ .ok_or(SwapchainSetupError::BadSurface)?;
+ let root_window = tree.root;
+ mem::drop(tree);
+ let mut screen = None;
+ let mut roots_iter =
+ xcb::ffi::xcb_setup_roots_iterator(xcb::ffi::xcb_get_setup(connection));
+ while roots_iter.rem != 0 {
+ if (*roots_iter.data).root == root_window {
+ screen = Some(roots_iter.data);
+ break;
+ }
+ xcb::ffi::xcb_screen_next(&mut roots_iter);
+ }
+ let screen = screen.ok_or(SwapchainSetupError::BadSurface)?;
+ let mut window_visual_type_and_depth = None;
+ let mut depth_iter = xcb::ffi::xcb_screen_allowed_depths_iterator(screen);
+ while depth_iter.rem != 0 {
+ let mut visual_iter = xcb::ffi::xcb_depth_visuals_iterator(depth_iter.data);
+ while visual_iter.rem != 0 {
+ if (*visual_iter.data).visual_id == window_visual_id {
+ window_visual_type_and_depth =
+ Some((visual_iter.data, (*depth_iter.data).depth));
+ break;
+ }
+ xcb::ffi::xcb_visualtype_next(&mut visual_iter);
+ }
+ if window_visual_type_and_depth.is_some() {
+ break;
+ }
+ xcb::ffi::xcb_depth_next(&mut depth_iter);
+ }
+ let (window_visual_type, window_depth) =
+ window_visual_type_and_depth.ok_or(SwapchainSetupError::BadSurface)?;
+ let ref window_visual_type = *window_visual_type;
+ let red_mask = window_visual_type.red_mask;
+ let green_mask = window_visual_type.green_mask;
+ let blue_mask = window_visual_type.blue_mask;
+ let alpha_mask = match window_depth {
+ 24 => 0,
+ 32 => !(red_mask | green_mask | blue_mask),
+ _ => return Err(SwapchainSetupError::NoSupport),
+ };
+ let mut window_pixmap_format = None;
+ let mut formats_iter =
+ xcb::ffi::xcb_setup_pixmap_formats_iterator(xcb::ffi::xcb_get_setup(connection));
+ while formats_iter.rem != 0 {
+ if (*formats_iter.data).depth == window_depth {
+ window_pixmap_format = Some(formats_iter.data);
+ break;
+ }
+ xcb::ffi::xcb_format_next(&mut formats_iter);
+ }
+ let ref window_pixmap_format =
+ *(window_pixmap_format.ok_or(SwapchainSetupError::BadSurface)?);
+ let image_pixel_size = match window_pixmap_format.bits_per_pixel {
+ 24 => 3,
+ 32 => 4,
+ _ => return Err(SwapchainSetupError::NoSupport),
+ };
+ fn u32_from_bytes(v: [u8; 4]) -> u32 {
+ unsafe { mem::transmute(v) }
+ }
+ let surface_format_group = match (
+ u32_from_bytes([0xFF, 0, 0, 0]),
+ u32_from_bytes([0, 0xFF, 0, 0]),
+ u32_from_bytes([0, 0, 0xFF, 0]),
+ u32_from_bytes([0, 0, 0, 0xFF]),
+ ) {
+ (r, g, b, a)
+ if r == red_mask
+ && g == green_mask
+ && b == blue_mask
+ && (alpha_mask == 0 || a == alpha_mask) =>
+ {
+ SurfaceFormatGroup::B8G8R8A8
+ }
+ _ => return Err(SwapchainSetupError::NoSupport),
+ };
+ let scanline_alignment = match window_pixmap_format.scanline_pad {
+ 8 => 1,
+ 16 => 2,
+ 32 => 4,
+ _ => unreachable!("invalid pixmap format scanline_pad"),
+ };
+ const PRESENT_MODES: &'static [api::VkPresentModeKHR] = &[
+ api::VK_PRESENT_MODE_FIFO_KHR, // FIXME: properly implement FIFO present mode using X11 Present extension
+ api::VK_PRESENT_MODE_IMMEDIATE_KHR,
+ ];
+ Ok(Self {
+ gc,
+ shm_supported,
+ window_depth,
+ surface_format_group,
+ present_modes: PRESENT_MODES,
+ capabilities: api::VkSurfaceCapabilitiesKHR {
+ minImageCount: 2,
+ maxImageCount: MAX_SWAPCHAIN_IMAGE_COUNT,
+ currentExtent: image_extent,
+ minImageExtent: image_extent,
+ maxImageExtent: image_extent,
+ maxImageArrayLayers: 1,
+ supportedTransforms: api::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
+ currentTransform: api::VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
+ supportedCompositeAlpha: api::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
+ supportedUsageFlags: api::VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+ | api::VK_IMAGE_USAGE_TRANSFER_DST_BIT
+ | api::VK_IMAGE_USAGE_SAMPLED_BIT
+ | api::VK_IMAGE_USAGE_STORAGE_BIT
+ | api::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+ | api::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
+ },
+ shared_present_capabilities: None,
+ image_pixel_size,
+ scanline_alignment,
+ shm_version,
+ image_descriptor: ImageDescriptor {
+ supported_tilings: SupportedTilings::Any,
+ format: api::VK_FORMAT_UNDEFINED,
+ extents: api::VkExtent3D {
+ width: image_extent.width,
+ height: image_extent.height,
+ depth: 1,
+ },
+ mip_levels: 1,
+ },
+ })
+ }
+}
+
+impl XcbSwapchain {
+ unsafe fn new(
+ create_info: &api::VkSwapchainCreateInfoKHR,
+ device_group_create_info: Option<&api::VkDeviceGroupSwapchainCreateInfoKHR>,
+ ) -> Result<Self, api::VkResult> {
+ unimplemented!()
+ }
+}
+
+#[derive(Debug)]
+pub struct XcbSurfaceImplementation;
+
+impl XcbSurfaceImplementation {
+ unsafe fn get_surface(&self, surface: api::VkSurfaceKHR) -> &api::VkIcdSurfaceXcb {
+ let surface = surface.get().unwrap().as_ptr();
+ assert_eq!((*surface).platform, api::VK_ICD_WSI_PLATFORM_XCB);
+ &*(surface as *const api::VkIcdSurfaceXcb)
+ }
+}
+
+impl SurfaceImplementation for XcbSurfaceImplementation {
+ fn get_platform(&self) -> SurfacePlatform {
+ SurfacePlatform::VK_ICD_WSI_PLATFORM_XCB
+ }
+ unsafe fn get_surface_formats(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkSurfaceFormatKHR]>, api::VkResult> {
+ let surface = &self.get_surface(surface);
+ let first_stage = SwapchainSetupFirstStage::new(surface.connection, surface.window, false)
+ .map_err(|v| match v {
+ SwapchainSetupError::BadSurface | SwapchainSetupError::NoSupport => {
+ api::VK_ERROR_SURFACE_LOST_KHR
+ }
+ })?;
+ match first_stage.surface_format_group {
+ SurfaceFormatGroup::B8G8R8A8 => {
+ const SURFACE_FORMATS: &'static [api::VkSurfaceFormatKHR] = &[
+ api::VkSurfaceFormatKHR {
+ format: api::VK_FORMAT_B8G8R8A8_SRGB,
+ colorSpace: api::VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ },
+ api::VkSurfaceFormatKHR {
+ format: api::VK_FORMAT_B8G8R8A8_UNORM,
+ colorSpace: api::VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ },
+ ];
+ Ok(Cow::Borrowed(SURFACE_FORMATS))
+ }
+ }
+ }
+ unsafe fn get_present_modes(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<Cow<'static, [api::VkPresentModeKHR]>, api::VkResult> {
+ let surface = &self.get_surface(surface);
+ let first_stage = SwapchainSetupFirstStage::new(surface.connection, surface.window, false)
+ .map_err(|v| match v {
+ SwapchainSetupError::BadSurface | SwapchainSetupError::NoSupport => {
+ api::VK_ERROR_SURFACE_LOST_KHR
+ }
+ })?;
+ Ok(Cow::Borrowed(first_stage.present_modes))
+ }
+ unsafe fn get_capabilities(
+ &self,
+ surface: api::VkSurfaceKHR,
+ ) -> Result<api::VkSurfaceCapabilitiesKHR, api::VkResult> {
+ let surface = &self.get_surface(surface);
+ let first_stage = SwapchainSetupFirstStage::new(surface.connection, surface.window, false)
+ .map_err(|v| match v {
+ SwapchainSetupError::BadSurface | SwapchainSetupError::NoSupport => {
+ api::VK_ERROR_SURFACE_LOST_KHR
+ }
+ })?;
+ Ok(first_stage.capabilities)
+ }
+ unsafe fn build(
+ &self,
+ create_info: &api::VkSwapchainCreateInfoKHR,
+ device_group_create_info: Option<&api::VkDeviceGroupSwapchainCreateInfoKHR>,
+ ) -> Result<Box<Swapchain>, api::VkResult> {
+ Ok(Box::new(XcbSwapchain::new(
+ create_info,
+ device_group_create_info,
+ )?))
+ }
+ fn duplicate(&self) -> Box<dyn SurfaceImplementation> {
+ Box::new(Self {})
+ }
+}
#ifdef __ANDROID__
#error not supported on Android; need to fix ABI
#endif
+#ifdef __unix
+#define VK_USE_PLATFORM_XCB_KHR
+#endif
#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
#include <vulkan/vk_icd.h>
-#ifdef __unix
-typedef struct xcb_connection_t xcb_connection_t;
-typedef uint32_t xcb_visualid_t;
-typedef uint32_t xcb_window_t;
-#include <vulkan/vulkan_xcb.h>
-#endif
#undef VK_NO_PROTOTYPES
+#ifdef VK_USE_PLATFORM_XCB_KHR
+#undef VK_USE_PLATFORM_XCB_KHR
+#endif