use std::ffi::c_void;
use std::ptr;
use libloading::{Library, Symbol};
use once_cell::sync::OnceCell;
use renderdoc_sys::RENDERDOC_API_1_4_1;
use crate::error::Error;
pub type Entry = RENDERDOC_API_1_4_1;
#[repr(u32)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum VersionCode {
V100 = 10000,
V101 = 10001,
V102 = 10002,
V110 = 10100,
V111 = 10101,
V112 = 10102,
V120 = 10200,
V130 = 10300,
V140 = 10400,
V141 = 10401,
}
pub trait Version {
const VERSION: VersionCode;
fn load() -> Result<*mut Entry, Error> {
static LIBRARY: OnceCell<Library> = OnceCell::new();
type GetApiFn = unsafe extern "C" fn(ver: u32, out: *mut *mut c_void) -> i32;
#[cfg(windows)]
let lib_path = "renderdoc.dll";
#[cfg(all(unix, not(target_os = "android")))]
let lib_path = "librenderdoc.so";
#[cfg(target_os = "android")]
let lib_path = "libVkLayer_GLES_RenderDoc.so";
unsafe {
#[cfg(not(feature = "ci"))]
#[cfg(unix)]
let lib = LIBRARY
.get_or_try_init(|| {
const RTLD_NOLOAD: i32 = 0x4;
let flags = libloading::os::unix::RTLD_NOW | RTLD_NOLOAD;
libloading::os::unix::Library::open(Some(lib_path), flags).map(Into::into)
})
.map_err(Error::library)?;
#[cfg(not(feature = "ci"))]
#[cfg(windows)]
let lib = LIBRARY
.get_or_try_init(|| {
libloading::os::windows::Library::open_already_loaded(lib_path).map(Into::into)
})
.map_err(Error::library)?;
#[cfg(feature = "ci")]
let lib = LIBRARY
.get_or_try_init(|| Library::new(lib_path))
.map_err(Error::library)?;
let get_api: Symbol<GetApiFn> =
lib.get(b"RENDERDOC_GetAPI\0").map_err(Error::symbol)?;
let mut obj = ptr::null_mut();
match get_api(Self::VERSION as u32, &mut obj) {
1 => Ok(obj as *mut Entry),
_ => Err(Error::no_compatible_api()),
}
}
}
}
pub trait HasPrevious: Version {
type Previous: Version;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V100 {}
impl Version for V100 {
const VERSION: VersionCode = VersionCode::V100;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V110 {}
impl Version for V110 {
const VERSION: VersionCode = VersionCode::V110;
}
impl HasPrevious for V110 {
type Previous = V100;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V111 {}
impl Version for V111 {
const VERSION: VersionCode = VersionCode::V111;
}
impl HasPrevious for V111 {
type Previous = V110;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V112 {}
impl Version for V112 {
const VERSION: VersionCode = VersionCode::V112;
}
impl HasPrevious for V112 {
type Previous = V111;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V120 {}
impl Version for V120 {
const VERSION: VersionCode = VersionCode::V120;
}
impl HasPrevious for V120 {
type Previous = V112;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V130 {}
impl Version for V130 {
const VERSION: VersionCode = VersionCode::V130;
}
impl HasPrevious for V130 {
type Previous = V120;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V140 {}
impl Version for V140 {
const VERSION: VersionCode = VersionCode::V140;
}
impl HasPrevious for V140 {
type Previous = V130;
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum V141 {}
impl Version for V141 {
const VERSION: VersionCode = VersionCode::V141;
}
impl HasPrevious for V141 {
type Previous = V140;
}