use device::Device;
use device_context::DeviceContext;
use error::Error;
use flags::{CreateDeviceFlags, DriverType, FeatureLevel};
use std::ptr;
use dxgi::adapter::Adapter;
use winapi::shared::dxgi::IDXGIAdapter;
use winapi::shared::minwindef::HMODULE;
use winapi::um::d3d11::{D3D11CreateDevice, D3D11_SDK_VERSION};
pub struct DeviceBuilder<'a> {
adapter: Option<&'a Adapter>,
driver_type: Option<DriverType>,
flags: CreateDeviceFlags,
feature_levels: &'a [FeatureLevel],
software_module: HMODULE,
}
impl<'a> Default for DeviceBuilder<'a> {
fn default() -> Self {
DeviceBuilder {
adapter: None,
driver_type: None,
flags: CreateDeviceFlags::NONE,
feature_levels: &[],
software_module: ptr::null_mut(),
}
}
}
impl<'a> DeviceBuilder<'a> {
pub fn with_driver_type(mut self, driver_type: DriverType) -> Self {
assert!(
(driver_type == DriverType::Unknown || self.adapter.is_none())
&& (driver_type == DriverType::Software || self.software_module.is_null()),
"If an adapter is specified, driver_type must be `Unknown`"
);
self.driver_type = Some(driver_type);
self
}
pub fn with_adapter(mut self, adapter: &'a Adapter) -> Self {
assert!(
self.driver_type.is_none() || self.driver_type == Some(DriverType::Unknown),
"Cannot specify Adapter if driver_type is not `Unknown`"
);
self.driver_type = Some(DriverType::Unknown);
self.adapter = Some(adapter);
self
}
pub fn with_flags(mut self, flags: CreateDeviceFlags) -> Self {
assert!(
!flags.is_set(CreateDeviceFlags::SINGLETHREADED),
"SINGLETHREADED is not supported right now. If this usecase is important, please open an issue."
);
assert!(flags.validate(), "Invalid flags passed");
self.flags = flags;
self
}
pub fn with_feature_levels(mut self, levels: &'a [FeatureLevel]) -> Self {
self.feature_levels = levels;
self
}
pub unsafe fn with_software_module(mut self, software: HMODULE) -> Self {
assert!(
self.driver_type.is_none() || self.driver_type == Some(DriverType::Software),
"Cannot specify software_module if driver_type is not `Software`"
);
self.driver_type = Some(DriverType::Software);
self.software_module = software;
self
}
pub fn build(self) -> Result<(FeatureLevel, Device, DeviceContext), Error> {
unsafe {
let mut dev_ptr = ptr::null_mut();
let mut feature_level = 0;
let mut devctx_ptr = ptr::null_mut();
let hr = D3D11CreateDevice(
self.adapter
.map(|a| a.get_raw() as *mut IDXGIAdapter)
.unwrap_or(ptr::null_mut()),
self.driver_type.unwrap_or(DriverType::Hardware) as u32,
self.software_module,
self.flags.0,
if !self.feature_levels.is_empty() {
&self.feature_levels[0].0
} else {
ptr::null()
},
self.feature_levels.len() as u32,
D3D11_SDK_VERSION,
&mut dev_ptr,
&mut feature_level,
&mut devctx_ptr,
);
let dev = Error::wrap_if(hr, dev_ptr)?;
let ctx = Error::wrap_if(hr, devctx_ptr)?;
let features = FeatureLevel(feature_level);
Ok((features, dev, ctx))
}
}
}