Skip to content

Commit

Permalink
better libloading error reporting, add theoretical win32 support
Browse files Browse the repository at this point in the history
  • Loading branch information
SludgePhD committed May 29, 2024
1 parent dd16b90 commit ef41b1a
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 35 deletions.
19 changes: 10 additions & 9 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use raw_window_handle::{HasDisplayHandle, RawDisplayHandle};

use crate::{
check, check_log,
dlopen::{libva, libva_drm, libva_wayland, libva_x11},
dlopen::{libva, libva_drm, libva_wayland, libva_win32, libva_x11},
image::{ImageFormat, ImageFormats},
raw::{VADisplay, VA_PADDING_LOW},
subpicture::{SubpictureFlags, SubpictureFormats},
Expand Down Expand Up @@ -131,6 +131,7 @@ pub enum DisplayApi {
Xlib,
Wayland,
Drm,
Win32,
}

/// Owns a VADisplay and destroys it on drop.
Expand Down Expand Up @@ -209,21 +210,21 @@ impl Display {
let api = match handle {
RawDisplayHandle::Xlib(d) => {
let display = d.display.map_or(ptr::null_mut(), NonNull::as_ptr);
raw = libva_x11::get()
.map_err(Error::from)?
.vaGetDisplay(display.cast());
raw = libva_x11::get()?.vaGetDisplay(display.cast());
DisplayApi::Xlib
}
RawDisplayHandle::Wayland(d) => {
raw = libva_wayland::get()
.map_err(Error::from)?
.vaGetDisplayWl(d.display.as_ptr().cast());
raw = libva_wayland::get()?.vaGetDisplayWl(d.display.as_ptr().cast());
DisplayApi::Wayland
}
RawDisplayHandle::Drm(d) => {
raw = libva_drm::get().map_err(Error::from)?.vaGetDisplayDRM(d.fd);
raw = libva_drm::get()?.vaGetDisplayDRM(d.fd);
DisplayApi::Drm
}
RawDisplayHandle::Windows(_) => {
raw = libva_win32::get()?.vaGetDisplayWin32(ptr::null());
DisplayApi::Win32
}
_ => {
return Err(Error::from(format!(
"unsupported display handle type: {:?}",
Expand All @@ -232,7 +233,7 @@ impl Display {
}
};

let libva = libva::get().map_err(Error::from)?;
let libva = libva::get()?;
let valid = libva.vaDisplayIsValid(raw);
if valid == 0 {
return Err(Error::from(format!(
Expand Down
29 changes: 20 additions & 9 deletions src/dlopen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
buffer::BufferType,
config::ConfigAttrib,
display::DisplayAttribute,
error::VAStatus,
error::{Error, VAStatus},
image::{ImageFormat, VAImage},
raw::*,
subpicture::SubpictureFlags,
Expand Down Expand Up @@ -44,14 +44,20 @@ macro_rules! dylib {

#[allow(unused)]
impl $strukt {
fn load() -> Result<Self, libloading::Error> {
fn load() -> Result<Self, Error> {
unsafe {
let libname = concat!(stringify!($strukt), ".so").replace('_', "-");
let lib = libloading::Library::new(&libname)?;
let libname = if cfg!(target_os = "windows") {
concat!(stringify!($strukt), ".dll").replace("lib", "")
} else {
concat!(stringify!($strukt), ".so").replace('_', "-")
};

let lib = libloading::Library::new(&libname).map_err(|e| Error::dlopen(&libname, e))?;

let this = Self {
$(
$func: *lib.get(concat!(stringify!($func), "\0").as_bytes())?,
$func: *lib.get(concat!(stringify!($func), "\0").as_bytes())
.map_err(|e| Error::dlsym(&libname, stringify!($func), e))?,
)+
};

Expand All @@ -62,11 +68,11 @@ macro_rules! dylib {
}
}

pub fn get() -> Result<&'static Self, &'static libloading::Error> {
static CELL: OnceLock<Result<$strukt, libloading::Error>> = OnceLock::new();
pub fn get() -> Result<&'static Self, Error> {
static CELL: OnceLock<Result<$strukt, Error>> = OnceLock::new();
match CELL.get_or_init(Self::load) {
Ok(this) => Ok(this),
Err(e) => Err(e),
Err(e) => Err(Error::statik(e)),
}
}

Expand All @@ -90,7 +96,6 @@ dylib! {
fn vaInitialize(dpy: VADisplay, major_version: *mut c_int, minor_version: *mut c_int) -> VAStatus;
fn vaTerminate(dpy: VADisplay) -> VAStatus;
fn vaQueryVendorString(dpy: VADisplay) -> *const c_char;
fn vaGetLibFunc(dpy: VADisplay, func: *const c_char) -> VAPrivFunc;
fn vaMaxNumProfiles(dpy: VADisplay) -> c_int;
fn vaMaxNumEntrypoints(dpy: VADisplay) -> c_int;
fn vaMaxNumConfigAttributes(dpy: VADisplay) -> c_int;
Expand Down Expand Up @@ -215,6 +220,12 @@ dylib! {
fn vaGetDisplayDRM(fd: c_int) -> VADisplay;
}

dylib! {
pub struct libva_win32;

fn vaGetDisplayWin32(adapter_luid: *const c_void) -> VADisplay;
}

pub struct wl_display;
pub struct wl_buffer;

Expand Down
67 changes: 57 additions & 10 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,24 @@ impl PartialEq<VAStatus> for VAError {
impl VAError {
pub fn to_str(self) -> Result<&'static str, Error> {
unsafe {
let cstr = &CStr::from_ptr(libva::get().map_err(Error::from)?.vaErrorStr(self.into()));
let cstr = &CStr::from_ptr(libva::get()?.vaErrorStr(self.into()));
Ok(cstr.to_str().map_err(Error::from)?)
}
}
}

pub(crate) enum Repr {
Libva(&'static str, VAError),
Libloading(&'static libloading::Error),
Libloading {
inner: libloading::Error,
libname: String,
funcname: Option<&'static str>,
},
Utf8Error(Utf8Error),
TryFromIntError(TryFromIntError),
HandleError(raw_window_handle::HandleError),
Other(String),
Static(&'static Error),
}

impl From<raw_window_handle::HandleError> for Repr {
Expand Down Expand Up @@ -124,12 +129,6 @@ impl From<Utf8Error> for Repr {
}
}

impl From<&'static libloading::Error> for Repr {
fn from(v: &'static libloading::Error) -> Self {
Self::Libloading(v)
}
}

/// The main error type used by this library.
pub struct Error {
repr: Repr,
Expand All @@ -154,17 +153,54 @@ impl Error {
repr: Repr::Libva(location, error),
}
}

pub(crate) fn dlopen(libname: &str, error: libloading::Error) -> Self {
Self {
repr: Repr::Libloading {
inner: error,
libname: libname.to_string(),
funcname: None,
},
}
}

pub(crate) fn dlsym(libname: &str, funcname: &'static str, error: libloading::Error) -> Self {
Self {
repr: Repr::Libloading {
inner: error,
libname: libname.to_string(),
funcname: Some(funcname),
},
}
}

pub(crate) fn statik(error: &'static Self) -> Self {
Self {
repr: Repr::Static(error),
}
}
}

impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.repr {
Repr::Libva(loc, e) => write!(f, "{loc}: {e:?}"),
Repr::Libloading(e) => e.fmt(f),
Repr::Libloading {
inner,
libname,
funcname,
} => {
write!(f, "{libname}")?;
if let Some(name) = funcname {
write!(f, "/{name}")?;
}
write!(f, ": {inner:?}")
}
Repr::Utf8Error(e) => e.fmt(f),
Repr::TryFromIntError(e) => e.fmt(f),
Repr::HandleError(e) => e.fmt(f),
Repr::Other(s) => s.fmt(f),
Repr::Static(e) => e.fmt(f),
}
}
}
Expand All @@ -176,11 +212,22 @@ impl fmt::Display for Error {
Ok(s) => write!(f, "{loc}: {s} ({e:?})"),
Err(_) => fmt::Debug::fmt(e, f),
},
Repr::Libloading(e) => e.fmt(f),
Repr::Libloading {
inner,
libname,
funcname,
} => {
write!(f, "{libname}")?;
if let Some(name) = funcname {
write!(f, "/{name}")?;
}
write!(f, ": {inner}")
}
Repr::Utf8Error(e) => e.fmt(f),
Repr::TryFromIntError(e) => e.fmt(f),
Repr::HandleError(e) => e.fmt(f),
Repr::Other(e) => e.fmt(f),
Repr::Static(e) => e.fmt(f),
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/raw.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
ffi::c_void,
os::raw::{c_char, c_int, c_uint},
os::raw::{c_char, c_uint},
};

use crate::buffer::BufferType;
Expand Down Expand Up @@ -58,7 +58,6 @@ pub type VADisplay = *mut c_void;

pub type VAMessageCallback =
unsafe extern "C" fn(user_context: *mut c_void, message: *const c_char);
pub type VAPrivFunc = unsafe extern "C" fn() -> c_int;
pub type VAGenericFunc = unsafe extern "C" fn();

pub type VAGenericID = c_uint;
Expand Down
12 changes: 7 additions & 5 deletions src/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use crate::{
buffer::Mapping,
check, check_log,
display::{Display, DisplayOwner},
dlopen::{libva_wayland, wl_buffer},
error::VAError,
image::{Image, ImageFormat},
pixelformat::PixelFormat,
Expand Down Expand Up @@ -547,14 +546,17 @@ impl Surface {
/// to the desired type to use it)
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub fn wayland_buffer(&self) -> Result<*mut wl_buffer> {
pub fn wayland_buffer(&self) -> Result<*mut crate::dlopen::wl_buffer> {
unsafe {
let mut wlbufferptr = MaybeUninit::uninit();
check(
"vaGetSurfaceBufferWl",
libva_wayland::get()
.map_err(Error::from)?
.vaGetSurfaceBufferWl(self.d.raw, self.id, 0, wlbufferptr.as_mut_ptr()),
crate::dlopen::libva_wayland::get()?.vaGetSurfaceBufferWl(
self.d.raw,
self.id,
0,
wlbufferptr.as_mut_ptr(),
),
)?;
Ok(wlbufferptr.assume_init())
}
Expand Down

0 comments on commit ef41b1a

Please sign in to comment.