#![allow(dead_code)] #![allow(unused_variables)]
use crate::{
device::physical::PhysicalDevice, swapchain::SupportedSurfaceTransforms, OomError, VulkanError,
VulkanObject,
};
use std::{
ffi::CStr,
fmt::{Display as FmtDisplay, Error as FmtError, Formatter},
ptr,
sync::Arc,
vec::IntoIter,
};
pub struct DisplayPlane {
physical_device: Arc<PhysicalDevice>,
index: u32,
properties: ash::vk::DisplayPlanePropertiesKHR,
supported_displays: Vec<ash::vk::DisplayKHR>,
}
impl DisplayPlane {
pub fn enumerate_raw(
physical_device: Arc<PhysicalDevice>,
) -> Result<IntoIter<DisplayPlane>, OomError> {
let fns = physical_device.instance().fns();
assert!(physical_device.instance().enabled_extensions().khr_display);
let display_plane_properties = unsafe {
loop {
let mut count = 0;
(fns.khr_display
.get_physical_device_display_plane_properties_khr)(
physical_device.handle(),
&mut count,
ptr::null_mut(),
)
.result()
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns
.khr_display
.get_physical_device_display_plane_properties_khr)(
physical_device.handle(),
&mut count,
properties.as_mut_ptr(),
);
match result {
ash::vk::Result::SUCCESS => {
properties.set_len(count as usize);
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(VulkanError::from(err).into()),
}
}
};
Ok(display_plane_properties
.into_iter()
.enumerate()
.map(|(index, prop)| {
let supported_displays = unsafe {
loop {
let mut count = 0;
(fns.khr_display.get_display_plane_supported_displays_khr)(
physical_device.handle(),
index as u32,
&mut count,
ptr::null_mut(),
)
.result()
.map_err(VulkanError::from)
.unwrap();
let mut displays = Vec::with_capacity(count as usize);
let result = (fns.khr_display.get_display_plane_supported_displays_khr)(
physical_device.handle(),
index as u32,
&mut count,
displays.as_mut_ptr(),
);
match result {
ash::vk::Result::SUCCESS => {
displays.set_len(count as usize);
break displays;
}
ash::vk::Result::INCOMPLETE => (),
err => todo!(), }
}
};
DisplayPlane {
physical_device: physical_device.clone(),
index: index as u32,
properties: prop,
supported_displays,
}
})
.collect::<Vec<_>>()
.into_iter())
}
#[inline]
pub fn enumerate(physical_device: Arc<PhysicalDevice>) -> IntoIter<DisplayPlane> {
DisplayPlane::enumerate_raw(physical_device).unwrap()
}
#[inline]
pub fn physical_device(&self) -> &Arc<PhysicalDevice> {
&self.physical_device
}
#[inline]
pub fn index(&self) -> u32 {
self.index
}
#[inline]
pub fn supports(&self, display: &Display) -> bool {
if self.physical_device().handle() != display.physical_device().handle() {
return false;
}
self.supported_displays
.iter()
.any(|&d| d == display.handle())
}
}
#[derive(Clone)]
pub struct Display {
physical_device: Arc<PhysicalDevice>,
properties: Arc<ash::vk::DisplayPropertiesKHR>, }
impl Display {
pub fn enumerate_raw(
physical_device: Arc<PhysicalDevice>,
) -> Result<IntoIter<Display>, OomError> {
let fns = physical_device.instance().fns();
assert!(physical_device.instance().enabled_extensions().khr_display);
let display_properties = unsafe {
loop {
let mut count = 0;
(fns.khr_display.get_physical_device_display_properties_khr)(
physical_device.handle(),
&mut count,
ptr::null_mut(),
)
.result()
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns.khr_display.get_physical_device_display_properties_khr)(
physical_device.handle(),
&mut count,
properties.as_mut_ptr(),
);
match result {
ash::vk::Result::SUCCESS => {
properties.set_len(count as usize);
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(VulkanError::from(err).into()),
}
}
};
Ok(display_properties
.into_iter()
.map(|prop| Display {
physical_device: physical_device.clone(),
properties: Arc::new(prop),
})
.collect::<Vec<_>>()
.into_iter())
}
#[inline]
pub fn enumerate(physical_device: Arc<PhysicalDevice>) -> IntoIter<Display> {
Display::enumerate_raw(physical_device).unwrap()
}
#[inline]
pub fn name(&self) -> &str {
unsafe {
CStr::from_ptr(self.properties.display_name)
.to_str()
.expect("non UTF-8 characters in display name")
}
}
#[inline]
pub fn physical_device(&self) -> &Arc<PhysicalDevice> {
&self.physical_device
}
#[inline]
pub fn physical_dimensions(&self) -> [u32; 2] {
let r = &self.properties.physical_dimensions;
[r.width, r.height]
}
#[inline]
pub fn physical_resolution(&self) -> [u32; 2] {
let r = &self.properties.physical_resolution;
[r.width, r.height]
}
#[inline]
pub fn supported_transforms(&self) -> SupportedSurfaceTransforms {
self.properties.supported_transforms.into()
}
#[inline]
pub fn plane_reorder_possible(&self) -> bool {
self.properties.plane_reorder_possible != 0
}
#[inline]
pub fn persistent_content(&self) -> bool {
self.properties.persistent_content != 0
}
pub fn display_modes_raw(&self) -> Result<IntoIter<DisplayMode>, OomError> {
let fns = self.physical_device.instance().fns();
let mode_properties = unsafe {
loop {
let mut count = 0;
(fns.khr_display.get_display_mode_properties_khr)(
self.physical_device().handle(),
self.properties.display,
&mut count,
ptr::null_mut(),
)
.result()
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns.khr_display.get_display_mode_properties_khr)(
self.physical_device().handle(),
self.properties.display,
&mut count,
properties.as_mut_ptr(),
);
match result {
ash::vk::Result::SUCCESS => {
properties.set_len(count as usize);
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(VulkanError::from(err).into()),
}
}
};
Ok(mode_properties
.into_iter()
.map(|mode| DisplayMode {
display: self.clone(),
display_mode: mode.display_mode,
parameters: mode.parameters,
})
.collect::<Vec<_>>()
.into_iter())
}
#[inline]
pub fn display_modes(&self) -> IntoIter<DisplayMode> {
self.display_modes_raw().unwrap()
}
}
unsafe impl VulkanObject for Display {
type Handle = ash::vk::DisplayKHR;
#[inline]
fn handle(&self) -> Self::Handle {
self.properties.display
}
}
pub struct DisplayMode {
display: Display,
display_mode: ash::vk::DisplayModeKHR,
parameters: ash::vk::DisplayModeParametersKHR,
}
impl DisplayMode {
#[inline]
pub fn display(&self) -> &Display {
&self.display
}
#[inline]
pub fn visible_region(&self) -> [u32; 2] {
let d = &self.parameters.visible_region;
[d.width, d.height]
}
#[inline]
pub fn refresh_rate(&self) -> u32 {
self.parameters.refresh_rate
}
}
impl FmtDisplay for DisplayMode {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
let visible_region = self.visible_region();
write!(
f,
"{}×{}px @ {}.{:03} Hz",
visible_region[0],
visible_region[1],
self.refresh_rate() / 1000,
self.refresh_rate() % 1000
)
}
}
unsafe impl VulkanObject for DisplayMode {
type Handle = ash::vk::DisplayModeKHR;
#[inline]
fn handle(&self) -> Self::Handle {
self.display_mode
}
}