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