1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use gl;
use graphics::draw_state::*;

pub fn bind_state(old_state: &DrawState, new_state: &DrawState) {
    if old_state.scissor != new_state.scissor {
        bind_scissor(new_state.scissor);
    }
    if old_state.stencil != new_state.stencil {
        bind_stencil(new_state.stencil);
    }
    if old_state.blend != new_state.blend {
        bind_blend(new_state.blend);
    }
}

pub fn bind_scissor(rect: Option<[u32; 4]>) {
    match rect {
        Some(r) => unsafe {
            gl::Enable(gl::SCISSOR_TEST);
            gl::Scissor(r[0] as gl::types::GLint,
                        r[1] as gl::types::GLint,
                        r[2] as gl::types::GLint,
                        r[3] as gl::types::GLint);
        },
        None => unsafe { gl::Disable(gl::SCISSOR_TEST) },
    }
}

pub fn bind_stencil(stencil: Option<Stencil>) {
    unsafe {
        match stencil {
            Some(s) => {
                gl::Enable(gl::STENCIL_TEST);
                match s {
                    Stencil::Clip(val) => {
                        gl::StencilFunc(gl::NEVER, val as gl::types::GLint, 255);
                        gl::StencilMask(255);
                        gl::StencilOp(gl::REPLACE, gl::KEEP, gl::KEEP);
                    }
                    Stencil::Inside(val) => {
                        gl::StencilFunc(gl::EQUAL, val as gl::types::GLint, 255);
                        gl::StencilMask(255);
                        gl::StencilOp(gl::KEEP, gl::KEEP, gl::KEEP);
                    }
                    Stencil::Outside(val) => {
                        gl::StencilFunc(gl::NOTEQUAL, val as gl::types::GLint, 255);
                        gl::StencilMask(255);
                        gl::StencilOp(gl::KEEP, gl::KEEP, gl::KEEP);
                    }
                }
            }
            None => gl::Disable(gl::STENCIL_TEST),
        }
    }
}

/*
fn map_equation(eq: Equation) -> gl::types::GLenum {
    match eq {
        Equation::Add    => gl::FUNC_ADD,
        Equation::Sub    => gl::FUNC_SUBTRACT,
        Equation::RevSub => gl::FUNC_REVERSE_SUBTRACT,
        Equation::Min    => gl::MIN,
        Equation::Max    => gl::MAX,
    }
}

fn map_factor(factor: Factor) -> gl::types::GLenum {
    match factor {
        Factor::Zero                              => gl::ZERO,
        Factor::One                               => gl::ONE,
        Factor::ZeroPlus(BlendValue::SourceColor) => gl::SRC_COLOR,
        Factor::OneMinus(BlendValue::SourceColor) => gl::ONE_MINUS_SRC_COLOR,
        Factor::ZeroPlus(BlendValue::SourceAlpha) => gl::SRC_ALPHA,
        Factor::OneMinus(BlendValue::SourceAlpha) => gl::ONE_MINUS_SRC_ALPHA,
        Factor::ZeroPlus(BlendValue::DestColor)   => gl::DST_COLOR,
        Factor::OneMinus(BlendValue::DestColor)   => gl::ONE_MINUS_DST_COLOR,
        Factor::ZeroPlus(BlendValue::DestAlpha)   => gl::DST_ALPHA,
        Factor::OneMinus(BlendValue::DestAlpha)   => gl::ONE_MINUS_DST_ALPHA,
        Factor::ZeroPlus(BlendValue::ConstColor)  => gl::CONSTANT_COLOR,
        Factor::OneMinus(BlendValue::ConstColor)  => gl::ONE_MINUS_CONSTANT_COLOR,
        Factor::ZeroPlus(BlendValue::ConstAlpha)  => gl::CONSTANT_ALPHA,
        Factor::OneMinus(BlendValue::ConstAlpha)  => gl::ONE_MINUS_CONSTANT_ALPHA,
        Factor::SourceAlphaSaturated => gl::SRC_ALPHA_SATURATE,
    }
}
*/

pub fn bind_blend(blend: Option<Blend>) {
    unsafe {
        match blend {
            Some(b) => {
                gl::Enable(gl::BLEND);
                gl::BlendColor(1.0, 1.0, 1.0, 1.0);
                match b {
                    Blend::Alpha => {
                        gl::BlendEquationSeparate(gl::FUNC_ADD, gl::FUNC_ADD);
                        gl::BlendFuncSeparate(gl::SRC_ALPHA,
                                              gl::ONE_MINUS_SRC_ALPHA,
                                              gl::ONE,
                                              gl::ONE);
                    }
                    Blend::Add => {
                        gl::BlendEquationSeparate(gl::FUNC_ADD, gl::FUNC_ADD);
                        gl::BlendFuncSeparate(gl::ONE, gl::ONE, gl::ONE, gl::ONE);
                    }
                    Blend::Multiply => {
                        gl::BlendEquationSeparate(gl::FUNC_ADD, gl::FUNC_ADD);
                        gl::BlendFuncSeparate(gl::DST_COLOR, gl::ZERO, gl::DST_ALPHA, gl::ZERO);
                    }
                    Blend::Invert => {
                        gl::BlendEquationSeparate(gl::FUNC_SUBTRACT, gl::FUNC_ADD);
                        gl::BlendFuncSeparate(gl::CONSTANT_COLOR, gl::SRC_COLOR, gl::ZERO, gl::ONE);
                    }
                }
            }
            None => gl::Disable(gl::BLEND),
        }
    }
}