1 use crate::{com::WeakPtr, CommandQueue, D3DResult, Resource, SampleDesc, HRESULT}; 2 use std::ptr; 3 use winapi::{ 4 shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgiformat, dxgitype, windef::HWND}, 5 um::{d3d12, dxgidebug}, 6 Interface, 7 }; 8 9 bitflags! { 10 pub struct FactoryCreationFlags: u32 { 11 const DEBUG = dxgi1_3::DXGI_CREATE_FACTORY_DEBUG; 12 } 13 } 14 15 #[repr(u32)] 16 #[derive(Debug, Copy, Clone)] 17 pub enum Scaling { 18 Stretch = dxgi1_2::DXGI_SCALING_STRETCH, 19 Identity = dxgi1_2::DXGI_SCALING_NONE, 20 Aspect = dxgi1_2::DXGI_SCALING_ASPECT_RATIO_STRETCH, 21 } 22 23 #[repr(u32)] 24 #[derive(Debug, Copy, Clone)] 25 pub enum SwapEffect { 26 Discard = dxgi::DXGI_SWAP_EFFECT_DISCARD, 27 Sequential = dxgi::DXGI_SWAP_EFFECT_SEQUENTIAL, 28 FlipDiscard = dxgi::DXGI_SWAP_EFFECT_FLIP_DISCARD, 29 FlipSequential = dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, 30 } 31 32 #[repr(u32)] 33 #[derive(Debug, Copy, Clone)] 34 pub enum AlphaMode { 35 Unspecified = dxgi1_2::DXGI_ALPHA_MODE_UNSPECIFIED, 36 Premultiplied = dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED, 37 Straight = dxgi1_2::DXGI_ALPHA_MODE_STRAIGHT, 38 Ignore = dxgi1_2::DXGI_ALPHA_MODE_IGNORE, 39 ForceDword = dxgi1_2::DXGI_ALPHA_MODE_FORCE_DWORD, 40 } 41 42 pub type Adapter1 = WeakPtr<dxgi::IDXGIAdapter1>; 43 pub type Factory2 = WeakPtr<dxgi1_2::IDXGIFactory2>; 44 pub type Factory4 = WeakPtr<dxgi1_4::IDXGIFactory4>; 45 pub type InfoQueue = WeakPtr<dxgidebug::IDXGIInfoQueue>; 46 pub type SwapChain = WeakPtr<dxgi::IDXGISwapChain>; 47 pub type SwapChain1 = WeakPtr<dxgi1_2::IDXGISwapChain1>; 48 pub type SwapChain3 = WeakPtr<dxgi1_4::IDXGISwapChain3>; 49 50 #[cfg(feature = "libloading")] 51 #[derive(Debug)] 52 pub struct DxgiLib { 53 lib: libloading::Library, 54 } 55 56 #[cfg(feature = "libloading")] 57 impl DxgiLib { new() -> Result<Self, libloading::Error>58 pub fn new() -> Result<Self, libloading::Error> { 59 unsafe { libloading::Library::new("dxgi.dll").map(|lib| DxgiLib { lib }) } 60 } 61 create_factory2( &self, flags: FactoryCreationFlags, ) -> Result<D3DResult<Factory4>, libloading::Error>62 pub fn create_factory2( 63 &self, 64 flags: FactoryCreationFlags, 65 ) -> Result<D3DResult<Factory4>, libloading::Error> { 66 type Fun = extern "system" fn( 67 winapi::shared::minwindef::UINT, 68 winapi::shared::guiddef::REFIID, 69 *mut *mut winapi::ctypes::c_void, 70 ) -> HRESULT; 71 72 let mut factory = Factory4::null(); 73 let hr = unsafe { 74 let func: libloading::Symbol<Fun> = self.lib.get(b"CreateDXGIFactory2")?; 75 func( 76 flags.bits(), 77 &dxgi1_4::IDXGIFactory4::uuidof(), 78 factory.mut_void(), 79 ) 80 }; 81 82 Ok((factory, hr)) 83 } 84 get_debug_interface1(&self) -> Result<D3DResult<InfoQueue>, libloading::Error>85 pub fn get_debug_interface1(&self) -> Result<D3DResult<InfoQueue>, libloading::Error> { 86 type Fun = extern "system" fn( 87 winapi::shared::minwindef::UINT, 88 winapi::shared::guiddef::REFIID, 89 *mut *mut winapi::ctypes::c_void, 90 ) -> HRESULT; 91 92 let mut queue = InfoQueue::null(); 93 let hr = unsafe { 94 let func: libloading::Symbol<Fun> = self.lib.get(b"DXGIGetDebugInterface1")?; 95 func(0, &dxgidebug::IDXGIInfoQueue::uuidof(), queue.mut_void()) 96 }; 97 Ok((queue, hr)) 98 } 99 } 100 101 // TODO: strong types 102 pub struct SwapchainDesc { 103 pub width: u32, 104 pub height: u32, 105 pub format: dxgiformat::DXGI_FORMAT, 106 pub stereo: bool, 107 pub sample: SampleDesc, 108 pub buffer_usage: dxgitype::DXGI_USAGE, 109 pub buffer_count: u32, 110 pub scaling: Scaling, 111 pub swap_effect: SwapEffect, 112 pub alpha_mode: AlphaMode, 113 pub flags: u32, 114 } 115 116 impl Factory2 { 117 // TODO: interface not complete create_swapchain_for_hwnd( &self, queue: CommandQueue, hwnd: HWND, desc: &SwapchainDesc, ) -> D3DResult<SwapChain1>118 pub fn create_swapchain_for_hwnd( 119 &self, 120 queue: CommandQueue, 121 hwnd: HWND, 122 desc: &SwapchainDesc, 123 ) -> D3DResult<SwapChain1> { 124 let desc = dxgi1_2::DXGI_SWAP_CHAIN_DESC1 { 125 AlphaMode: desc.alpha_mode as _, 126 BufferCount: desc.buffer_count, 127 Width: desc.width, 128 Height: desc.height, 129 Format: desc.format, 130 Flags: desc.flags, 131 BufferUsage: desc.buffer_usage, 132 SampleDesc: dxgitype::DXGI_SAMPLE_DESC { 133 Count: desc.sample.count, 134 Quality: desc.sample.quality, 135 }, 136 Scaling: desc.scaling as _, 137 Stereo: desc.stereo as _, 138 SwapEffect: desc.swap_effect as _, 139 }; 140 141 let mut swap_chain = SwapChain1::null(); 142 let hr = unsafe { 143 self.CreateSwapChainForHwnd( 144 queue.as_mut_ptr() as *mut _, 145 hwnd, 146 &desc, 147 ptr::null(), 148 ptr::null_mut(), 149 swap_chain.mut_void() as *mut *mut _, 150 ) 151 }; 152 153 (swap_chain, hr) 154 } 155 } 156 157 impl Factory4 { 158 #[cfg(feature = "implicit-link")] create(flags: FactoryCreationFlags) -> D3DResult<Self>159 pub fn create(flags: FactoryCreationFlags) -> D3DResult<Self> { 160 let mut factory = Factory4::null(); 161 let hr = unsafe { 162 dxgi1_3::CreateDXGIFactory2( 163 flags.bits(), 164 &dxgi1_4::IDXGIFactory4::uuidof(), 165 factory.mut_void(), 166 ) 167 }; 168 169 (factory, hr) 170 } 171 as_factory2(&self) -> Factory2172 pub fn as_factory2(&self) -> Factory2 { 173 unsafe { Factory2::from_raw(self.as_mut_ptr() as *mut _) } 174 } 175 enumerate_adapters(&self, id: u32) -> D3DResult<Adapter1>176 pub fn enumerate_adapters(&self, id: u32) -> D3DResult<Adapter1> { 177 let mut adapter = Adapter1::null(); 178 let hr = unsafe { self.EnumAdapters1(id, adapter.mut_void() as *mut *mut _) }; 179 180 (adapter, hr) 181 } 182 } 183 184 bitflags! { 185 pub struct SwapChainPresentFlags: u32 { 186 const DXGI_PRESENT_DO_NOT_SEQUENCE = dxgi::DXGI_PRESENT_DO_NOT_SEQUENCE; 187 const DXGI_PRESENT_TEST = dxgi::DXGI_PRESENT_TEST; 188 const DXGI_PRESENT_RESTART = dxgi::DXGI_PRESENT_RESTART; 189 const DXGI_PRESENT_DO_NOT_WAIT = dxgi::DXGI_PRESENT_DO_NOT_WAIT; 190 const DXGI_PRESENT_RESTRICT_TO_OUTPUT = dxgi::DXGI_PRESENT_RESTRICT_TO_OUTPUT; 191 const DXGI_PRESENT_STEREO_PREFER_RIGHT = dxgi::DXGI_PRESENT_STEREO_PREFER_RIGHT; 192 const DXGI_PRESENT_STEREO_TEMPORARY_MONO = dxgi::DXGI_PRESENT_STEREO_TEMPORARY_MONO; 193 const DXGI_PRESENT_USE_DURATION = dxgi::DXGI_PRESENT_USE_DURATION; 194 const DXGI_PRESENT_ALLOW_TEARING = dxgi::DXGI_PRESENT_ALLOW_TEARING; 195 } 196 } 197 198 impl SwapChain { get_buffer(&self, id: u32) -> D3DResult<Resource>199 pub fn get_buffer(&self, id: u32) -> D3DResult<Resource> { 200 let mut resource = Resource::null(); 201 let hr = 202 unsafe { self.GetBuffer(id, &d3d12::ID3D12Resource::uuidof(), resource.mut_void()) }; 203 204 (resource, hr) 205 } 206 207 //TODO: replace by present_flags present(&self, interval: u32, flags: u32) -> HRESULT208 pub fn present(&self, interval: u32, flags: u32) -> HRESULT { 209 unsafe { self.Present(interval, flags) } 210 } 211 present_flags(&self, interval: u32, flags: SwapChainPresentFlags) -> HRESULT212 pub fn present_flags(&self, interval: u32, flags: SwapChainPresentFlags) -> HRESULT { 213 unsafe { self.Present(interval, flags.bits()) } 214 } 215 } 216 217 impl SwapChain1 { as_swapchain0(&self) -> SwapChain218 pub fn as_swapchain0(&self) -> SwapChain { 219 unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } 220 } 221 } 222 223 impl SwapChain3 { as_swapchain0(&self) -> SwapChain224 pub fn as_swapchain0(&self) -> SwapChain { 225 unsafe { SwapChain::from_raw(self.as_mut_ptr() as *mut _) } 226 } 227 get_current_back_buffer_index(&self) -> u32228 pub fn get_current_back_buffer_index(&self) -> u32 { 229 unsafe { self.GetCurrentBackBufferIndex() } 230 } 231 } 232