• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! Allows you to create surfaces that fill a whole display, outside of the windowing system.
11 //!
12 //! **As far as the author knows, no existing device supports these features. Therefore the code
13 //! here is mostly a draft and needs rework in both the API and the implementation.**
14 //!
15 //! The purpose of the objects in this module is to let you create a `Surface` object that
16 //! represents a location on the screen. This is done in four steps:
17 //!
18 //! - Choose a `Display` where the surface will be located. A `Display` represents a display
19 //!   display, usually a monitor. The available displays can be enumerated with
20 //!   `Display::enumerate`.
21 //! - Choose a `DisplayMode`, which is the combination of a display, a resolution and a refresh
22 //!   rate. You can enumerate the modes available on a display with `Display::display_modes`, or
23 //!   attempt to create your own mode with `TODO`.
24 //! - Choose a `DisplayPlane`. A display can show multiple planes in a stacking fashion.
25 //! - Create a `Surface` object with `Surface::from_display_mode` and pass the chosen `DisplayMode`
26 //!   and `DisplayPlane`.
27 
28 #![allow(dead_code)] // TODO: this module isn't finished
29 #![allow(unused_variables)] // TODO: this module isn't finished
30 
31 use crate::check_errors;
32 use crate::device::physical::PhysicalDevice;
33 use crate::instance::Instance;
34 use crate::swapchain::SupportedSurfaceTransforms;
35 use crate::OomError;
36 use crate::VulkanObject;
37 use std::ffi::CStr;
38 use std::fmt::Formatter;
39 use std::sync::Arc;
40 use std::vec::IntoIter;
41 use std::{fmt, ptr};
42 
43 // TODO: extract this to a `display` module and solve the visibility problems
44 
45 /// ?
46 // TODO: plane capabilities
47 // TODO: store properties in the instance?
48 pub struct DisplayPlane {
49     instance: Arc<Instance>,
50     physical_device: usize,
51     index: u32,
52     properties: ash::vk::DisplayPlanePropertiesKHR,
53     supported_displays: Vec<ash::vk::DisplayKHR>,
54 }
55 
56 impl DisplayPlane {
57     /// See the docs of enumerate().
enumerate_raw(device: PhysicalDevice) -> Result<IntoIter<DisplayPlane>, OomError>58     pub fn enumerate_raw(device: PhysicalDevice) -> Result<IntoIter<DisplayPlane>, OomError> {
59         let fns = device.instance().fns();
60 
61         assert!(device.instance().enabled_extensions().khr_display); // TODO: return error instead
62 
63         let num = unsafe {
64             let mut num: u32 = 0;
65             check_errors(
66                 fns.khr_display
67                     .get_physical_device_display_plane_properties_khr(
68                         device.internal_object(),
69                         &mut num,
70                         ptr::null_mut(),
71                     ),
72             )?;
73             num
74         };
75 
76         let planes: Vec<ash::vk::DisplayPlanePropertiesKHR> = unsafe {
77             let mut planes = Vec::with_capacity(num as usize);
78             let mut num = num;
79             check_errors(
80                 fns.khr_display
81                     .get_physical_device_display_plane_properties_khr(
82                         device.internal_object(),
83                         &mut num,
84                         planes.as_mut_ptr(),
85                     ),
86             )?;
87             planes.set_len(num as usize);
88             planes
89         };
90 
91         Ok(planes
92             .into_iter()
93             .enumerate()
94             .map(|(index, prop)| {
95                 let num = unsafe {
96                     let mut num: u32 = 0;
97                     check_errors(fns.khr_display.get_display_plane_supported_displays_khr(
98                         device.internal_object(),
99                         index as u32,
100                         &mut num,
101                         ptr::null_mut(),
102                     ))
103                     .unwrap(); // TODO: shouldn't unwrap
104                     num
105                 };
106 
107                 let supported_displays: Vec<ash::vk::DisplayKHR> = unsafe {
108                     let mut displays = Vec::with_capacity(num as usize);
109                     let mut num = num;
110                     check_errors(fns.khr_display.get_display_plane_supported_displays_khr(
111                         device.internal_object(),
112                         index as u32,
113                         &mut num,
114                         displays.as_mut_ptr(),
115                     ))
116                     .unwrap(); // TODO: shouldn't unwrap
117                     displays.set_len(num as usize);
118                     displays
119                 };
120 
121                 DisplayPlane {
122                     instance: device.instance().clone(),
123                     physical_device: device.index(),
124                     index: index as u32,
125                     properties: prop,
126                     supported_displays: supported_displays,
127                 }
128             })
129             .collect::<Vec<_>>()
130             .into_iter())
131     }
132 
133     /// Enumerates all the display planes that are available on a given physical device.
134     ///
135     /// # Panic
136     ///
137     /// - Panics if the device or host ran out of memory.
138     ///
139     // TODO: move iterator creation here from raw constructor?
140     #[inline]
enumerate(device: PhysicalDevice) -> IntoIter<DisplayPlane>141     pub fn enumerate(device: PhysicalDevice) -> IntoIter<DisplayPlane> {
142         DisplayPlane::enumerate_raw(device).unwrap()
143     }
144 
145     /// Returns the physical device that was used to create this display.
146     #[inline]
physical_device(&self) -> PhysicalDevice147     pub fn physical_device(&self) -> PhysicalDevice {
148         PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
149     }
150 
151     /// Returns the index of the plane.
152     #[inline]
index(&self) -> u32153     pub fn index(&self) -> u32 {
154         self.index
155     }
156 
157     /// Returns true if this plane supports the given display.
158     #[inline]
supports(&self, display: &Display) -> bool159     pub fn supports(&self, display: &Display) -> bool {
160         // making sure that the physical device is the same
161         if self.physical_device().internal_object() != display.physical_device().internal_object() {
162             return false;
163         }
164 
165         self.supported_displays
166             .iter()
167             .find(|&&d| d == display.internal_object())
168             .is_some()
169     }
170 }
171 
172 /// Represents a monitor connected to a physical device.
173 // TODO: store properties in the instance?
174 #[derive(Clone)]
175 pub struct Display {
176     instance: Arc<Instance>,
177     physical_device: usize,
178     properties: Arc<ash::vk::DisplayPropertiesKHR>, // TODO: Arc because struct isn't clone
179 }
180 
181 impl Display {
182     /// See the docs of enumerate().
enumerate_raw(device: PhysicalDevice) -> Result<IntoIter<Display>, OomError>183     pub fn enumerate_raw(device: PhysicalDevice) -> Result<IntoIter<Display>, OomError> {
184         let fns = device.instance().fns();
185         assert!(device.instance().enabled_extensions().khr_display); // TODO: return error instead
186 
187         let num = unsafe {
188             let mut num = 0;
189             check_errors(fns.khr_display.get_physical_device_display_properties_khr(
190                 device.internal_object(),
191                 &mut num,
192                 ptr::null_mut(),
193             ))?;
194             num
195         };
196 
197         let displays: Vec<ash::vk::DisplayPropertiesKHR> = unsafe {
198             let mut displays = Vec::with_capacity(num as usize);
199             let mut num = num;
200             check_errors(fns.khr_display.get_physical_device_display_properties_khr(
201                 device.internal_object(),
202                 &mut num,
203                 displays.as_mut_ptr(),
204             ))?;
205             displays.set_len(num as usize);
206             displays
207         };
208 
209         Ok(displays
210             .into_iter()
211             .map(|prop| Display {
212                 instance: device.instance().clone(),
213                 physical_device: device.index(),
214                 properties: Arc::new(prop),
215             })
216             .collect::<Vec<_>>()
217             .into_iter())
218     }
219 
220     /// Enumerates all the displays that are available on a given physical device.
221     ///
222     /// # Panic
223     ///
224     /// - Panics if the device or host ran out of memory.
225     ///
226     // TODO: move iterator creation here from raw constructor?
227     #[inline]
enumerate(device: PhysicalDevice) -> IntoIter<Display>228     pub fn enumerate(device: PhysicalDevice) -> IntoIter<Display> {
229         Display::enumerate_raw(device).unwrap()
230     }
231 
232     /// Returns the name of the display.
233     #[inline]
name(&self) -> &str234     pub fn name(&self) -> &str {
235         unsafe {
236             CStr::from_ptr(self.properties.display_name)
237                 .to_str()
238                 .expect("non UTF-8 characters in display name")
239         }
240     }
241 
242     /// Returns the physical device that was used to create this display.
243     #[inline]
physical_device(&self) -> PhysicalDevice244     pub fn physical_device(&self) -> PhysicalDevice {
245         PhysicalDevice::from_index(&self.instance, self.physical_device).unwrap()
246     }
247 
248     /// Returns the physical dimensions of the display in millimeters.
249     #[inline]
physical_dimensions(&self) -> [u32; 2]250     pub fn physical_dimensions(&self) -> [u32; 2] {
251         let ref r = self.properties.physical_dimensions;
252         [r.width, r.height]
253     }
254 
255     /// Returns the physical, native, or preferred resolution of the display.
256     ///
257     /// > **Note**: The display is usually still capable of displaying other resolutions. This is
258     /// > only the "best" resolution.
259     #[inline]
physical_resolution(&self) -> [u32; 2]260     pub fn physical_resolution(&self) -> [u32; 2] {
261         let ref r = self.properties.physical_resolution;
262         [r.width, r.height]
263     }
264 
265     /// Returns the transforms supported by this display.
266     #[inline]
supported_transforms(&self) -> SupportedSurfaceTransforms267     pub fn supported_transforms(&self) -> SupportedSurfaceTransforms {
268         self.properties.supported_transforms.into()
269     }
270 
271     /// Returns true if TODO.
272     #[inline]
plane_reorder_possible(&self) -> bool273     pub fn plane_reorder_possible(&self) -> bool {
274         self.properties.plane_reorder_possible != 0
275     }
276 
277     /// Returns true if TODO.
278     #[inline]
persistent_content(&self) -> bool279     pub fn persistent_content(&self) -> bool {
280         self.properties.persistent_content != 0
281     }
282 
283     /// See the docs of display_modes().
display_modes_raw(&self) -> Result<IntoIter<DisplayMode>, OomError>284     pub fn display_modes_raw(&self) -> Result<IntoIter<DisplayMode>, OomError> {
285         let fns = self.instance.fns();
286 
287         let num = unsafe {
288             let mut num = 0;
289             check_errors(fns.khr_display.get_display_mode_properties_khr(
290                 self.physical_device().internal_object(),
291                 self.properties.display,
292                 &mut num,
293                 ptr::null_mut(),
294             ))?;
295             num
296         };
297 
298         let modes: Vec<ash::vk::DisplayModePropertiesKHR> = unsafe {
299             let mut modes = Vec::with_capacity(num as usize);
300             let mut num = num;
301             check_errors(fns.khr_display.get_display_mode_properties_khr(
302                 self.physical_device().internal_object(),
303                 self.properties.display,
304                 &mut num,
305                 modes.as_mut_ptr(),
306             ))?;
307             modes.set_len(num as usize);
308             modes
309         };
310 
311         Ok(modes
312             .into_iter()
313             .map(|mode| DisplayMode {
314                 display: self.clone(),
315                 display_mode: mode.display_mode,
316                 parameters: mode.parameters,
317             })
318             .collect::<Vec<_>>()
319             .into_iter())
320     }
321 
322     /// Returns a list of all modes available on this display.
323     ///
324     /// # Panic
325     ///
326     /// - Panics if the device or host ran out of memory.
327     ///
328     // TODO: move iterator creation here from display_modes_raw?
329     #[inline]
display_modes(&self) -> IntoIter<DisplayMode>330     pub fn display_modes(&self) -> IntoIter<DisplayMode> {
331         self.display_modes_raw().unwrap()
332     }
333 }
334 
335 unsafe impl VulkanObject for Display {
336     type Object = ash::vk::DisplayKHR;
337 
338     #[inline]
internal_object(&self) -> ash::vk::DisplayKHR339     fn internal_object(&self) -> ash::vk::DisplayKHR {
340         self.properties.display
341     }
342 }
343 
344 /// Represents a mode on a specific display.
345 ///
346 /// A display mode describes a supported display resolution and refresh rate.
347 pub struct DisplayMode {
348     display: Display,
349     display_mode: ash::vk::DisplayModeKHR,
350     parameters: ash::vk::DisplayModeParametersKHR,
351 }
352 
353 impl DisplayMode {
354     /*pub fn new(display: &Display) -> Result<Arc<DisplayMode>, OomError> {
355         let fns = instance.fns();
356         assert!(device.instance().enabled_extensions().khr_display);     // TODO: return error instead
357 
358         let parameters = ash::vk::DisplayModeParametersKHR {
359             visibleRegion: ash::vk::Extent2D { width: , height:  },
360             refreshRate: ,
361         };
362 
363         let display_mode = {
364             let infos = ash::vk::DisplayModeCreateInfoKHR {
365                 flags: ash::vk::DisplayModeCreateFlags::empty(),
366                 parameters: parameters,
367                 ..Default::default()
368             };
369 
370             let mut output = mem::uninitialized();
371             check_errors(fns.v1_0.CreateDisplayModeKHR(display.device.internal_object(),
372                                                       display.display, &infos, ptr::null(),
373                                                       &mut output))?;
374             output
375         };
376 
377         Ok(Arc::new(DisplayMode {
378             instance: display.device.instance().clone(),
379             display_mode: display_mode,
380             parameters: ,
381         }))
382     }*/
383 
384     /// Returns the display corresponding to this mode.
385     #[inline]
display(&self) -> &Display386     pub fn display(&self) -> &Display {
387         &self.display
388     }
389 
390     /// Returns the dimensions of the region that is visible on the monitor.
391     #[inline]
visible_region(&self) -> [u32; 2]392     pub fn visible_region(&self) -> [u32; 2] {
393         let ref d = self.parameters.visible_region;
394         [d.width, d.height]
395     }
396 
397     /// Returns the refresh rate of this mode.
398     ///
399     /// The returned value is multiplied by 1000. As such the value is in terms of millihertz (mHz).
400     /// For example, a 60Hz display mode would have a refresh rate of 60,000 mHz.
401     #[inline]
refresh_rate(&self) -> u32402     pub fn refresh_rate(&self) -> u32 {
403         self.parameters.refresh_rate
404     }
405 }
406 
407 impl fmt::Display for DisplayMode {
408     #[inline]
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result409     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
410         let visible_region = self.visible_region();
411 
412         write!(
413             f,
414             "{}×{}px @ {}.{:03} Hz",
415             visible_region[0],
416             visible_region[1],
417             self.refresh_rate() / 1000,
418             self.refresh_rate() % 1000
419         )
420     }
421 }
422 
423 unsafe impl VulkanObject for DisplayMode {
424     type Object = ash::vk::DisplayModeKHR;
425 
426     #[inline]
internal_object(&self) -> ash::vk::DisplayModeKHR427     fn internal_object(&self) -> ash::vk::DisplayModeKHR {
428         self.display_mode
429     }
430 }
431