// Copyright (c) 2016 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. //! Allows you to create surfaces that fill a whole display, outside of the windowing system. //! //! **As far as the author knows, no existing device supports these features. Therefore the code //! here is mostly a draft and needs rework in both the API and the implementation.** //! //! The purpose of the objects in this module is to let you create a `Surface` object that //! represents a location on the screen. This is done in four steps: //! //! - Choose a `Display` where the surface will be located. A `Display` represents a display //! display, usually a monitor. The available displays can be enumerated with //! `Display::enumerate`. //! - Choose a `DisplayMode`, which is the combination of a display, a resolution and a refresh //! rate. You can enumerate the modes available on a display with `Display::display_modes`, or //! attempt to create your own mode with `TODO`. //! - Choose a `DisplayPlane`. A display can show multiple planes in a stacking fashion. //! - Create a `Surface` object with `Surface::from_display_mode` and pass the chosen `DisplayMode` //! and `DisplayPlane`. #![allow(dead_code)] // TODO: this module isn't finished #![allow(unused_variables)] // TODO: this module isn't finished use crate::check_errors; use crate::device::physical::PhysicalDevice; use crate::instance::Instance; use crate::swapchain::SupportedSurfaceTransforms; use crate::OomError; use crate::VulkanObject; use std::ffi::CStr; use std::fmt::Formatter; use std::sync::Arc; use std::vec::IntoIter; use std::{fmt, ptr}; // TODO: extract this to a `display` module and solve the visibility problems /// ? // TODO: plane capabilities // TODO: store properties in the instance? pub struct DisplayPlane { instance: Arc, physical_device: usize, index: u32, properties: ash::vk::DisplayPlanePropertiesKHR, supported_displays: Vec, } impl DisplayPlane { /// See the docs of enumerate(). pub fn enumerate_raw(device: PhysicalDevice) -> Result, OomError> { let fns = device.instance().fns(); assert!(device.instance().enabled_extensions().khr_display); // TODO: return error instead let num = unsafe { let mut num: u32 = 0; check_errors( fns.khr_display .get_physical_device_display_plane_properties_khr( device.internal_object(), &mut num, ptr::null_mut(), ), )?; num }; let planes: Vec = unsafe { let mut planes = Vec::with_capacity(num as usize); let mut num = num; check_errors( fns.khr_display .get_physical_device_display_plane_properties_khr( device.internal_object(), &mut num, planes.as_mut_ptr(), ), )?; planes.set_len(num as usize); planes }; Ok(planes .into_iter() .enumerate() .map(|(index, prop)| { let num = unsafe { let mut num: u32 = 0; check_errors(fns.khr_display.get_display_plane_supported_displays_khr( device.internal_object(), index as u32, &mut num, ptr::null_mut(), )) .unwrap(); // TODO: shouldn't unwrap num }; let supported_displays: Vec = unsafe { let mut displays = Vec::with_capacity(num as usize); let mut num = num; check_errors(fns.khr_display.get_display_plane_supported_displays_khr( device.internal_object(), index as u32, &mut num, displays.as_mut_ptr(), )) .unwrap(); // TODO: shouldn't unwrap displays.set_len(num as usize); displays }; DisplayPlane { instance: device.instance().clone(), physical_device: device.index(), index: index as u32, properties: prop, supported_displays: supported_displays, } }) .collect::>() .into_iter()) } /// Enumerates all the display planes that are available on a given physical device. /// /// # Panic /// /// - Panics if the device or host ran out of memory. /// // TODO: move iterator creation here from raw constructor? #[inline] pub fn enumerate(device: PhysicalDevice) -> IntoIter { DisplayPlane::enumerate_raw(device).unwrap() } /// Returns the physical device that was used to create this display. #[inline] pub fn physical_device(&self) -> PhysicalDevice { PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap() } /// Returns the index of the plane. #[inline] pub fn index(&self) -> u32 { self.index } /// Returns true if this plane supports the given display. #[inline] pub fn supports(&self, display: &Display) -> bool { // making sure that the physical device is the same if self.physical_device().internal_object() != display.physical_device().internal_object() { return false; } self.supported_displays .iter() .find(|&&d| d == display.internal_object()) .is_some() } } /// Represents a monitor connected to a physical device. // TODO: store properties in the instance? #[derive(Clone)] pub struct Display { instance: Arc, physical_device: usize, properties: Arc, // TODO: Arc because struct isn't clone } impl Display { /// See the docs of enumerate(). pub fn enumerate_raw(device: PhysicalDevice) -> Result, OomError> { let fns = device.instance().fns(); assert!(device.instance().enabled_extensions().khr_display); // TODO: return error instead let num = unsafe { let mut num = 0; check_errors(fns.khr_display.get_physical_device_display_properties_khr( device.internal_object(), &mut num, ptr::null_mut(), ))?; num }; let displays: Vec = unsafe { let mut displays = Vec::with_capacity(num as usize); let mut num = num; check_errors(fns.khr_display.get_physical_device_display_properties_khr( device.internal_object(), &mut num, displays.as_mut_ptr(), ))?; displays.set_len(num as usize); displays }; Ok(displays .into_iter() .map(|prop| Display { instance: device.instance().clone(), physical_device: device.index(), properties: Arc::new(prop), }) .collect::>() .into_iter()) } /// Enumerates all the displays that are available on a given physical device. /// /// # Panic /// /// - Panics if the device or host ran out of memory. /// // TODO: move iterator creation here from raw constructor? #[inline] pub fn enumerate(device: PhysicalDevice) -> IntoIter { Display::enumerate_raw(device).unwrap() } /// Returns the name of the display. #[inline] pub fn name(&self) -> &str { unsafe { CStr::from_ptr(self.properties.display_name) .to_str() .expect("non UTF-8 characters in display name") } } /// Returns the physical device that was used to create this display. #[inline] pub fn physical_device(&self) -> PhysicalDevice { PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap() } /// Returns the physical dimensions of the display in millimeters. #[inline] pub fn physical_dimensions(&self) -> [u32; 2] { let ref r = self.properties.physical_dimensions; [r.width, r.height] } /// Returns the physical, native, or preferred resolution of the display. /// /// > **Note**: The display is usually still capable of displaying other resolutions. This is /// > only the "best" resolution. #[inline] pub fn physical_resolution(&self) -> [u32; 2] { let ref r = self.properties.physical_resolution; [r.width, r.height] } /// Returns the transforms supported by this display. #[inline] pub fn supported_transforms(&self) -> SupportedSurfaceTransforms { self.properties.supported_transforms.into() } /// Returns true if TODO. #[inline] pub fn plane_reorder_possible(&self) -> bool { self.properties.plane_reorder_possible != 0 } /// Returns true if TODO. #[inline] pub fn persistent_content(&self) -> bool { self.properties.persistent_content != 0 } /// See the docs of display_modes(). pub fn display_modes_raw(&self) -> Result, OomError> { let fns = self.instance.fns(); let num = unsafe { let mut num = 0; check_errors(fns.khr_display.get_display_mode_properties_khr( self.physical_device().internal_object(), self.properties.display, &mut num, ptr::null_mut(), ))?; num }; let modes: Vec = unsafe { let mut modes = Vec::with_capacity(num as usize); let mut num = num; check_errors(fns.khr_display.get_display_mode_properties_khr( self.physical_device().internal_object(), self.properties.display, &mut num, modes.as_mut_ptr(), ))?; modes.set_len(num as usize); modes }; Ok(modes .into_iter() .map(|mode| DisplayMode { display: self.clone(), display_mode: mode.display_mode, parameters: mode.parameters, }) .collect::>() .into_iter()) } /// Returns a list of all modes available on this display. /// /// # Panic /// /// - Panics if the device or host ran out of memory. /// // TODO: move iterator creation here from display_modes_raw? #[inline] pub fn display_modes(&self) -> IntoIter { self.display_modes_raw().unwrap() } } unsafe impl VulkanObject for Display { type Object = ash::vk::DisplayKHR; #[inline] fn internal_object(&self) -> ash::vk::DisplayKHR { self.properties.display } } /// Represents a mode on a specific display. /// /// A display mode describes a supported display resolution and refresh rate. pub struct DisplayMode { display: Display, display_mode: ash::vk::DisplayModeKHR, parameters: ash::vk::DisplayModeParametersKHR, } impl DisplayMode { /*pub fn new(display: &Display) -> Result, OomError> { let fns = instance.fns(); assert!(device.instance().enabled_extensions().khr_display); // TODO: return error instead let parameters = ash::vk::DisplayModeParametersKHR { visibleRegion: ash::vk::Extent2D { width: , height: }, refreshRate: , }; let display_mode = { let infos = ash::vk::DisplayModeCreateInfoKHR { flags: ash::vk::DisplayModeCreateFlags::empty(), parameters: parameters, ..Default::default() }; let mut output = mem::uninitialized(); check_errors(fns.v1_0.CreateDisplayModeKHR(display.device.internal_object(), display.display, &infos, ptr::null(), &mut output))?; output }; Ok(Arc::new(DisplayMode { instance: display.device.instance().clone(), display_mode: display_mode, parameters: , })) }*/ /// Returns the display corresponding to this mode. #[inline] pub fn display(&self) -> &Display { &self.display } /// Returns the dimensions of the region that is visible on the monitor. #[inline] pub fn visible_region(&self) -> [u32; 2] { let ref d = self.parameters.visible_region; [d.width, d.height] } /// Returns the refresh rate of this mode. /// /// The returned value is multiplied by 1000. As such the value is in terms of millihertz (mHz). /// For example, a 60Hz display mode would have a refresh rate of 60,000 mHz. #[inline] pub fn refresh_rate(&self) -> u32 { self.parameters.refresh_rate } } impl fmt::Display for DisplayMode { #[inline] fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 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 Object = ash::vk::DisplayModeKHR; #[inline] fn internal_object(&self) -> ash::vk::DisplayModeKHR { self.display_mode } }