summaryrefslogtreecommitdiffstats
path: root/third_party/rust/gfx-backend-dx11/src/dxgi.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/gfx-backend-dx11/src/dxgi.rs
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/gfx-backend-dx11/src/dxgi.rs')
-rw-r--r--third_party/rust/gfx-backend-dx11/src/dxgi.rs213
1 files changed, 213 insertions, 0 deletions
diff --git a/third_party/rust/gfx-backend-dx11/src/dxgi.rs b/third_party/rust/gfx-backend-dx11/src/dxgi.rs
new file mode 100644
index 0000000000..bd722d7554
--- /dev/null
+++ b/third_party/rust/gfx-backend-dx11/src/dxgi.rs
@@ -0,0 +1,213 @@
+use hal::adapter::{AdapterInfo, DeviceType};
+
+use winapi::{
+ shared::{
+ dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgi1_5,
+ guiddef::{GUID, REFIID},
+ winerror,
+ },
+ um::unknwnbase::IUnknown,
+ Interface,
+};
+
+use wio::com::ComPtr;
+
+use std::{ffi::OsString, mem, os::windows::ffi::OsStringExt, ptr};
+
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum DxgiVersion {
+ /// Capable of the following interfaces:
+ /// * IDXGIObject
+ /// * IDXGIDeviceSubObject
+ /// * IDXGIResource
+ /// * IDXGIKeyedMutex
+ /// * IDXGISurface
+ /// * IDXGISurface1
+ /// * IDXGIOutput
+ /// * IDXGISwapChain
+ /// * IDXGIFactory
+ /// * IDXGIDevice
+ /// * IDXGIFactory1
+ /// * IDXGIAdapter1
+ /// * IDXGIDevice1
+ Dxgi1_0,
+
+ /// Capable of the following interfaces:
+ /// * IDXGIDisplayControl
+ /// * IDXGIOutputDuplication
+ /// * IDXGISurface2
+ /// * IDXGIResource1
+ /// * IDXGIDevice2
+ /// * IDXGISwapChain1
+ /// * IDXGIFactory2
+ /// * IDXGIAdapter2
+ /// * IDXGIOutput1
+ Dxgi1_2,
+
+ /// Capable of the following interfaces:
+ /// * IDXGIDevice3
+ /// * IDXGISwapChain2
+ /// * IDXGIOutput2
+ /// * IDXGIDecodeSwapChain
+ /// * IDXGIFactoryMedia
+ /// * IDXGISwapChainMedia
+ /// * IDXGIOutput3
+ Dxgi1_3,
+
+ /// Capable of the following interfaces:
+ /// * IDXGISwapChain3
+ /// * IDXGIOutput4
+ /// * IDXGIFactory4
+ /// * IDXGIAdapter3
+ Dxgi1_4,
+
+ /// Capable of the following interfaces:
+ /// * IDXGIOutput5
+ /// * IDXGISwapChain4
+ /// * IDXGIDevice4
+ /// * IDXGIFactory5
+ Dxgi1_5,
+}
+
+type DxgiFun =
+ unsafe extern "system" fn(REFIID, *mut *mut winapi::ctypes::c_void) -> winerror::HRESULT;
+
+fn create_dxgi_factory1(
+ func: &DxgiFun,
+ guid: &GUID,
+) -> Result<ComPtr<dxgi::IDXGIFactory>, winerror::HRESULT> {
+ let mut factory: *mut IUnknown = ptr::null_mut();
+
+ let hr = unsafe { func(guid, &mut factory as *mut *mut _ as *mut *mut _) };
+
+ if winerror::SUCCEEDED(hr) {
+ Ok(unsafe { ComPtr::from_raw(factory as *mut _) })
+ } else {
+ Err(hr)
+ }
+}
+
+pub(crate) fn get_dxgi_factory(
+) -> Result<(libloading::Library, ComPtr<dxgi::IDXGIFactory>, DxgiVersion), winerror::HRESULT> {
+ // The returned Com-pointer is only safe to use for the lifetime of the Library.
+ let library = libloading::Library::new("dxgi.dll").map_err(|_| -1)?;
+ let func: libloading::Symbol<DxgiFun> =
+ unsafe { library.get(b"CreateDXGIFactory1") }.map_err(|_| -1)?;
+
+ // TODO: do we even need `create_dxgi_factory2`?
+ if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_5::IDXGIFactory5::uuidof()) {
+ return Ok((library, factory, DxgiVersion::Dxgi1_5));
+ }
+
+ if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_4::IDXGIFactory4::uuidof()) {
+ return Ok((library, factory, DxgiVersion::Dxgi1_4));
+ }
+
+ if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_3::IDXGIFactory3::uuidof()) {
+ return Ok((library, factory, DxgiVersion::Dxgi1_3));
+ }
+
+ if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_2::IDXGIFactory2::uuidof()) {
+ return Ok((library, factory, DxgiVersion::Dxgi1_2));
+ }
+
+ if let Ok(factory) = create_dxgi_factory1(&func, &dxgi::IDXGIFactory1::uuidof()) {
+ return Ok((library, factory, DxgiVersion::Dxgi1_0));
+ }
+
+ // TODO: any reason why above would fail and this wouldnt?
+ match create_dxgi_factory1(&func, &dxgi::IDXGIFactory::uuidof()) {
+ Ok(factory) => Ok((library, factory, DxgiVersion::Dxgi1_0)),
+ Err(hr) => Err(hr),
+ }
+}
+
+fn enum_adapters1(
+ idx: u32,
+ factory: *mut dxgi::IDXGIFactory,
+) -> Result<ComPtr<dxgi::IDXGIAdapter>, winerror::HRESULT> {
+ let mut adapter: *mut dxgi::IDXGIAdapter = ptr::null_mut();
+
+ let hr = unsafe {
+ (*(factory as *mut dxgi::IDXGIFactory1))
+ .EnumAdapters1(idx, &mut adapter as *mut *mut _ as *mut *mut _)
+ };
+
+ if winerror::SUCCEEDED(hr) {
+ Ok(unsafe { ComPtr::from_raw(adapter) })
+ } else {
+ Err(hr)
+ }
+}
+
+fn get_adapter_desc(adapter: *mut dxgi::IDXGIAdapter, version: DxgiVersion) -> AdapterInfo {
+ match version {
+ DxgiVersion::Dxgi1_0 => {
+ let mut desc: dxgi::DXGI_ADAPTER_DESC1 = unsafe { mem::zeroed() };
+ unsafe {
+ (*(adapter as *mut dxgi::IDXGIAdapter1)).GetDesc1(&mut desc);
+ }
+
+ let device_name = {
+ let len = desc.Description.iter().take_while(|&&c| c != 0).count();
+ let name = <OsString as OsStringExt>::from_wide(&desc.Description[..len]);
+ name.to_string_lossy().into_owned()
+ };
+
+ AdapterInfo {
+ name: device_name,
+ vendor: desc.VendorId as usize,
+ device: desc.DeviceId as usize,
+ device_type: if (desc.Flags & dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) != 0 {
+ DeviceType::VirtualGpu
+ } else {
+ DeviceType::DiscreteGpu
+ },
+ }
+ }
+ DxgiVersion::Dxgi1_2
+ | DxgiVersion::Dxgi1_3
+ | DxgiVersion::Dxgi1_4
+ | DxgiVersion::Dxgi1_5 => {
+ let mut desc: dxgi1_2::DXGI_ADAPTER_DESC2 = unsafe { mem::zeroed() };
+ unsafe {
+ (*(adapter as *mut dxgi1_2::IDXGIAdapter2)).GetDesc2(&mut desc);
+ }
+
+ let device_name = {
+ let len = desc.Description.iter().take_while(|&&c| c != 0).count();
+ let name = <OsString as OsStringExt>::from_wide(&desc.Description[..len]);
+ name.to_string_lossy().into_owned()
+ };
+
+ AdapterInfo {
+ name: device_name,
+ vendor: desc.VendorId as usize,
+ device: desc.DeviceId as usize,
+ device_type: if (desc.Flags & dxgi::DXGI_ADAPTER_FLAG_SOFTWARE) != 0 {
+ DeviceType::VirtualGpu
+ } else {
+ DeviceType::DiscreteGpu
+ },
+ }
+ }
+ }
+}
+
+pub(crate) fn get_adapter(
+ idx: u32,
+ factory: *mut dxgi::IDXGIFactory,
+ version: DxgiVersion,
+) -> Result<(ComPtr<dxgi::IDXGIAdapter>, AdapterInfo), winerror::HRESULT> {
+ let adapter = match version {
+ DxgiVersion::Dxgi1_0
+ | DxgiVersion::Dxgi1_2
+ | DxgiVersion::Dxgi1_3
+ | DxgiVersion::Dxgi1_4
+ | DxgiVersion::Dxgi1_5 => enum_adapters1(idx, factory)?,
+ };
+
+ let desc = get_adapter_desc(adapter.as_raw(), version);
+
+ Ok((adapter, desc))
+}