use attrib::{FloatSize, IntSubType};
use std::default::Default;
use std::fmt;
use state;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SurfaceError {
UnsupportedFormat,
UnsupportedGamma,
}
#[derive(Copy, Clone, PartialEq)]
pub enum TextureError {
UnsupportedFormat,
UnsupportedGamma,
UnsupportedSampling,
InvalidInfo(TextureInfo),
IncorrectSize(usize),
}
impl fmt::Debug for TextureError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&TextureError::UnsupportedFormat =>
write!(f, "Failed to map a given format to the device"),
&TextureError::UnsupportedGamma =>
write!(f, "Failed to provide sRGB formats"),
&TextureError::UnsupportedSampling =>
write!(
f,
"Failed to map a given multisampled kind to the device"
),
&TextureError::InvalidInfo(info) =>
write!(
f,
"Invalid TextureInfo (width, height, and levels must not \
be zero): {:?}\n",
info
),
&TextureError::IncorrectSize(expected) =>
write!(
f,
"Invalid data size provided to update the texture, \
expected size {:?}",
expected
),
}
}
}
pub type Size = u16;
pub type Bits = u8;
pub type NumSamples = u8;
pub type NumFragments = u8;
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum AaMode {
Msaa(NumSamples),
Eqaa(NumSamples, NumFragments),
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[repr(u8)]
pub enum Components {
R,
RG,
RGB,
RGBA,
}
impl Components {
pub fn get_count(&self) -> u8 {
match *self {
Components::R => 1,
Components::RG => 2,
Components::RGB => 3,
Components::RGBA => 4,
}
}
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
pub enum Compression {
ETC2_RGB,
ETC2_SRGB,
ETC2_EAC_RGBA8,
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
pub enum Format {
Float(Components, FloatSize),
Integer(Components, Bits, IntSubType),
Unsigned(Components, Bits, IntSubType),
Compressed(Compression),
R3_G3_B2,
R5_G6_B5,
RGB5_A1,
RGB10_A2,
RGB10_A2UI,
R11F_G11F_B10F,
RGB9_E5,
BGRA8,
SRGB8,
SRGB8_A8,
DEPTH16,
DEPTH24,
DEPTH32F,
DEPTH24_STENCIL8,
DEPTH32F_STENCIL8,
}
impl Format {
pub fn get_components(&self) -> Option<Components> {
Some(match *self {
Format::Float(c, _) => c,
Format::Integer(c, _, _) => c,
Format::Unsigned(c, _, _) => c,
Format::Compressed(_) => {
error!("Tried to get components of compressed texel!");
return None
},
Format::R3_G3_B2 |
Format::R5_G6_B5 |
Format::R11F_G11F_B10F |
Format::RGB9_E5 |
Format::SRGB8 => Components::RGB,
Format::RGB5_A1 |
Format::RGB10_A2 |
Format::RGB10_A2UI |
Format::BGRA8 |
Format::SRGB8_A8 => Components::RGBA,
Format::DEPTH16 |
Format::DEPTH24 |
Format::DEPTH32F |
Format::DEPTH24_STENCIL8 |
Format::DEPTH32F_STENCIL8 => return None,
})
}
pub fn is_color(&self) -> bool {
match *self {
Format::DEPTH16 |
Format::DEPTH24 |
Format::DEPTH32F |
Format::DEPTH24_STENCIL8 |
Format::DEPTH32F_STENCIL8 => false,
_ => true,
}
}
pub fn has_depth(&self) -> bool {
match *self {
Format::DEPTH16 |
Format::DEPTH24 |
Format::DEPTH32F |
Format::DEPTH24_STENCIL8 |
Format::DEPTH32F_STENCIL8 => true,
_ => false,
}
}
pub fn has_stencil(&self) -> bool {
match *self {
Format::DEPTH24_STENCIL8 |
Format::DEPTH32F_STENCIL8 => true,
_ => false,
}
}
pub fn is_compressed(&self) -> bool {
match *self {
Format::Compressed(_) => true,
_ => false
}
}
pub fn does_convert_gamma(&self) -> bool {
match *self {
Format::SRGB8 |
Format::SRGB8_A8 |
Format::Compressed(Compression::ETC2_SRGB) => true,
_ => false,
}
}
pub fn get_size(&self) -> Option<u8> {
Some(match *self {
Format::Float(c, FloatSize::F16) => c.get_count() * 2,
Format::Float(c, FloatSize::F32) => c.get_count() * 4,
Format::Float(c, FloatSize::F64) => c.get_count() * 8,
Format::Integer(c, bits, _) => (c.get_count() * bits) >> 3,
Format::Unsigned(c, bits, _) => (c.get_count() * bits) >> 3,
Format::Compressed(_) => return None,
Format::R3_G3_B2 => 1,
Format::R5_G6_B5 => 2,
Format::RGB5_A1 => 2,
Format::RGB10_A2 => 4,
Format::RGB10_A2UI => 4,
Format::R11F_G11F_B10F => 4,
Format::RGB9_E5 => 4,
Format::BGRA8 => 4,
Format::SRGB8 => 4,
Format::SRGB8_A8 => 4,
Format::DEPTH16 => 2,
Format::DEPTH24 => 4,
Format::DEPTH32F => 4,
Format::DEPTH24_STENCIL8 => 4,
Format::DEPTH32F_STENCIL8 => 8,
})
}
}
pub static R8 : Format = Format::Unsigned(Components::R, 8, IntSubType::Normalized);
pub static RGBA8 : Format = Format::Unsigned(Components::RGBA, 8, IntSubType::Normalized);
pub static RGBA16F: Format = Format::Float(Components::RGBA, FloatSize::F16);
pub static RGBA32F: Format = Format::Float(Components::RGBA, FloatSize::F32);
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct SurfaceInfo {
pub width: Size,
pub height: Size,
pub format: Format,
pub aa_mode: Option<AaMode>,
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum FilterMethod {
Scale,
Mipmap,
Bilinear,
Trilinear,
Anisotropic(u8)
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
#[allow(missing_docs)]
pub enum CubeFace {
PosZ,
NegZ,
PosX,
NegX,
PosY,
NegY
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum Kind {
D1,
D1Array,
D2,
D2Array,
D2MultiSample(AaMode),
D2MultiSampleArray(AaMode),
Cube(CubeFace),
D3,
}
impl Kind {
pub fn get_aa_mode(&self) -> Option<AaMode> {
match *self {
Kind::D2MultiSample(aa) => Some(aa),
Kind::D2MultiSampleArray(aa) => Some(aa),
_ => None,
}
}
}
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct TextureInfo {
pub width: Size,
pub height: Size,
pub depth: Size,
pub levels: u8,
pub kind: Kind,
pub format: Format,
}
#[allow(missing_docs)]
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub struct ImageInfo {
pub xoffset: Size,
pub yoffset: Size,
pub zoffset: Size,
pub width: Size,
pub height: Size,
pub depth: Size,
pub format: Format,
pub mipmap: u8,
}
impl Default for ImageInfo {
fn default() -> ImageInfo {
ImageInfo {
xoffset: 0,
yoffset: 0,
zoffset: 0,
width: 0,
height: 1,
depth: 1,
format: RGBA8,
mipmap: 0
}
}
}
impl Default for TextureInfo {
fn default() -> TextureInfo {
TextureInfo {
width: 0,
height: 1,
depth: 1,
levels: !0,
kind: Kind::D2,
format: RGBA8,
}
}
}
impl TextureInfo {
pub fn new() -> TextureInfo {
Default::default()
}
pub fn contains(&self, img: &ImageInfo) -> bool {
self.width <= img.xoffset + img.width &&
self.height <= img.yoffset + img.height &&
self.depth <= img.zoffset + img.depth &&
self.format == img.format &&
img.mipmap < self.levels &&
self.kind.get_aa_mode().is_none()
}
}
impl From<TextureInfo> for ImageInfo {
fn from(ti: TextureInfo) -> ImageInfo {
ImageInfo {
xoffset: 0,
yoffset: 0,
zoffset: 0,
width: ti.width,
height: ti.height,
depth: ti.depth,
format: ti.format,
mipmap: 0,
}
}
}
impl From<TextureInfo> for SurfaceInfo {
fn from(ti: TextureInfo) -> SurfaceInfo {
SurfaceInfo {
width: ti.width,
height: ti.height,
format: ti.format,
aa_mode: ti.kind.get_aa_mode(),
}
}
}
impl ImageInfo {
pub fn new() -> ImageInfo { Default::default() }
pub fn get_texel_count(&self) -> usize {
self.width as usize *
self.height as usize *
self.depth as usize
}
}
#[derive(Eq, Ord, PartialEq, PartialOrd, Hash, Copy, Clone, Debug)]
pub enum WrapMode {
Tile,
Mirror,
Clamp,
}
#[derive(PartialEq, PartialOrd, Clone, Copy, Debug)]
pub struct SamplerInfo {
pub filtering: FilterMethod,
pub wrap_mode: (WrapMode, WrapMode, WrapMode),
pub lod_bias: f32,
pub lod_range: (f32, f32),
pub comparison: Option<state::Comparison>,
}
impl SamplerInfo {
pub fn new(filtering: FilterMethod, wrap: WrapMode) -> SamplerInfo {
SamplerInfo {
filtering: filtering,
wrap_mode: (wrap, wrap, wrap),
lod_bias: 0.0,
lod_range: (-1000.0, 1000.0),
comparison: None,
}
}
}