use bitflags::bitflags;
use crate::error::*;
use crate::format::DxgiFormat;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use enum_primitive_derive::Primitive;
use num_traits::FromPrimitive;
use std::fmt;
use std::io::{Read, Write};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Primitive)]
pub enum D3D10ResourceDimension {
Unknown = 0,
Buffer = 1,
Texture1D = 2,
Texture2D = 3,
Texture3D = 4,
}
#[derive(Clone)]
pub struct Header10 {
pub dxgi_format: DxgiFormat,
pub resource_dimension: D3D10ResourceDimension,
pub misc_flag: MiscFlag,
pub array_size: u32,
pub alpha_mode: AlphaMode,
}
impl fmt::Debug for Header10 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, " Header10:")?;
writeln!(f, " dxgi_format: {:?}", self.dxgi_format)?;
writeln!(f, " resource_dimension: {:?}", self.resource_dimension)?;
writeln!(f, " misc_flag: {:?}", self.misc_flag)?;
writeln!(f, " array_size: {:?}", self.array_size)?;
write!(f, " alpha_mode: {:?}", self.alpha_mode)?;
Ok(())
}
}
impl Default for Header10 {
fn default() -> Header10 {
Header10 {
dxgi_format: DxgiFormat::Unknown,
resource_dimension: D3D10ResourceDimension::Unknown,
misc_flag: MiscFlag::empty(),
array_size: 0,
alpha_mode: AlphaMode::Unknown,
}
}
}
impl Header10 {
pub fn new(
format: DxgiFormat,
is_cubemap: bool,
resource_dimension: D3D10ResourceDimension,
array_size: u32,
alpha_mode: AlphaMode,
) -> Header10 {
let mut flags = MiscFlag::empty();
if is_cubemap {
flags |= MiscFlag::TEXTURECUBE
};
Header10 {
dxgi_format: format,
resource_dimension,
misc_flag: flags,
array_size,
alpha_mode,
}
}
pub fn read<R: Read>(mut r: R) -> Result<Header10, Error> {
let dxgi_format = r.read_u32::<LittleEndian>()?;
let resource_dimension = r.read_u32::<LittleEndian>()?;
let misc_flag = MiscFlag::from_bits_truncate(r.read_u32::<LittleEndian>()?);
let array_size = r.read_u32::<LittleEndian>()?;
let alpha_mode = r.read_u32::<LittleEndian>()?;
let dxgi_format_result: Result<DxgiFormat, Error> = DxgiFormat::from_u32(dxgi_format)
.ok_or_else(|| Error::InvalidField("dxgi_format".to_owned()));
let resource_dimension_result: Result<D3D10ResourceDimension, Error> =
D3D10ResourceDimension::from_u32(resource_dimension)
.ok_or_else(|| Error::InvalidField("resource_dimension".to_owned()));
let alpha_mode: Result<AlphaMode, Error> = AlphaMode::from_u32(alpha_mode)
.ok_or_else(|| Error::InvalidField("alpha mode (misc_flags2)".to_owned()));
Ok(Header10 {
dxgi_format: dxgi_format_result?,
resource_dimension: resource_dimension_result?,
misc_flag,
array_size,
alpha_mode: alpha_mode?,
})
}
pub fn write<W: Write>(&self, w: &mut W) -> Result<(), Error> {
w.write_u32::<LittleEndian>(self.dxgi_format as u32)?;
w.write_u32::<LittleEndian>(self.resource_dimension as u32)?;
w.write_u32::<LittleEndian>(self.misc_flag.bits())?;
w.write_u32::<LittleEndian>(self.array_size)?;
w.write_u32::<LittleEndian>(self.alpha_mode as u32)?;
Ok(())
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MiscFlag: u32 {
const TEXTURECUBE = 0x4;
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Primitive)]
pub enum AlphaMode {
Unknown = 0x0,
Straight = 0x1,
PreMultiplied = 0x2,
Opaque = 0x3,
Custom = 0x4,
}