X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihed-cros-libva%2Fsrc%2Fdisplay.rs;h=7cff18fa3ab6ab80fa182e669f04a3f3abc2eb6d;hb=49bf1d79384ecf1b28822101233719fb1c1b29b1;hp=462bc3e8db1dcb154b14bf8026fa06ea579f4842;hpb=683627242f69bed0b818d976d4b03d651e529697;p=nihav-player.git diff --git a/nihed-cros-libva/src/display.rs b/nihed-cros-libva/src/display.rs index 462bc3e..7cff18f 100644 --- a/nihed-cros-libva/src/display.rs +++ b/nihed-cros-libva/src/display.rs @@ -9,16 +9,13 @@ use std::path::Path; use std::path::PathBuf; use std::rc::Rc; -use anyhow::anyhow; -use anyhow::Context as AnyhowContext; -use anyhow::Result; - use crate::bindings; use crate::config::Config; use crate::context::Context; -use crate::status::Status; +use crate::formats::{RTFormat, VAFourcc}; +use crate::status::*; use crate::surface::Surface; -use crate::UsageHint; +use crate::UsageHints; /// Iterates over existing DRM devices. /// @@ -59,6 +56,10 @@ impl Iterator for DrmDeviceIterator { } } +unsafe extern "C" fn null_msg_cb(_ctx: *mut std::ffi::c_void, _message: *const std::ffi::c_char) { +// let msg = CStr::from_ptr(message).to_string_lossy(); +} + /// A VADisplay opened over DRM. /// /// A Display is the starting point to using libva. This struct is essentially a safe wrapper over @@ -80,29 +81,43 @@ impl Display { /// Opens and initializes a specific DRM `Display`. /// /// `path` is the path to a DRM device that supports VAAPI, e.g. `/dev/dri/renderD128`. - pub fn open_drm_display>(path: P) -> Result> { + pub fn open_drm_display>(path: P) -> VAResult> { + Self::open_drm_display_internal(path, false) + } + fn open_drm_display_internal>(path: P, silent: bool) -> VAResult> { let file = std::fs::File::options() .read(true) .write(true) .open(path.as_ref()) - .context(format!("failed to open {}", path.as_ref().display()))?; + .map_err(|_| VAError::InvalidValue)?; // Safe because fd represents a valid file descriptor and the pointer is checked for // NULL afterwards. let display = unsafe { bindings::vaGetDisplayDRM(file.as_raw_fd()) }; if display.is_null() { // The File will close the DRM fd on drop. - return Err(anyhow!( - "failed to obtain VA display from DRM device {}", - path.as_ref().display() - )); + return Err(VAError::InvalidDisplay); + } + + if silent { + // Safe because we ensure that the display is valid (i.e not NULL) before call. + unsafe { + bindings::vaSetInfoCallback(display, Some(null_msg_cb), std::ptr::null_mut()); + } } let mut major = 0i32; let mut minor = 0i32; // Safe because we ensure that the display is valid (i.e not NULL) before calling // vaInitialize. The File will close the DRM fd on drop. - Status(unsafe { bindings::vaInitialize(display, &mut major, &mut minor) }).check()?; + (unsafe { bindings::vaInitialize(display, &mut major, &mut minor) }).check()?; + + if silent { + // Safe because we ensure that the display is valid (i.e not NULL) before call. + unsafe { + bindings::vaSetInfoCallback(display, None, std::ptr::null_mut()); + } + } Ok(Rc::new(Self { handle: display, @@ -127,20 +142,40 @@ impl Display { None } + /// Opens the first device that succeeds and returns its `Display`. + /// + /// The only difference from ordinary `open` is that it does not print debug information + /// about libva version and opened driver. + /// + /// If an error occurs on a given device, it is ignored and the next one is tried until one + /// succeeds or we reach the end of the iterator. + pub fn open_silently() -> Option> { + let devices = DrmDeviceIterator::default(); + + // Try all the DRM devices until one succeeds. + for device in devices { + if let Ok(display) = Self::open_drm_display_internal(device, true) { + return Some(display); + } + } + + None + } + /// Returns the handle of this display. pub(crate) fn handle(&self) -> bindings::VADisplay { self.handle } /// Queries supported profiles by this display. - pub fn query_config_profiles(&self) -> Result> { + pub fn query_config_profiles(&self) -> VAResult> { // Safe because `self` represents a valid VADisplay. let mut max_num_profiles = unsafe { bindings::vaMaxNumProfiles(self.handle) }; let mut profiles = Vec::with_capacity(max_num_profiles as usize); // Safe because `self` represents a valid `VADisplay` and the vector has `max_num_profiles` // as capacity. - Status(unsafe { + (unsafe { bindings::vaQueryConfigProfiles( self.handle, profiles.as_mut_ptr(), @@ -182,14 +217,14 @@ impl Display { pub fn query_config_entrypoints( &self, profile: bindings::VAProfile::Type, - ) -> Result> { + ) -> VAResult> { // Safe because `self` represents a valid VADisplay. let mut max_num_entrypoints = unsafe { bindings::vaMaxNumEntrypoints(self.handle) }; let mut entrypoints = Vec::with_capacity(max_num_entrypoints as usize); // Safe because `self` represents a valid VADisplay and the vector has `max_num_entrypoints` // as capacity. - Status(unsafe { + (unsafe { bindings::vaQueryConfigEntrypoints( self.handle, profile, @@ -218,10 +253,10 @@ impl Display { profile: bindings::VAProfile::Type, entrypoint: bindings::VAEntrypoint::Type, attributes: &mut [bindings::VAConfigAttrib], - ) -> Result<()> { + ) -> VAResult<()> { // Safe because `self` represents a valid VADisplay. The slice length is passed to the C // function, so it is impossible to write past the end of the slice's storage by mistake. - Status(unsafe { + (unsafe { bindings::vaGetConfigAttributes( self.handle, profile, @@ -237,7 +272,7 @@ impl Display { /// /// # Arguments /// - /// * `rt_format` - The desired surface format. See `VA_RT_FORMAT_*` + /// * `rt_format` - The desired surface format. /// * `va_fourcc` - The desired pixel format (optional). See `VA_FOURCC_*` /// * `width` - Width for the create surfaces /// * `height` - Height for the created surfaces @@ -245,20 +280,20 @@ impl Display { /// * `num_surfaces` - Number of surfaces to create pub fn create_surfaces( self: &Rc, - rt_format: u32, - va_fourcc: Option, + rt_format: RTFormat, + va_fourcc: Option, width: u32, height: u32, - usage_hint: Option, + usage_hints: Option, num_surfaces: u32, - ) -> Result> { + ) -> VAResult> { Surface::new( Rc::clone(self), rt_format, va_fourcc, width, height, - usage_hint, + usage_hints, num_surfaces, ) } @@ -279,7 +314,7 @@ impl Display { coded_height: i32, surfaces: Option<&Vec>, progressive: bool, - ) -> Result> { + ) -> VAResult> { Context::new( Rc::clone(self), config, @@ -301,12 +336,12 @@ impl Display { attrs: Vec, profile: bindings::VAProfile::Type, entrypoint: bindings::VAEntrypoint::Type, - ) -> Result { + ) -> VAResult { Config::new(Rc::clone(self), attrs, profile, entrypoint) } /// Returns available image formats for this display by wrapping around `vaQueryImageFormats`. - pub fn query_image_formats(&self) -> Result> { + pub fn query_image_formats(&self) -> VAResult> { // Safe because `self` represents a valid VADisplay. let mut num_image_formats = unsafe { bindings::vaMaxNumImageFormats(self.handle) }; let mut image_formats = Vec::with_capacity(num_image_formats as usize); @@ -314,7 +349,7 @@ impl Display { // Safe because `self` represents a valid VADisplay. The `image_formats` vector is properly // initialized and a valid size is passed to the C function, so it is impossible to write // past the end of their storage by mistake. - Status(unsafe { + (unsafe { bindings::vaQueryImageFormats( self.handle, image_formats.as_mut_ptr(),