use windows::core::{Interface};
use windows::Win32::Foundation::LUID;
use windows::Win32::Graphics::Dxgi::{CreateDXGIFactory2, DXGI_ADAPTER_DESC3, IDXGIAdapter4, IDXGIFactory4};
use crate::outputs::Display;
use crate::utils::convert_u16_to_string;
#[cfg(test)]
mod test {
use crate::devices::AdapterFactory;
#[test]
fn test_adapter_methods() {
for adapter in AdapterFactory::new() {
println!("{}", adapter.name());
println!("{:?}", adapter.luid());
}
}
#[test]
fn test_adapter_factory() {
for adapter in AdapterFactory::new() {
println!("{}", adapter.name());
}
}
}
#[repr(transparent)]
#[derive(Clone)]
pub struct Adapter(pub IDXGIAdapter4);
unsafe impl Send for Adapter {}
unsafe impl Sync for Adapter {}
impl Adapter {
pub fn name(&self) -> String {
let desc: DXGI_ADAPTER_DESC3 = unsafe { self.0.GetDesc3().unwrap() };
convert_u16_to_string(&desc.Description)
}
pub fn luid(&self) -> LUID {
let desc: DXGI_ADAPTER_DESC3 = unsafe { self.0.GetDesc3().unwrap() };
desc.AdapterLuid
}
pub fn iter_displays(&self) -> DisplayIterator {
DisplayIterator::new(self.clone())
}
pub fn get_display_by_idx(&self, idx: u32) -> Option<Display> {
DisplayIterator::get_display_by_idx(&self, idx)
}
}
#[repr(C)]
pub struct DisplayIterator {
adapter: Adapter,
idx: u32,
}
impl DisplayIterator {
fn new(adapter: Adapter) -> Self {
Self {
adapter,
idx: 0,
}
}
fn get_display_by_idx(adapter: &Adapter, idx: u32) -> Option<Display> {
let output = unsafe { adapter.0.EnumOutputs(idx) };
if output.is_err() {
None
} else {
Some(Display::new(output.unwrap().cast().unwrap()))
}
}
}
impl Iterator for DisplayIterator {
type Item = Display;
fn next(&mut self) -> Option<Self::Item> {
let out = Self::get_display_by_idx(&self.adapter, self.idx);
if out.is_some() {
self.idx += 1;
} else {
self.idx = 0;
}
out
}
}
pub struct AdapterFactory {
fac: IDXGIFactory4,
count: u32,
}
unsafe impl Send for AdapterFactory {}
unsafe impl Sync for AdapterFactory {}
impl Default for AdapterFactory {
fn default() -> Self {
AdapterFactory::new()
}
}
impl AdapterFactory {
pub fn new() -> Self {
unsafe {
let dxgi_factory: IDXGIFactory4 = CreateDXGIFactory2(0).unwrap();
Self {
fac: dxgi_factory,
count: 0,
}
}
}
pub fn get_adapter_by_idx(&self, idx: u32) -> Option<Adapter> {
let adapter = unsafe { self.fac.EnumAdapters1(idx) };
if adapter.is_ok() {
Some(Adapter(adapter.unwrap().cast().unwrap()))
} else {
None
}
}
pub fn get_adapter_by_luid(&self, luid: LUID) -> Option<Adapter> {
let adapter = unsafe { self.fac.EnumAdapterByLuid(luid) };
if adapter.is_ok() {
Some(Adapter(adapter.unwrap()))
} else {
None
}
}
pub fn reset(&mut self) {
self.count = 0;
}
}
impl Iterator for AdapterFactory {
type Item = Adapter;
fn next(&mut self) -> Option<Self::Item> {
let adapter = self.get_adapter_by_idx(self.count);
self.count += 1;
if adapter.is_none() {
self.count = 0;
}
adapter
}
}