x-graphics 0.2.1

Graphics framework for X
Documentation
use windows::Win32::Graphics::{
    Direct2D::{D2D1CreateFactory, ID2D1Factory, D2D1_DEBUG_LEVEL_INFORMATION, D2D1_FACTORY_OPTIONS, D2D1_FACTORY_TYPE_SINGLE_THREADED},
    Direct3D::{D3D_DRIVER_TYPE, D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP},
    Direct3D11::{D3D11CreateDevice, ID3D11Device, D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_CREATE_DEVICE_DEBUG, D3D11_SDK_VERSION},
    DirectWrite::{DWriteCreateFactory, IDWriteFactory, DWRITE_FACTORY_TYPE_SHARED},
};

use crate::{device::DeviceContextBackend, error::GraphicsError};

#[derive(Clone, Debug)]
pub struct D2DDeviceContext {
    pub device: ID3D11Device,
    pub factory: ID2D1Factory,
    pub dwrite_factory: IDWriteFactory,
}

impl DeviceContextBackend for D2DDeviceContext {
    fn new() -> Result<Self, GraphicsError> {
        let factory = Self::new_factory()?;
        let device = Self::new_device()?;
        let dwrite_factory = Self::new_dwrite_factory()?;
        Ok(Self {
            factory,
            device,
            dwrite_factory,
        })
    }
}

impl D2DDeviceContext {
    fn new_factory() -> Result<ID2D1Factory, GraphicsError> {
        let mut options = D2D1_FACTORY_OPTIONS::default();
        if cfg!(debug_assertions) {
            options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
        }
        unsafe { D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, Some(&options)).map_err(|err| GraphicsError::CreationFailed(err.to_string())) }
    }

    fn new_device_with_type(device_type: D3D_DRIVER_TYPE) -> Result<ID3D11Device, GraphicsError> {
        let mut flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
        if cfg!(debug_assertions) {
            flags |= D3D11_CREATE_DEVICE_DEBUG;
        }
        let mut device = None;
        unsafe {
            D3D11CreateDevice(None, device_type, None, flags, None, D3D11_SDK_VERSION, Some(&mut device), None, None)
                .map(|_| device.unwrap())
                .map_err(|err| GraphicsError::CreationFailed(err.to_string()))
        }
    }

    fn new_device() -> Result<ID3D11Device, GraphicsError> {
        Self::new_device_with_type(D3D_DRIVER_TYPE_HARDWARE).or_else(|_| Self::new_device_with_type(D3D_DRIVER_TYPE_WARP))
    }

    fn new_dwrite_factory() -> Result<IDWriteFactory, GraphicsError> {
        unsafe { DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED).map_err(|err| GraphicsError::CreationFailed(err.to_string())) }
    }
}