use super::FullScreenExclusive;
use super::Win32Monitor;
use crate::check_errors;
use crate::image::ImageUsage;
use crate::instance::Instance;
use crate::swapchain::display::DisplayMode;
use crate::swapchain::display::DisplayPlane;
use crate::swapchain::SurfaceSwapchainLock;
use crate::Error;
use crate::OomError;
use crate::VulkanObject;
use std::error;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem::MaybeUninit;
use std::os::raw::c_ulong;
use std::ptr;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
pub struct Surface<W> {
handle: ash::vk::SurfaceKHR,
instance: Arc<Instance>,
api: SurfaceApi,
window: W,
has_swapchain: AtomicBool,
}
impl<W> Surface<W> {
pub unsafe fn from_raw_surface(
instance: Arc<Instance>,
handle: ash::vk::SurfaceKHR,
api: SurfaceApi,
win: W,
) -> Surface<W> {
Surface {
handle,
instance,
api,
window: win,
has_swapchain: AtomicBool::new(false),
}
}
pub fn from_display_plane(
display_mode: &DisplayMode,
plane: &DisplayPlane,
) -> Result<Arc<Surface<()>>, SurfaceCreationError> {
if !display_mode
.display()
.physical_device()
.instance()
.enabled_extensions()
.khr_display
{
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_display",
});
}
assert_eq!(
display_mode.display().physical_device().internal_object(),
plane.physical_device().internal_object()
);
assert!(plane.supports(display_mode.display()));
let instance = display_mode.display().physical_device().instance();
let create_info = ash::vk::DisplaySurfaceCreateInfoKHR {
flags: ash::vk::DisplaySurfaceCreateFlagsKHR::empty(),
display_mode: display_mode.internal_object(),
plane_index: plane.index(),
plane_stack_index: 0, transform: ash::vk::SurfaceTransformFlagsKHR::IDENTITY, global_alpha: 0.0, alpha_mode: ash::vk::DisplayPlaneAlphaFlagsKHR::OPAQUE, image_extent: ash::vk::Extent2D {
width: display_mode.visible_region()[0],
height: display_mode.visible_region()[1],
},
..Default::default()
};
let handle = unsafe {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_display.create_display_plane_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance: instance.clone(),
api: SurfaceApi::DisplayPlane,
window: (),
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_android<T>(
instance: Arc<Instance>,
window: *const T,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().khr_android_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_android_surface",
});
}
let create_info = ash::vk::AndroidSurfaceCreateInfoKHR {
flags: ash::vk::AndroidSurfaceCreateFlagsKHR::empty(),
window: window as *mut _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_android_surface.create_android_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Android,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_ios<T>(
instance: Arc<Instance>,
view: *const T,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().mvk_ios_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_MVK_ios_surface",
});
}
let create_info = ash::vk::IOSSurfaceCreateInfoMVK {
flags: ash::vk::IOSSurfaceCreateFlagsMVK::empty(),
p_view: view as *const _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.mvk_ios_surface.create_ios_surface_mvk(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Ios,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_mac_os<T>(
instance: Arc<Instance>,
view: *const T,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().mvk_macos_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_MVK_macos_surface",
});
}
let create_info = ash::vk::MacOSSurfaceCreateInfoMVK {
flags: ash::vk::MacOSSurfaceCreateFlagsMVK::empty(),
p_view: view as *const _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.mvk_macos_surface.create_mac_os_surface_mvk(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::MacOs,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_metal<T>(
instance: Arc<Instance>,
layer: *const T,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().ext_metal_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_EXT_metal_surface",
});
}
let create_info = ash::vk::MetalSurfaceCreateInfoEXT {
flags: ash::vk::MetalSurfaceCreateFlagsEXT::empty(),
p_layer: layer as *const _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.ext_metal_surface.create_metal_surface_ext(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Metal,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_vi<T>(
instance: Arc<Instance>,
window: *const T,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().nn_vi_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_NN_vi_surface",
});
}
let create_info = ash::vk::ViSurfaceCreateInfoNN {
flags: ash::vk::ViSurfaceCreateFlagsNN::empty(),
window: window as *mut _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.nn_vi_surface.create_vi_surface_nn(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Vi,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_wayland<D, S>(
instance: Arc<Instance>,
display: *const D,
surface: *const S,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().khr_wayland_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_wayland_surface",
});
}
let create_info = ash::vk::WaylandSurfaceCreateInfoKHR {
flags: ash::vk::WaylandSurfaceCreateFlagsKHR::empty(),
display: display as *mut _,
surface: surface as *mut _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_wayland_surface.create_wayland_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Wayland,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_win32<T, U>(
instance: Arc<Instance>,
hinstance: *const T,
hwnd: *const U,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().khr_win32_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_win32_surface",
});
}
let create_info = ash::vk::Win32SurfaceCreateInfoKHR {
flags: ash::vk::Win32SurfaceCreateFlagsKHR::empty(),
hinstance: hinstance as *mut _,
hwnd: hwnd as *mut _,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_win32_surface.create_win32_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Win32,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_xcb<C>(
instance: Arc<Instance>,
connection: *const C,
window: u32,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().khr_xcb_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_xcb_surface",
});
}
let create_info = ash::vk::XcbSurfaceCreateInfoKHR {
flags: ash::vk::XcbSurfaceCreateFlagsKHR::empty(),
connection: connection as *mut _,
window,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_xcb_surface.create_xcb_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Xcb,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
pub unsafe fn from_xlib<D>(
instance: Arc<Instance>,
display: *const D,
window: c_ulong,
win: W,
) -> Result<Arc<Surface<W>>, SurfaceCreationError> {
if !instance.enabled_extensions().khr_xlib_surface {
return Err(SurfaceCreationError::MissingExtension {
name: "VK_KHR_xlib_surface",
});
}
let create_info = ash::vk::XlibSurfaceCreateInfoKHR {
flags: ash::vk::XlibSurfaceCreateFlagsKHR::empty(),
dpy: display as *mut _,
window,
..Default::default()
};
let handle = {
let fns = instance.fns();
let mut output = MaybeUninit::uninit();
check_errors(fns.khr_xlib_surface.create_xlib_surface_khr(
instance.internal_object(),
&create_info,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Arc::new(Surface {
handle,
instance,
api: SurfaceApi::Xlib,
window: win,
has_swapchain: AtomicBool::new(false),
}))
}
#[inline]
pub fn instance(&self) -> &Arc<Instance> {
&self.instance
}
#[inline]
pub fn api(&self) -> SurfaceApi {
self.api
}
#[inline]
pub fn window(&self) -> &W {
&self.window
}
}
impl<W> Drop for Surface<W> {
#[inline]
fn drop(&mut self) {
unsafe {
let fns = self.instance.fns();
fns.khr_surface.destroy_surface_khr(
self.instance.internal_object(),
self.handle,
ptr::null(),
);
}
}
}
unsafe impl<W> VulkanObject for Surface<W> {
type Object = ash::vk::SurfaceKHR;
#[inline]
fn internal_object(&self) -> ash::vk::SurfaceKHR {
self.handle
}
}
impl<W> fmt::Debug for Surface<W> {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let Self {
handle,
instance,
api,
window: _,
has_swapchain,
} = self;
fmt.debug_struct("Surface")
.field("handle", handle)
.field("instance", instance)
.field("api", api)
.field("window", &())
.field("has_swapchain", &has_swapchain)
.finish()
}
}
impl<W> PartialEq for Surface<W> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.handle == other.handle && self.instance() == other.instance()
}
}
impl<W> Eq for Surface<W> {}
impl<W> Hash for Surface<W> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.handle.hash(state);
self.instance().hash(state);
}
}
unsafe impl<W> SurfaceSwapchainLock for Surface<W> {
#[inline]
fn flag(&self) -> &AtomicBool {
&self.has_swapchain
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SurfaceCreationError {
OomError(OomError),
MissingExtension {
name: &'static str,
},
}
impl error::Error for SurfaceCreationError {
#[inline]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
SurfaceCreationError::OomError(ref err) => Some(err),
_ => None,
}
}
}
impl fmt::Display for SurfaceCreationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
fmt,
"{}",
match *self {
SurfaceCreationError::OomError(_) => "not enough memory available",
SurfaceCreationError::MissingExtension { .. } => {
"the extension required for this function was not enabled"
}
}
)
}
}
impl From<OomError> for SurfaceCreationError {
#[inline]
fn from(err: OomError) -> SurfaceCreationError {
SurfaceCreationError::OomError(err)
}
}
impl From<Error> for SurfaceCreationError {
#[inline]
fn from(err: Error) -> SurfaceCreationError {
match err {
err @ Error::OutOfHostMemory => SurfaceCreationError::OomError(OomError::from(err)),
err @ Error::OutOfDeviceMemory => SurfaceCreationError::OomError(OomError::from(err)),
_ => panic!("unexpected error: {:?}", err),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SurfaceApi {
DisplayPlane,
Android,
Ios,
MacOs,
Metal,
Vi,
Wayland,
Win32,
Xcb,
Xlib,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
#[non_exhaustive]
pub enum PresentMode {
Immediate = ash::vk::PresentModeKHR::IMMEDIATE.as_raw(),
Mailbox = ash::vk::PresentModeKHR::MAILBOX.as_raw(),
Fifo = ash::vk::PresentModeKHR::FIFO.as_raw(),
FifoRelaxed = ash::vk::PresentModeKHR::FIFO_RELAXED.as_raw(),
}
impl From<PresentMode> for ash::vk::PresentModeKHR {
#[inline]
fn from(val: PresentMode) -> Self {
Self::from_raw(val as i32)
}
}
impl TryFrom<ash::vk::PresentModeKHR> for PresentMode {
type Error = ();
fn try_from(value: ash::vk::PresentModeKHR) -> Result<Self, Self::Error> {
Ok(match value {
ash::vk::PresentModeKHR::IMMEDIATE => Self::Immediate,
ash::vk::PresentModeKHR::MAILBOX => Self::Mailbox,
ash::vk::PresentModeKHR::FIFO => Self::Fifo,
ash::vk::PresentModeKHR::FIFO_RELAXED => Self::FifoRelaxed,
_ => return Err(()),
})
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
#[non_exhaustive]
pub enum SurfaceTransform {
Identity = ash::vk::SurfaceTransformFlagsKHR::IDENTITY.as_raw(),
Rotate90 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_90.as_raw(),
Rotate180 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_180.as_raw(),
Rotate270 = ash::vk::SurfaceTransformFlagsKHR::ROTATE_270.as_raw(),
HorizontalMirror = ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR.as_raw(),
HorizontalMirrorRotate90 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_90.as_raw(),
HorizontalMirrorRotate180 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_180.as_raw(),
HorizontalMirrorRotate270 =
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_270.as_raw(),
Inherit = ash::vk::SurfaceTransformFlagsKHR::INHERIT.as_raw(),
}
impl From<SurfaceTransform> for ash::vk::SurfaceTransformFlagsKHR {
#[inline]
fn from(val: SurfaceTransform) -> Self {
Self::from_raw(val as u32)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct SupportedSurfaceTransforms {
pub identity: bool,
pub rotate90: bool,
pub rotate180: bool,
pub rotate270: bool,
pub horizontal_mirror: bool,
pub horizontal_mirror_rotate90: bool,
pub horizontal_mirror_rotate180: bool,
pub horizontal_mirror_rotate270: bool,
pub inherit: bool,
}
impl From<ash::vk::SurfaceTransformFlagsKHR> for SupportedSurfaceTransforms {
fn from(val: ash::vk::SurfaceTransformFlagsKHR) -> Self {
macro_rules! v {
($val:expr, $out:ident, $e:expr, $f:ident) => {
if !($val & $e).is_empty() {
$out.$f = true;
}
};
}
let mut result = SupportedSurfaceTransforms::none();
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::IDENTITY,
identity
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_90,
rotate90
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_180,
rotate180
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::ROTATE_270,
rotate270
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR,
horizontal_mirror
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_90,
horizontal_mirror_rotate90
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_180,
horizontal_mirror_rotate180
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::HORIZONTAL_MIRROR_ROTATE_270,
horizontal_mirror_rotate270
);
v!(
val,
result,
ash::vk::SurfaceTransformFlagsKHR::INHERIT,
inherit
);
result
}
}
impl SupportedSurfaceTransforms {
#[inline]
pub fn none() -> SupportedSurfaceTransforms {
SupportedSurfaceTransforms {
identity: false,
rotate90: false,
rotate180: false,
rotate270: false,
horizontal_mirror: false,
horizontal_mirror_rotate90: false,
horizontal_mirror_rotate180: false,
horizontal_mirror_rotate270: false,
inherit: false,
}
}
#[inline]
pub fn supports(&self, value: SurfaceTransform) -> bool {
match value {
SurfaceTransform::Identity => self.identity,
SurfaceTransform::Rotate90 => self.rotate90,
SurfaceTransform::Rotate180 => self.rotate180,
SurfaceTransform::Rotate270 => self.rotate270,
SurfaceTransform::HorizontalMirror => self.horizontal_mirror,
SurfaceTransform::HorizontalMirrorRotate90 => self.horizontal_mirror_rotate90,
SurfaceTransform::HorizontalMirrorRotate180 => self.horizontal_mirror_rotate180,
SurfaceTransform::HorizontalMirrorRotate270 => self.horizontal_mirror_rotate270,
SurfaceTransform::Inherit => self.inherit,
}
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = SurfaceTransform> {
let moved = *self;
[
SurfaceTransform::Identity,
SurfaceTransform::Rotate90,
SurfaceTransform::Rotate180,
SurfaceTransform::Rotate270,
SurfaceTransform::HorizontalMirror,
SurfaceTransform::HorizontalMirrorRotate90,
SurfaceTransform::HorizontalMirrorRotate180,
SurfaceTransform::HorizontalMirrorRotate270,
SurfaceTransform::Inherit,
]
.into_iter()
.filter(move |&mode| moved.supports(mode))
}
}
impl Default for SurfaceTransform {
#[inline]
fn default() -> SurfaceTransform {
SurfaceTransform::Identity
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
#[non_exhaustive]
pub enum CompositeAlpha {
Opaque = ash::vk::CompositeAlphaFlagsKHR::OPAQUE.as_raw(),
PreMultiplied = ash::vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED.as_raw(),
PostMultiplied = ash::vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED.as_raw(),
Inherit = ash::vk::CompositeAlphaFlagsKHR::INHERIT.as_raw(),
}
impl From<CompositeAlpha> for ash::vk::CompositeAlphaFlagsKHR {
#[inline]
fn from(val: CompositeAlpha) -> Self {
Self::from_raw(val as u32)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct SupportedCompositeAlpha {
pub opaque: bool,
pub pre_multiplied: bool,
pub post_multiplied: bool,
pub inherit: bool,
}
impl From<ash::vk::CompositeAlphaFlagsKHR> for SupportedCompositeAlpha {
#[inline]
fn from(val: ash::vk::CompositeAlphaFlagsKHR) -> SupportedCompositeAlpha {
let mut result = SupportedCompositeAlpha::none();
if !(val & ash::vk::CompositeAlphaFlagsKHR::OPAQUE).is_empty() {
result.opaque = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED).is_empty() {
result.pre_multiplied = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED).is_empty() {
result.post_multiplied = true;
}
if !(val & ash::vk::CompositeAlphaFlagsKHR::INHERIT).is_empty() {
result.inherit = true;
}
result
}
}
impl SupportedCompositeAlpha {
#[inline]
pub fn none() -> SupportedCompositeAlpha {
SupportedCompositeAlpha {
opaque: false,
pre_multiplied: false,
post_multiplied: false,
inherit: false,
}
}
#[inline]
pub fn supports(&self, value: CompositeAlpha) -> bool {
match value {
CompositeAlpha::Opaque => self.opaque,
CompositeAlpha::PreMultiplied => self.pre_multiplied,
CompositeAlpha::PostMultiplied => self.post_multiplied,
CompositeAlpha::Inherit => self.inherit,
}
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = CompositeAlpha> {
let moved = *self;
[
CompositeAlpha::Opaque,
CompositeAlpha::PreMultiplied,
CompositeAlpha::PostMultiplied,
CompositeAlpha::Inherit,
]
.into_iter()
.filter(move |&mode| moved.supports(mode))
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)]
#[non_exhaustive]
pub enum ColorSpace {
SrgbNonLinear = ash::vk::ColorSpaceKHR::SRGB_NONLINEAR.as_raw(),
DisplayP3NonLinear = ash::vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT.as_raw(),
ExtendedSrgbLinear = ash::vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT.as_raw(),
ExtendedSrgbNonLinear = ash::vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT.as_raw(),
DisplayP3Linear = ash::vk::ColorSpaceKHR::DISPLAY_P3_LINEAR_EXT.as_raw(),
DciP3NonLinear = ash::vk::ColorSpaceKHR::DCI_P3_NONLINEAR_EXT.as_raw(),
Bt709Linear = ash::vk::ColorSpaceKHR::BT709_LINEAR_EXT.as_raw(),
Bt709NonLinear = ash::vk::ColorSpaceKHR::BT709_NONLINEAR_EXT.as_raw(),
Bt2020Linear = ash::vk::ColorSpaceKHR::BT2020_LINEAR_EXT.as_raw(),
Hdr10St2084 = ash::vk::ColorSpaceKHR::HDR10_ST2084_EXT.as_raw(),
DolbyVision = ash::vk::ColorSpaceKHR::DOLBYVISION_EXT.as_raw(),
Hdr10Hlg = ash::vk::ColorSpaceKHR::HDR10_HLG_EXT.as_raw(),
AdobeRgbLinear = ash::vk::ColorSpaceKHR::ADOBERGB_LINEAR_EXT.as_raw(),
AdobeRgbNonLinear = ash::vk::ColorSpaceKHR::ADOBERGB_NONLINEAR_EXT.as_raw(),
PassThrough = ash::vk::ColorSpaceKHR::PASS_THROUGH_EXT.as_raw(),
DisplayNative = ash::vk::ColorSpaceKHR::DISPLAY_NATIVE_AMD.as_raw(),
}
impl From<ColorSpace> for ash::vk::ColorSpaceKHR {
#[inline]
fn from(val: ColorSpace) -> Self {
Self::from_raw(val as i32)
}
}
impl From<ash::vk::ColorSpaceKHR> for ColorSpace {
#[inline]
fn from(val: ash::vk::ColorSpaceKHR) -> Self {
match val {
ash::vk::ColorSpaceKHR::SRGB_NONLINEAR => ColorSpace::SrgbNonLinear,
ash::vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT => ColorSpace::DisplayP3NonLinear,
ash::vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT => ColorSpace::ExtendedSrgbLinear,
ash::vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT => {
ColorSpace::ExtendedSrgbNonLinear
}
ash::vk::ColorSpaceKHR::DISPLAY_P3_LINEAR_EXT => ColorSpace::DisplayP3Linear,
ash::vk::ColorSpaceKHR::DCI_P3_NONLINEAR_EXT => ColorSpace::DciP3NonLinear,
ash::vk::ColorSpaceKHR::BT709_LINEAR_EXT => ColorSpace::Bt709Linear,
ash::vk::ColorSpaceKHR::BT709_NONLINEAR_EXT => ColorSpace::Bt709NonLinear,
ash::vk::ColorSpaceKHR::BT2020_LINEAR_EXT => ColorSpace::Bt2020Linear,
ash::vk::ColorSpaceKHR::HDR10_ST2084_EXT => ColorSpace::Hdr10St2084,
ash::vk::ColorSpaceKHR::DOLBYVISION_EXT => ColorSpace::DolbyVision,
ash::vk::ColorSpaceKHR::HDR10_HLG_EXT => ColorSpace::Hdr10Hlg,
ash::vk::ColorSpaceKHR::ADOBERGB_LINEAR_EXT => ColorSpace::AdobeRgbLinear,
ash::vk::ColorSpaceKHR::ADOBERGB_NONLINEAR_EXT => ColorSpace::AdobeRgbNonLinear,
ash::vk::ColorSpaceKHR::PASS_THROUGH_EXT => ColorSpace::PassThrough,
ash::vk::ColorSpaceKHR::DISPLAY_NATIVE_AMD => ColorSpace::DisplayNative,
_ => panic!("Wrong value for color space enum {:?}", val),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SurfaceInfo {
pub full_screen_exclusive: FullScreenExclusive,
pub win32_monitor: Option<Win32Monitor>,
pub _ne: crate::NonExhaustive,
}
impl Default for SurfaceInfo {
#[inline]
fn default() -> Self {
Self {
full_screen_exclusive: FullScreenExclusive::Default,
win32_monitor: None,
_ne: crate::NonExhaustive(()),
}
}
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct SurfaceCapabilities {
pub min_image_count: u32,
pub max_image_count: Option<u32>,
pub current_extent: Option<[u32; 2]>,
pub min_image_extent: [u32; 2],
pub max_image_extent: [u32; 2],
pub max_image_array_layers: u32,
pub supported_transforms: SupportedSurfaceTransforms,
pub current_transform: SurfaceTransform,
pub supported_composite_alpha: SupportedCompositeAlpha,
pub supported_usage_flags: ImageUsage,
pub full_screen_exclusive_supported: bool,
}
#[cfg(test)]
mod tests {
use crate::swapchain::Surface;
use crate::swapchain::SurfaceCreationError;
use std::ptr;
#[test]
fn khr_win32_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
}
#[test]
fn khr_xcb_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
}
#[test]
fn khr_xlib_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
}
#[test]
fn khr_wayland_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
}
#[test]
fn khr_android_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_android(instance, ptr::null::<u8>(), ()) } {
Err(SurfaceCreationError::MissingExtension { .. }) => (),
_ => panic!(),
}
}
}