use core::marker::PhantomData;
use pixel::Pixel;
#[derive(Clone, Copy, Debug)]
pub enum Wrap {
ClampToEdge,
Repeat,
MirroredRepeat
}
#[derive(Clone, Copy, Debug)]
pub enum Filter {
Nearest,
Linear
}
#[derive(Clone, Copy, Debug)]
pub enum DepthComparison {
Never,
Always,
Equal,
NotEqual,
Less,
LessOrEqual,
Greater,
GreaterOrEqual
}
pub trait Dimensionable {
type Size;
type Offset;
fn dim() -> Dim;
fn width(size: Self::Size) -> u32 where Self::Size: Copy;
fn height(_: Self::Size) -> u32 where Self::Size: Copy { 1 }
fn depth(_: Self::Size) -> u32 where Self::Size: Copy { 1 }
fn x_offset(offset: Self::Offset) -> u32 where Self::Offset: Copy;
fn y_offset(_: Self::Offset) -> u32 where Self::Offset: Copy { 1 }
fn z_offset(_: Self::Offset) -> u32 where Self::Offset: Copy { 1 }
fn zero_offset() -> Self::Offset;
}
pub fn dim_capacity<D>(size: D::Size) -> u32 where D: Dimensionable, D::Size: Copy {
D::width(size) * D::height(size) * D::depth(size)
}
#[derive(Clone, Copy, Debug)]
pub enum Dim {
Dim1,
Dim2,
Dim3,
Cubemap
}
#[derive(Clone, Copy, Debug)]
pub struct Dim1;
impl Dimensionable for Dim1 {
type Size = u32;
type Offset = u32;
fn dim() -> Dim { Dim::Dim1 }
fn width(w: Self::Size) -> u32 { w }
fn x_offset(off: Self::Offset) -> u32 { off }
fn zero_offset() -> Self::Offset { 0 }
}
#[derive(Clone, Copy, Debug)]
pub struct Dim2;
impl Dimensionable for Dim2 {
type Size = (u32, u32);
type Offset = (u32, u32);
fn dim() -> Dim { Dim::Dim2 }
fn width(size: Self::Size) -> u32 { size.0 }
fn height(size: Self::Size) -> u32 { size.1 }
fn x_offset(off: Self::Offset) -> u32 { off.0 }
fn y_offset(off: Self::Offset) -> u32 { off.1 }
fn zero_offset() -> Self::Offset { (0, 0) }
}
#[derive(Clone, Copy, Debug)]
pub struct Dim3;
impl Dimensionable for Dim3 {
type Size = (u32, u32, u32);
type Offset = (u32, u32, u32);
fn dim() -> Dim { Dim::Dim3 }
fn width(size: Self::Size) -> u32 { size.0 }
fn height(size: Self::Size) -> u32 { size.1 }
fn depth(size: Self::Size) -> u32 { size.2 }
fn x_offset(off: Self::Offset) -> u32 { off.0 }
fn y_offset(off: Self::Offset) -> u32 { off.1 }
fn z_offset(off: Self::Offset) -> u32 { off.2 }
fn zero_offset() -> Self::Offset { (0, 0, 0) }
}
#[derive(Clone, Copy, Debug)]
pub struct Cubemap;
impl Dimensionable for Cubemap {
type Size = u32;
type Offset = (u32, u32, CubeFace);
fn dim() -> Dim { Dim::Cubemap }
fn width(s: Self::Size) -> u32 { s }
fn height(s: Self::Size) -> u32 { s }
fn depth(_: Self::Size) -> u32 { 6 }
fn x_offset(off: Self::Offset) -> u32 { off.0 }
fn y_offset(off: Self::Offset) -> u32 { off.1 }
fn z_offset(off: Self::Offset) -> u32 {
match off.2 {
CubeFace::PositiveX => 0,
CubeFace::NegativeX => 1,
CubeFace::PositiveY => 2,
CubeFace::NegativeY => 3,
CubeFace::PositiveZ => 4,
CubeFace::NegativeZ => 5
}
}
fn zero_offset() -> Self::Offset { (0, 0, CubeFace::PositiveX) }
}
#[derive(Clone, Copy, Debug)]
pub enum CubeFace {
PositiveX,
NegativeX,
PositiveY,
NegativeY,
PositiveZ,
NegativeZ
}
pub trait Layerable {
fn layering() -> Layering;
}
#[derive(Clone, Copy, Debug)]
pub enum Layering {
Flat,
Layered
}
#[derive(Clone, Copy, Debug)]
pub struct Flat;
impl Layerable for Flat { fn layering() -> Layering { Layering::Flat } }
#[derive(Clone, Copy, Debug)]
pub struct Layered;
impl Layerable for Layered { fn layering() -> Layering { Layering::Layered } }
pub trait HasTexture {
type ATexture;
fn new_texture<L, D, P>(size: D::Size, mipmaps: u32, sampler: &Sampler) -> Self::ATexture
where L: Layerable,
D: Dimensionable,
D::Size: Copy,
P: Pixel;
fn free(tex: &mut Self::ATexture);
fn clear_part<L, D, P>(tex: &Self::ATexture, gen_mimpmaps: bool, offset: D::Offset, size: D::Size, pixel: P::Encoding)
where L: Layerable, D: Dimensionable, D::Offset: Copy, D::Size: Copy, P: Pixel, P::Encoding: Copy;
fn upload_part<L, D, P>(tex: &Self::ATexture, gen_mipmaps: bool, offset: D::Offset, size: D::Size, texels: &Vec<P::Encoding>)
where L: Layerable, D::Offset: Copy, D::Size: Copy, D: Dimensionable, P: Pixel;
}
#[derive(Debug)]
pub struct Texture<C, L, D, P> where C: HasTexture, L: Layerable, D: Dimensionable, P: Pixel {
pub repr: C::ATexture,
pub size: D::Size,
pub mipmaps: u32,
_l: PhantomData<L>,
_c: PhantomData<C>,
_p: PhantomData<P>
}
impl<C, L, D, P> Drop for Texture<C, L, D, P> where C: HasTexture, L: Layerable, D: Dimensionable, P: Pixel {
fn drop(&mut self) {
C::free(&mut self.repr)
}
}
impl<C, L, D, P> Texture<C, L, D, P>
where C: HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P: Pixel {
pub fn new(size: D::Size, mipmaps: u32, sampler: &Sampler) -> Self {
let tex = C::new_texture::<L, D, P>(size, mipmaps, sampler);
Texture {
repr: tex,
size: size,
mipmaps: mipmaps,
_c: PhantomData,
_l: PhantomData,
_p: PhantomData
}
}
pub fn from_raw(texture: C::ATexture, size: D::Size, mipmaps: u32) -> Self {
Texture {
repr: texture,
size: size,
mipmaps: mipmaps,
_c: PhantomData,
_l: PhantomData,
_p: PhantomData
}
}
pub fn clear_part(&self, gen_mipmaps: bool, offset: D::Offset, size: D::Size, pixel: P::Encoding)
where D::Offset: Copy,
D::Size: Copy,
P::Encoding: Copy {
C::clear_part::<L, D, P>(&self.repr, gen_mipmaps, offset, size, pixel)
}
pub fn clear(&self, gen_mipmaps: bool, pixel: P::Encoding)
where D::Offset: Copy,
D::Size: Copy,
P::Encoding: Copy {
self.clear_part(gen_mipmaps, D::zero_offset(), self.size, pixel)
}
pub fn upload_part(&self, gen_mipmaps: bool, offset: D::Offset, size: D::Size, texels: &Vec<P::Encoding>)
where D::Offset: Copy,
D::Size: Copy {
C::upload_part::<L, D, P>(&self.repr, gen_mipmaps, offset, size, texels)
}
pub fn upload(&self, gen_mipmaps: bool, texels: &Vec<P::Encoding>)
where D::Offset: Copy,
D::Size: Copy {
self.upload_part(gen_mipmaps, D::zero_offset(), self.size, texels)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Sampler {
pub wrap_r: Wrap,
pub wrap_s: Wrap,
pub wrap_t: Wrap,
pub minification: Filter,
pub magnification: Filter,
pub depth_comparison: Option<DepthComparison>
}
impl Default for Sampler {
fn default() -> Self {
Sampler {
wrap_r: Wrap::ClampToEdge,
wrap_s: Wrap::ClampToEdge,
wrap_t: Wrap::ClampToEdge,
minification: Filter::Linear,
magnification: Filter::Linear,
depth_comparison: None
}
}
}