arcdps\globals/
dxgi.rs

1use crate::util::Share;
2use std::{
3    ffi::c_void,
4    sync::{
5        atomic::{AtomicU32, Ordering},
6        OnceLock,
7    },
8};
9use windows::{
10    core::{Interface, InterfaceRef},
11    Win32::Graphics::{Direct3D11::ID3D11Device, Dxgi::IDXGISwapChain},
12};
13
14/// Current DirectX version.
15static D3D_VERSION: AtomicU32 = AtomicU32::new(0);
16
17/// Returns the current DirectX version.
18///
19/// `11` for DirectX 11 and `9` for legacy DirectX 9 mode.
20#[inline]
21pub fn d3d_version() -> u32 {
22    D3D_VERSION.load(Ordering::Relaxed)
23}
24
25/// DirectX 11 swap chain.
26static DXGI_SWAP_CHAIN: OnceLock<Share<InterfaceRef<'static, IDXGISwapChain>>> = OnceLock::new();
27
28/// Returns the DirectX swap chain, if available.
29#[inline]
30pub fn dxgi_swap_chain() -> Option<IDXGISwapChain> {
31    DXGI_SWAP_CHAIN
32        .get()
33        .map(|swap_chain| (*unsafe { swap_chain.get() }).to_owned())
34}
35
36/// Returns the DirectX 11 device, if available.
37#[inline]
38pub fn d3d11_device() -> Option<ID3D11Device> {
39    let swap_chain = dxgi_swap_chain()?;
40    unsafe { swap_chain.GetDevice() }.ok()
41}
42
43/// Initializes DirectX information.
44pub unsafe fn init_dxgi(id3d: *mut c_void, d3d_version: u32) {
45    D3D_VERSION.store(d3d_version, Ordering::Relaxed);
46    if d3d_version == 11 && !id3d.is_null() {
47        let swap_chain =
48            unsafe { IDXGISwapChain::from_raw_borrowed(&id3d) }.expect("invalid swap chain");
49        DXGI_SWAP_CHAIN.get_or_init(|| Share::new(InterfaceRef::from_interface(swap_chain)));
50    }
51}