1use std::sync::atomic::{AtomicUsize, Ordering};
2use std::os::raw::c_void;
3use status::{Status, NvAPI_Status};
4use types;
5
6pub type QueryInterfaceFn = extern "C" fn(id: u32) -> *const c_void;
7
8#[cfg(all(windows, target_pointer_width = "32"))]
9pub const LIBRARY_NAME: &'static [u8; 10] = b"nvapi.dll\0";
10#[cfg(all(windows, target_pointer_width = "64"))]
11pub const LIBRARY_NAME: &'static [u8; 12] = b"nvapi64.dll\0";
12
13pub const FN_NAME: &'static [u8; 21] = b"nvapi_QueryInterface\0";
14
15static QUERY_INTERFACE_CACHE: AtomicUsize = AtomicUsize::new(0);
16
17pub unsafe fn set_query_interface(ptr: QueryInterfaceFn) {
18 QUERY_INTERFACE_CACHE.store(ptr as usize, Ordering::Relaxed);
19}
20
21#[cfg(not(windows))]
22pub fn nvapi_QueryInterface(id: u32) -> ::Result<usize> {
23 Err(Status::LibraryNotFound)
25}
26
27#[cfg(windows)]
28pub fn nvapi_QueryInterface(id: u32) -> ::Result<usize> {
29 use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryA};
30 use std::mem;
31 use std::os::raw::c_char;
32
33 unsafe {
34 let ptr = match QUERY_INTERFACE_CACHE.load(Ordering::Relaxed) {
35 0 => {
36 let lib = LoadLibraryA(LIBRARY_NAME.as_ptr() as *const c_char);
37 if lib.is_null() {
38 Err(Status::LibraryNotFound)
39 } else {
40 let ptr = GetProcAddress(lib, FN_NAME.as_ptr() as *const c_char);
41 if ptr.is_null() {
42 Err(Status::LibraryNotFound)
43 } else {
44 QUERY_INTERFACE_CACHE.store(ptr as usize, Ordering::Relaxed);
45 Ok(ptr as usize)
46 }
47 }
48 },
49 ptr => Ok(ptr),
50 }?;
51
52 match mem::transmute::<_, QueryInterfaceFn>(ptr)(id) as usize {
53 0 => Err(Status::NoImplementation),
54 ptr => Ok(ptr),
55 }
56 }
57}
58
59pub(crate) fn query_interface(id: u32, cache: &AtomicUsize) -> ::Result<usize> {
60 match cache.load(Ordering::Relaxed) {
61 0 => {
62 let value = nvapi_QueryInterface(id)?;
63 cache.store(value, Ordering::Relaxed);
64 Ok(value)
65 },
66 value => Ok(value),
67 }
68}
69
70nvapi! {
71 pub type InitializeFn = extern "C" fn() -> NvAPI_Status;
72
73 pub unsafe fn NvAPI_Initialize;
76}
77
78nvapi! {
79 pub type UnloadFn = extern "C" fn() -> NvAPI_Status;
80
81 pub unsafe fn NvAPI_Unload;
100}
101
102nvapi! {
103 pub type GetErrorMessageFn = extern "C" fn(nr: NvAPI_Status, szDesc: *mut types::NvAPI_ShortString) -> NvAPI_Status;
104
105 pub unsafe fn NvAPI_GetErrorMessage;
107}
108
109nvapi! {
110 pub type GetInterfaceVersionStringFn = extern "C" fn(szDesc: *mut types::NvAPI_ShortString) -> NvAPI_Status;
111
112 pub unsafe fn NvAPI_GetInterfaceVersionString;
115}
116