windows_capture/
d3d11.rs

1use windows::Graphics::DirectX::Direct3D11::IDirect3DDevice;
2use windows::Win32::Foundation::HMODULE;
3use windows::Win32::Graphics::Direct3D::{
4    D3D_DRIVER_TYPE_HARDWARE, D3D_FEATURE_LEVEL, D3D_FEATURE_LEVEL_9_1, D3D_FEATURE_LEVEL_9_2,
5    D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0,
6    D3D_FEATURE_LEVEL_11_1,
7};
8use windows::Win32::Graphics::Direct3D11::{
9    D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_SDK_VERSION, D3D11CreateDevice, ID3D11Device,
10    ID3D11DeviceContext,
11};
12use windows::Win32::Graphics::Dxgi::IDXGIDevice;
13use windows::Win32::System::WinRT::Direct3D11::CreateDirect3D11DeviceFromDXGIDevice;
14use windows::core::Interface;
15
16#[derive(thiserror::Error, Eq, PartialEq, Clone, Debug)]
17pub enum Error {
18    #[error("Failed to create DirectX device with the recommended feature levels")]
19    FeatureLevelNotSatisfied,
20    #[error("Windows API Error: {0}")]
21    WindowsError(#[from] windows::core::Error),
22}
23
24/// A wrapper to send a DirectX device across threads.
25pub struct SendDirectX<T>(pub T);
26
27impl<T> SendDirectX<T> {
28    /// Creates a new `SendDirectX` instance.
29    ///
30    /// # Arguments
31    ///
32    /// * `device` - The DirectX device.
33    ///
34    /// # Returns
35    ///
36    /// Returns a new `SendDirectX` instance.
37    #[must_use]
38    #[inline]
39    pub const fn new(device: T) -> Self {
40        Self(device)
41    }
42}
43
44#[allow(clippy::non_send_fields_in_send_ty)]
45unsafe impl<T> Send for SendDirectX<T> {}
46
47/// Creates an `ID3D11Device` and an `ID3D11DeviceContext`.
48#[inline]
49pub fn create_d3d_device() -> Result<(ID3D11Device, ID3D11DeviceContext), Error> {
50    // Array of Direct3D feature levels.
51    // The feature levels are listed in descending order of capability.
52    // The highest feature level supported by the system is at index 0.
53    // The lowest feature level supported by the system is at the last index.
54    let feature_flags = [
55        D3D_FEATURE_LEVEL_11_1,
56        D3D_FEATURE_LEVEL_11_0,
57        D3D_FEATURE_LEVEL_10_1,
58        D3D_FEATURE_LEVEL_10_0,
59        D3D_FEATURE_LEVEL_9_3,
60        D3D_FEATURE_LEVEL_9_2,
61        D3D_FEATURE_LEVEL_9_1,
62    ];
63
64    let mut d3d_device = None;
65    let mut feature_level = D3D_FEATURE_LEVEL::default();
66    let mut d3d_device_context = None;
67    unsafe {
68        D3D11CreateDevice(
69            None,
70            D3D_DRIVER_TYPE_HARDWARE,
71            HMODULE::default(),
72            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
73            Some(&feature_flags),
74            D3D11_SDK_VERSION,
75            Some(&mut d3d_device),
76            Some(&mut feature_level),
77            Some(&mut d3d_device_context),
78        )?;
79    };
80
81    if feature_level.0 < D3D_FEATURE_LEVEL_11_0.0 {
82        return Err(Error::FeatureLevelNotSatisfied);
83    }
84
85    Ok((d3d_device.unwrap(), d3d_device_context.unwrap()))
86}
87
88/// Creates an `IDirect3DDevice` from an `ID3D11Device`.
89#[inline]
90pub fn create_direct3d_device(d3d_device: &ID3D11Device) -> Result<IDirect3DDevice, Error> {
91    let dxgi_device: IDXGIDevice = d3d_device.cast()?;
92    let inspectable = unsafe { CreateDirect3D11DeviceFromDXGIDevice(&dxgi_device)? };
93    let device: IDirect3DDevice = inspectable.cast()?;
94
95    Ok(device)
96}