use chain::Chain;
use std::marker::PhantomData;
use pixel::{ColorPixel, DepthPixel, Pixel, PixelFormat, RenderablePixel};
use texture::{Dim2, Dimensionable, Flat, HasTexture, Layerable, Texture};
pub trait HasFramebuffer: HasTexture + Sized {
type Framebuffer;
fn new_framebuffer<L, D, CS, DS>(size: D::Size, mipmaps: usize) -> Result<(Self::Framebuffer, Vec<Self::ATexture>, Option<Self::ATexture>), FramebufferError>
where L: Layerable,
D: Dimensionable,
D::Size: Copy,
CS: ColorSlot<Self, L, D>,
DS: DepthSlot<Self, L, D>;
fn free_framebuffer(framebuffer: &mut Self::Framebuffer);
fn default_framebuffer<D>(size: D::Size) -> Self::Framebuffer
where D: Dimensionable,
D::Size: Copy;
}
#[derive(Debug)]
pub enum FramebufferError {
Incomplete(String)
}
#[derive(Debug)]
pub struct Framebuffer<C, L, D, CS, DS>
where C: HasTexture + HasFramebuffer,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
CS: ColorSlot<C, L, D>,
DS: DepthSlot<C, L, D> {
pub repr: C::Framebuffer,
pub color_slot: CS,
pub depth_slot: DS,
_l: PhantomData<L>,
_d: PhantomData<D>,
}
impl<C> Framebuffer<C, Flat, Dim2, (), ()> where C: HasTexture + HasFramebuffer {
pub fn default(size: <Dim2 as Dimensionable>::Size) -> Self {
Framebuffer {
repr: C::default_framebuffer::<Dim2>(size),
color_slot: (),
depth_slot: (),
_l: PhantomData,
_d: PhantomData,
}
}
}
impl<C, L, D, CS, DS> Drop for Framebuffer<C, L, D, CS, DS>
where C: HasTexture + HasFramebuffer,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
CS: ColorSlot<C, L, D>,
DS: DepthSlot<C, L, D> {
fn drop(&mut self) {
C::free_framebuffer(&mut self.repr)
}
}
impl<C, L, D, CS, DS> Framebuffer<C, L, D, CS, DS>
where C: HasTexture + HasFramebuffer,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
CS: ColorSlot<C, L, D>,
DS: DepthSlot<C, L, D> {
pub fn new(size: D::Size, mipmaps: usize) -> Result<Framebuffer<C, L, D, CS, DS>, FramebufferError> {
let mipmaps = mipmaps + 1;
C::new_framebuffer::<L, D, CS, DS>(size, mipmaps).map(|(framebuffer, mut color_textures, depth_texture)| {
Framebuffer {
repr: framebuffer,
color_slot: CS::reify_textures(size, mipmaps, &mut color_textures),
depth_slot: DS::reify_texture(size, mipmaps, depth_texture),
_l: PhantomData,
_d: PhantomData,
}
})
}
}
pub struct Slot<C, L, D, P>
where C: HasTexture,
L: Layerable,
D: Dimensionable,
P: Pixel {
pub texture: Texture<C, L, D, P>
}
pub trait ColorSlot<C, L, D> where C: HasFramebuffer + HasTexture, L: Layerable, D: Dimensionable, D::Size: Copy {
fn color_formats() -> Vec<PixelFormat>;
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self;
}
impl<C, L, D> ColorSlot<C, L, D> for () where C: HasFramebuffer + HasTexture, L: Layerable, D: Dimensionable, D::Size: Copy {
fn color_formats() -> Vec<PixelFormat> { Vec::new() }
fn reify_textures(_: D::Size, _: usize, _: &mut Vec<C::ATexture>) -> Self { () }
}
impl<C, L, D, P> ColorSlot<C, L, D> for Slot<C, L, D, P>
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> { vec![P::pixel_format()] }
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let color_texture = textures.swap_remove(0);
Slot {
texture: Texture::from_raw(color_texture, size, mipmaps)
}
}
}
impl<C, L, D, P, B> ColorSlot<C, L, D> for Chain<Slot<C, L, D, P>, B>
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P: ColorPixel + RenderablePixel,
B: ColorSlot<C, L, D> {
fn color_formats() -> Vec<PixelFormat> {
let mut a = Slot::<C, L, D, P>::color_formats();
a.extend(B::color_formats());
a
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let a = Slot::<C, L, D, P>::reify_textures(size, mipmaps, textures);
let b = B::reify_textures(size, mipmaps, textures);
Chain(a, b)
}
}
impl<C, L, D, P0, P1> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Slot<C, L, D, P1>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, b) = Chain::<Slot<C, L, D, P0>, Slot<C, L, D, P1>>::reify_textures(size, mipmaps, textures);
(a, b)
}
}
impl<C, L, D, P0, P1, P2> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Slot<C, L, D, P2>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, c)) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Slot<C, L, D, P2>>>::reify_textures(size, mipmaps, textures);
(a, b, c)
}
}
impl<C, L, D, P0, P1, P2, P3> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Slot<C, L, D, P3>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, d))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Slot<C, L, D, P3>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d)
}
}
impl<C, L, D, P0, P1, P2, P3, P4> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Slot<C, L, D, P4>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, e)))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Slot<C, L, D, P4>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e)
}
}
impl<C, L, D, P0, P1, P2, P3, P4, P5> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>, Slot<C, L, D, P5>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel,
P5: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Slot<C, L, D, P5>>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, Chain(e, f))))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Slot<C, L, D, P5>>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e, f)
}
}
impl<C, L, D, P0, P1, P2, P3, P4, P5, P6> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>, Slot<C, L, D, P5>, Slot<C, L, D, P6>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel,
P5: ColorPixel + RenderablePixel,
P6: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Slot<C, L, D, P6>>>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, Chain(e, Chain(f, g)))))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Slot<C, L, D, P6>>>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e, f, g)
}
}
impl<C, L, D, P0, P1, P2, P3, P4, P5, P6, P7> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>, Slot<C, L, D, P5>, Slot<C, L, D, P6>, Slot<C, L, D, P7>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel,
P5: ColorPixel + RenderablePixel,
P6: ColorPixel + RenderablePixel,
P7: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Slot<C, L, D, P7>>>>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, Chain(e, Chain(f, Chain(g, h))))))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Slot<C, L, D, P7>>>>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e, f, g, h)
}
}
impl<C, L, D, P0, P1, P2, P3, P4, P5, P6, P7, P8> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>, Slot<C, L, D, P5>, Slot<C, L, D, P6>, Slot<C, L, D, P7>, Slot<C, L, D, P8>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel,
P5: ColorPixel + RenderablePixel,
P6: ColorPixel + RenderablePixel,
P7: ColorPixel + RenderablePixel,
P8: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Chain<Slot<C, L, D, P7>, Slot<C, L, D, P8>>>>>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, Chain(e, Chain(f, Chain(g, Chain(h, i)))))))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Chain<Slot<C, L, D, P7>, Slot<C, L, D, P8>>>>>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e, f, g, h, i)
}
}
impl<C, L, D, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9> ColorSlot<C, L, D> for (Slot<C, L, D, P0>, Slot<C, L, D, P1>, Slot<C, L, D, P2>, Slot<C, L, D, P3>, Slot<C, L, D, P4>, Slot<C, L, D, P5>, Slot<C, L, D, P6>, Slot<C, L, D, P7>, Slot<C, L, D, P8>, Slot<C, L, D, P9>)
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P0: ColorPixel + RenderablePixel,
P1: ColorPixel + RenderablePixel,
P2: ColorPixel + RenderablePixel,
P3: ColorPixel + RenderablePixel,
P4: ColorPixel + RenderablePixel,
P5: ColorPixel + RenderablePixel,
P6: ColorPixel + RenderablePixel,
P7: ColorPixel + RenderablePixel,
P8: ColorPixel + RenderablePixel,
P9: ColorPixel + RenderablePixel {
fn color_formats() -> Vec<PixelFormat> {
Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Chain<Slot<C, L, D, P7>, Chain<Slot<C, L, D, P8>, Slot<C, L, D, P9>>>>>>>>>>::color_formats()
}
fn reify_textures(size: D::Size, mipmaps: usize, textures: &mut Vec<C::ATexture>) -> Self {
let Chain(a, Chain(b, Chain(c, Chain(d, Chain(e, Chain(f, Chain(g, Chain(h, Chain(i, j))))))))) = Chain::<Slot<C, L, D, P0>, Chain<Slot<C, L, D, P1>, Chain<Slot<C, L, D, P2>, Chain<Slot<C, L, D, P3>, Chain<Slot<C, L, D, P4>, Chain<Slot<C, L, D, P5>, Chain<Slot<C, L, D, P6>, Chain<Slot<C, L, D, P7>, Chain<Slot<C, L, D, P8>, Slot<C, L, D, P9>>>>>>>>>>::reify_textures(size, mipmaps, textures);
(a, b, c, d, e, f, g, h, i, j)
}
}
pub trait DepthSlot<C, L, D> where C: HasFramebuffer + HasTexture, L: Layerable, D: Dimensionable, D::Size: Copy {
fn depth_format() -> Option<PixelFormat>;
fn reify_texture(size: D::Size, mipmaps: usize, texture: Option<C::ATexture>) -> Self; }
impl<C, L, D> DepthSlot<C, L, D> for () where C: HasFramebuffer + HasTexture, L: Layerable, D: Dimensionable, D::Size: Copy {
fn depth_format() -> Option<PixelFormat> { None }
fn reify_texture(_: D::Size, _: usize, _: Option<C::ATexture>) -> Self { () }
}
impl<C, L, D, P> DepthSlot<C, L, D> for Slot<C, L, D, P>
where C: HasFramebuffer + HasTexture,
L: Layerable,
D: Dimensionable,
D::Size: Copy,
P: DepthPixel {
fn depth_format() -> Option<PixelFormat> { Some(P::pixel_format()) }
fn reify_texture(size: D::Size, mipmaps: usize, texture: Option<C::ATexture>) -> Self {
Slot {
texture: Texture::from_raw(texture.unwrap(), size, mipmaps)
}
}
}