From ef41b1a2e393920ab10b9d909a2bc5c80bdc196e Mon Sep 17 00:00:00 2001 From: Sludge <96552222+SludgePhD@users.noreply.github.com> Date: Wed, 29 May 2024 13:59:31 +0200 Subject: [PATCH] better libloading error reporting, add theoretical win32 support --- src/display.rs | 19 +++++++------- src/dlopen.rs | 29 +++++++++++++++------- src/error.rs | 67 ++++++++++++++++++++++++++++++++++++++++++-------- src/raw.rs | 3 +-- src/surface.rs | 12 +++++---- 5 files changed, 95 insertions(+), 35 deletions(-) diff --git a/src/display.rs b/src/display.rs index ddaad73..715c849 100644 --- a/src/display.rs +++ b/src/display.rs @@ -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}, @@ -131,6 +131,7 @@ pub enum DisplayApi { Xlib, Wayland, Drm, + Win32, } /// Owns a VADisplay and destroys it on drop. @@ -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: {:?}", @@ -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!( diff --git a/src/dlopen.rs b/src/dlopen.rs index 2672d92..b707881 100644 --- a/src/dlopen.rs +++ b/src/dlopen.rs @@ -13,7 +13,7 @@ use crate::{ buffer::BufferType, config::ConfigAttrib, display::DisplayAttribute, - error::VAStatus, + error::{Error, VAStatus}, image::{ImageFormat, VAImage}, raw::*, subpicture::SubpictureFlags, @@ -44,14 +44,20 @@ macro_rules! dylib { #[allow(unused)] impl $strukt { - fn load() -> Result { + fn load() -> Result { 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))?, )+ }; @@ -62,11 +68,11 @@ macro_rules! dylib { } } - pub fn get() -> Result<&'static Self, &'static libloading::Error> { - static CELL: OnceLock> = OnceLock::new(); + pub fn get() -> Result<&'static Self, Error> { + static CELL: OnceLock> = OnceLock::new(); match CELL.get_or_init(Self::load) { Ok(this) => Ok(this), - Err(e) => Err(e), + Err(e) => Err(Error::statik(e)), } } @@ -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; @@ -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; diff --git a/src/error.rs b/src/error.rs index 07440ce..24d7ccb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -79,7 +79,7 @@ impl PartialEq 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)?) } } @@ -87,11 +87,16 @@ impl VAError { 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 for Repr { @@ -124,12 +129,6 @@ impl From 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, @@ -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), } } } @@ -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), } } } diff --git a/src/raw.rs b/src/raw.rs index 3569d75..49522d5 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -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; @@ -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; diff --git a/src/surface.rs b/src/surface.rs index 8766715..3323997 100644 --- a/src/surface.rs +++ b/src/surface.rs @@ -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, @@ -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()) }