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.
///
}
}
+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
/// 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<P: AsRef<Path>>(path: P) -> Result<Rc<Self>> {
+ pub fn open_drm_display<P: AsRef<Path>>(path: P) -> VAResult<Rc<Self>> {
+ Self::open_drm_display_internal(path, false)
+ }
+ fn open_drm_display_internal<P: AsRef<Path>>(path: P, silent: bool) -> VAResult<Rc<Self>> {
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,
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<Rc<Self>> {
+ 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<Vec<bindings::VAProfile::Type>> {
+ pub fn query_config_profiles(&self) -> VAResult<Vec<bindings::VAProfile::Type>> {
// 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(),
pub fn query_config_entrypoints(
&self,
profile: bindings::VAProfile::Type,
- ) -> Result<Vec<bindings::VAEntrypoint::Type>> {
+ ) -> VAResult<Vec<bindings::VAEntrypoint::Type>> {
// 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,
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,
///
/// # 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
/// * `num_surfaces` - Number of surfaces to create
pub fn create_surfaces(
self: &Rc<Self>,
- rt_format: u32,
- va_fourcc: Option<u32>,
+ rt_format: RTFormat,
+ va_fourcc: Option<VAFourcc>,
width: u32,
height: u32,
- usage_hint: Option<UsageHint>,
+ usage_hints: Option<UsageHints>,
num_surfaces: u32,
- ) -> Result<Vec<Surface>> {
+ ) -> VAResult<Vec<Surface>> {
Surface::new(
Rc::clone(self),
rt_format,
va_fourcc,
width,
height,
- usage_hint,
+ usage_hints,
num_surfaces,
)
}
coded_height: i32,
surfaces: Option<&Vec<Surface>>,
progressive: bool,
- ) -> Result<Rc<Context>> {
+ ) -> VAResult<Rc<Context>> {
Context::new(
Rc::clone(self),
config,
attrs: Vec<bindings::VAConfigAttrib>,
profile: bindings::VAProfile::Type,
entrypoint: bindings::VAEntrypoint::Type,
- ) -> Result<Config> {
+ ) -> VAResult<Config> {
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<Vec<bindings::VAImageFormat>> {
+ pub fn query_image_formats(&self) -> VAResult<Vec<bindings::VAImageFormat>> {
// 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);
// 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(),