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
use super::errors::*;

use std::path::Path;
use std::fs::File;
use std::io::prelude::*;

use raw::*;

#[derive(Debug)]
pub struct Shader {
    id: ShaderId,
    pub shader_type: ShaderType,
}

impl Shader {
    pub fn new<T: AsRef<str>>(shader_type: ShaderType, sources: &[T]) -> Result<Shader> {
        let id: ShaderId;

        unsafe {
            id = create_shader(shader_type);

            shader_source(id, sources);
            compile_shader(id);

            if !get_shader_compiled(id) {
                let shader_info_log =
                    get_shader_info_log(id).chain_err(|| "Could not retrieve shader compilation log")?;

                delete_shader(id);
                bail!(shader_info_log);
            }
        }

        Ok(Shader {
            id: id,
            shader_type: shader_type,
        })
    }

    pub fn from_files(shader_type: ShaderType, filepaths: &[&Path]) -> Result<Shader> {
        let mut sources: Vec<String> = Vec::new();

        for filepath in filepaths {
            let mut file = match File::open(&filepath) {
                Ok(file) => file,
                Err(e) => return Err(format!("Could not open shader file : {}", e).into()),
            };

            let mut source = String::new();
            match file.read_to_string(&mut source) {
                Ok(_) => {}
                Err(e) => return Err(format!("Could not read shader file! : {}", e).into()),
            };

            sources.push(source);
        }

        Shader::new(shader_type, sources.as_slice())
    }

    pub fn from_file(shader_type: ShaderType, filepath: &Path) -> Result<Shader> {
        let mut file = match File::open(&filepath) {
            Ok(file) => file,
            Err(e) => return Err(format!("Could not open shader file : {}", e).into()),
        };

        let mut source = String::new();
        match file.read_to_string(&mut source) {
            Ok(_) => {}
            Err(e) => return Err(format!("Could not read shader file! : {}", e).into()),
        };

        Shader::new(shader_type, &[source.as_str()])
    }

    pub fn get_id(&self) -> ShaderId {
        self.id
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            delete_shader(self.id);
        }
    }
}