use memory::Pod;
macro_rules! impl_channel_type {
{ $($name:ident = $shader_type:ident [ $($imp_trait:ident),* ] ,)* } => {
#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub enum ChannelType {
$( $name, )*
}
$(
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub enum $name {}
impl ChannelTyped for $name {
type ShaderType = $shader_type;
fn get_channel_type() -> ChannelType {
ChannelType::$name
}
}
$(
impl $imp_trait for $name {}
)*
)*
}
}
impl_channel_type! {
Int = i32 [TextureChannel, RenderChannel],
Uint = u32 [TextureChannel, RenderChannel],
Inorm = f32 [TextureChannel, RenderChannel, BlendChannel],
Unorm = f32 [TextureChannel, RenderChannel, BlendChannel],
Float = f32 [TextureChannel, RenderChannel, BlendChannel],
Srgb = f32 [TextureChannel, RenderChannel, BlendChannel],
}
macro_rules! impl_formats {
{ $($name:ident : $container:ident < $($channel:ident),* > = $data_type:ty {$alpha_bits:expr} [ $($imp_trait:ident),* ], doc = $doc:expr ,)* } => {
#[repr(u8)]
#[allow(missing_docs, non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub enum SurfaceType {
$( #[doc = $doc] $name, )*
}
impl SurfaceType {
pub fn get_total_bits(&self) -> u8 {
use std::mem::size_of;
match *self {
$( SurfaceType::$name => (size_of::<$data_type>() * 8) as u8, )*
}
}
pub fn get_alpha_stencil_bits(&self) -> u8 {
match *self {
$( SurfaceType::$name => $alpha_bits, )*
}
}
}
$(
#[allow(missing_docs, non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
#[doc = $doc]
pub enum $name {}
impl SurfaceTyped for $name {
type DataType = $data_type;
fn get_surface_type() -> SurfaceType {
SurfaceType::$name
}
}
$(
impl $imp_trait for $name {}
)*
$(
impl Formatted for ($name, $channel) {
type Surface = $name;
type Channel = $channel;
type View = $container< <$channel as ChannelTyped>::ShaderType >;
}
)*
)*
}
}
impl_formats! {
R4_G4 : Vec2<Unorm> = u8 {0} [TextureSurface, RenderSurface], doc = "",
R4_G4_B4_A4 : Vec4<Unorm> = u16 {4} [TextureSurface, RenderSurface], doc = "",
R5_G5_B5_A1 : Vec4<Unorm> = u16 {1} [TextureSurface, RenderSurface], doc = "",
R5_G6_B5 : Vec3<Unorm> = u16 {0} [TextureSurface, RenderSurface], doc = "",
R8 : Vec1<Int, Uint, Inorm, Unorm> = u8 {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R8_G8 : Vec2<Int, Uint, Inorm, Unorm> = [u8; 2] {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R8_G8_B8_A8 : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 4] {8}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R10_G10_B10_A2 : Vec4<Uint, Unorm> = u32 {2}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R11_G11_B10 : Vec4<Unorm, Float> = u32 {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R16 : Vec1<Int, Uint, Inorm, Unorm, Float> = u16 {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R16_G16 : Vec2<Int, Uint, Inorm, Unorm, Float> = [u16; 2] {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R16_G16_B16 : Vec3<Int, Uint, Inorm, Unorm, Float> = [u16; 3] {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R16_G16_B16_A16 : Vec4<Int, Uint, Inorm, Unorm, Float> = [u16; 4] {16}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R32 : Vec1<Int, Uint, Float> = u32 {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R32_G32 : Vec2<Int, Uint, Float> = [u32; 2] {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R32_G32_B32 : Vec3<Int, Uint, Float> = [u32; 3] {0}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
R32_G32_B32_A32 : Vec4<Int, Uint, Float> = [u32; 4] {32}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
B8_G8_R8_A8 : Vec4<Unorm, Srgb> = [u8; 4] {32}
[BufferSurface, TextureSurface, RenderSurface], doc = "",
D16 : Vec1<Unorm> = F16 {0} [TextureSurface, DepthSurface], doc = "",
D24 : Vec1<Unorm> = f32 {8} [TextureSurface, DepthSurface], doc = "",
D24_S8 : Vec1<Unorm, Uint> = u32 {8} [TextureSurface, DepthSurface, StencilSurface], doc = "",
D32 : Vec1<Float> = f32 {0} [TextureSurface, DepthSurface], doc = "",
BC1_R8_G8_B8 : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 3] {0} [TextureSurface],
doc = "Block Compression 1 also known as DXT1, S3TC. See \
[S3TC wiki](https://wikipedia.org/wiki/S3_Texture_Compression).\
\n\nCurrently supported in the gfx_device_gl backend only.",
BC3_R8_G8_B8_A8 : Vec4<Int, Uint, Inorm, Unorm, Srgb> = [u8; 4] {8} [TextureSurface],
doc = "Block Compression 3 also known as DXT5, S3TC. See \
[S3TC wiki](https://wikipedia.org/wiki/S3_Texture_Compression).\
\n\nCurrently supported in the gfx_device_gl backend only.",
}
#[allow(missing_docs)]
#[repr(u8)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub enum ChannelSource {
Zero,
One,
X,
Y,
Z,
W,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub struct Swizzle(pub ChannelSource, pub ChannelSource, pub ChannelSource, pub ChannelSource);
impl Swizzle {
pub fn new() -> Swizzle {
Swizzle(ChannelSource::X, ChannelSource::Y, ChannelSource::Z, ChannelSource::W)
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub struct Format(pub SurfaceType, pub ChannelType);
pub trait SurfaceTyped {
type DataType: Pod;
fn get_surface_type() -> SurfaceType;
}
pub trait BufferSurface: SurfaceTyped {}
pub trait TextureSurface: SurfaceTyped {}
pub trait RenderSurface: SurfaceTyped {}
pub trait DepthSurface: SurfaceTyped {}
pub trait StencilSurface: SurfaceTyped {}
pub trait ChannelTyped {
type ShaderType;
fn get_channel_type() -> ChannelType;
}
pub trait TextureChannel: ChannelTyped {}
pub trait RenderChannel: ChannelTyped {}
pub trait BlendChannel: RenderChannel {}
pub trait Formatted {
type Surface: SurfaceTyped;
type Channel: ChannelTyped;
type View;
fn get_format() -> Format {
Format(
Self::Surface::get_surface_type(),
Self::Channel::get_channel_type())
}
}
pub trait BufferFormat: Formatted {}
pub trait DepthFormat: Formatted {}
pub trait StencilFormat: Formatted {}
pub trait DepthStencilFormat: DepthFormat + StencilFormat {}
pub trait TextureFormat: Formatted {}
pub trait RenderFormat: Formatted {}
pub trait BlendFormat: RenderFormat {}
impl<F> BufferFormat for F where
F: Formatted,
F::Surface: BufferSurface,
F::Channel: ChannelTyped,
{}
impl<F> DepthFormat for F where
F: Formatted,
F::Surface: DepthSurface,
F::Channel: RenderChannel,
{}
impl<F> StencilFormat for F where
F: Formatted,
F::Surface: StencilSurface,
F::Channel: RenderChannel,
{}
impl<F> DepthStencilFormat for F where
F: DepthFormat + StencilFormat
{}
impl<F> TextureFormat for F where
F: Formatted,
F::Surface: TextureSurface,
F::Channel: TextureChannel,
{}
impl<F> RenderFormat for F where
F: Formatted,
F::Surface: RenderSurface,
F::Channel: RenderChannel,
{}
impl<F> BlendFormat for F where
F: Formatted,
F::Surface: RenderSurface,
F::Channel: BlendChannel,
{}
macro_rules! alias {
{ $( $name:ident = $ty:ty, )* } => {
$(
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub struct $name(pub $ty);
impl From<$ty> for $name {
fn from(v: $ty) -> $name {
$name(v)
}
}
unsafe impl Pod for $name {}
impl $name {
pub fn cast2(v: [$ty; 2]) -> [$name; 2] {
[$name(v[0]), $name(v[1])]
}
pub fn cast3(v: [$ty; 3]) -> [$name; 3] {
[$name(v[0]), $name(v[1]), $name(v[2])]
}
pub fn cast4(v: [$ty; 4]) -> [$name; 4] {
[$name(v[0]), $name(v[1]), $name(v[2]), $name(v[3])]
}
pub fn cast_slice(slice: &[$ty]) -> &[$name] {
use std::mem::transmute;
unsafe { transmute(slice) }
}
}
)*
}
}
alias! {
U8Norm = u8,
I8Norm = i8,
U16Norm = u16,
I16Norm = i16,
F16 = u16,
}
pub type Vec1<T> = T;
pub type Vec2<T> = [T; 2];
pub type Vec3<T> = [T; 3];
pub type Vec4<T> = [T; 4];
pub type Rgba8 = (R8_G8_B8_A8, Unorm);
pub type Srgba8 = (R8_G8_B8_A8, Srgb);
pub type Rgb10a2F = (R10_G10_B10_A2, Float);
pub type Rgba16F = (R16_G16_B16_A16, Float);
pub type Rgba32F = (R32_G32_B32_A32, Float);
pub type Bgra8 = (B8_G8_R8_A8, Unorm);
pub type Depth = (D24, Unorm);
pub type DepthStencil = (D24_S8, Unorm);
pub type Depth32F = (D32, Float);
macro_rules! impl_simple_formats {
{ $( $container:ident< $ty:ty > = $channel:ident $surface:ident, )* } => {
$(
impl Formatted for $container<$ty> {
type Surface = $surface;
type Channel = $channel;
type View = $container<<$channel as ChannelTyped>::ShaderType>;
}
)*
}
}
macro_rules! impl_formats_8bit {
{ $( $ty:ty = $channel:ident, )* } => {
impl_simple_formats! {$(
Vec1<$ty> = $channel R8,
Vec2<$ty> = $channel R8_G8,
Vec4<$ty> = $channel R8_G8_B8_A8,
)*}
}
}
macro_rules! impl_formats_16bit {
{ $( $ty:ty = $channel:ident, )* } => {
impl_simple_formats! {$(
Vec1<$ty> = $channel R16,
Vec2<$ty> = $channel R16_G16,
Vec3<$ty> = $channel R16_G16_B16,
Vec4<$ty> = $channel R16_G16_B16_A16,
)*}
}
}
macro_rules! impl_formats_32bit {
{ $( $ty:ty = $channel:ident, )* } => {
impl_simple_formats! {$(
Vec1<$ty> = $channel R32,
Vec2<$ty> = $channel R32_G32,
Vec3<$ty> = $channel R32_G32_B32,
Vec4<$ty> = $channel R32_G32_B32_A32,
)*}
}
}
impl_formats_8bit! {
u8 = Uint,
i8 = Int,
U8Norm = Unorm,
I8Norm = Inorm,
}
impl_formats_16bit! {
u16 = Uint,
i16 = Int,
U16Norm = Unorm,
I16Norm = Inorm,
F16 = Float,
}
impl_formats_32bit! {
u32 = Uint,
i32 = Int,
f32 = Float,
}