diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/gfx-backend-dx11/src/dxgi.rs | |
parent | Initial commit. (diff) | |
download | firefox-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.rs | 213 |
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)) +} |