1 //! Models versions of OpenGL Shader Language (GLSL)
2 
3 use { OpenGL, PickShader, Shaders };
4 use std::str::FromStr;
5 use std::fmt;
6 use std::error::Error;
7 
8 /// For OpenGL version 3.3 and above,
9 /// the GLSL version is the same as the OpenGL version.
10 ///
11 /// Source: http://www.opengl.org/wiki/Core_Language_%28GLSL%29
12 #[allow(missing_docs)]
13 #[allow(non_camel_case_types)]
14 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
15 pub enum GLSL {
16     V1_10,
17     V1_20,
18     V1_30,
19     V1_40,
20     V1_50,
21     V3_30,
22     V4_00,
23     V4_10,
24     V4_20,
25     V4_30,
26     V4_40,
27     V4_50
28 }
29 
30 impl GLSL {
31     /// Gets OpenGL version associated with GLSL.
32     #[allow(non_snake_case)]
to_opengl(&self) -> OpenGL33     pub fn to_opengl(&self) -> OpenGL {
34         match *self {
35             GLSL::V1_10 => OpenGL::V2_0,
36             GLSL::V1_20 => OpenGL::V2_1,
37             GLSL::V1_30 => OpenGL::V3_0,
38             GLSL::V1_40 => OpenGL::V3_1,
39             GLSL::V1_50 => OpenGL::V3_2,
40             GLSL::V3_30 => OpenGL::V3_3,
41             GLSL::V4_00 => OpenGL::V4_0,
42             GLSL::V4_10 => OpenGL::V4_1,
43             GLSL::V4_20 => OpenGL::V4_2,
44             GLSL::V4_30 => OpenGL::V4_3,
45             GLSL::V4_40 => OpenGL::V4_4,
46             GLSL::V4_50 => OpenGL::V4_5
47         }
48     }
49 }
50 
51 impl PickShader for GLSL {
pick_shader<'a, S: ?Sized>(self, shaders: &Shaders<'a, Self, S>) -> Option<&'a S>52     fn pick_shader<'a, S: ?Sized>(self, shaders: &Shaders<'a, Self, S>) -> Option<&'a S> {
53         // OpenGL since 3.2 in core profile doesn't support GLSL lower than 1.50.
54         // Since there are no compatible shader in this case, it will return `None`.
55         let low = if self < GLSL::V1_50 {
56             GLSL::V1_10
57         } else {
58             GLSL::V1_50
59         };
60         shaders.0.iter()
61                .skip_while(|&(v, _)| *v < low)
62                .take_while(|&(v, _)| *v <= self)
63                .last().map(|(_, &s)| s)
64     }
65 }
66 
67 
68 impl FromStr for GLSL {
69     type Err = ParseGLSLError;
70 
from_str(s: &str) -> Result<Self, Self::Err>71     fn from_str(s: &str) -> Result<Self, Self::Err> {
72         match s {
73             "1.10" => Ok(GLSL::V1_10),
74             "1.20" => Ok(GLSL::V1_20),
75             "1.30" => Ok(GLSL::V1_30),
76             "1.40" => Ok(GLSL::V1_40),
77             "1.50" => Ok(GLSL::V1_50),
78             "3.30" => Ok(GLSL::V3_30),
79             "4.00" => Ok(GLSL::V4_00),
80             "4.10" => Ok(GLSL::V4_10),
81             "4.20" => Ok(GLSL::V4_20),
82             "4.30" => Ok(GLSL::V4_30),
83             "4.40" => Ok(GLSL::V4_40),
84             "4.50" => Ok(GLSL::V4_50),
85             error => Err(ParseGLSLError{input: error.into()}),
86         }
87     }
88 }
89 
90 
91 /// Represents an error while trying to get `GLSL` from `&str`.
92 #[derive(Debug)]
93 pub struct ParseGLSLError{
94     input: String
95 }
96 
97 impl fmt::Display for ParseGLSLError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result98     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99         write!(f, "`{}` is not a valid GLSL version", self.input)
100     }
101 }
102 
103 impl Error for ParseGLSLError {
description(&self) -> &str104     fn description(&self) -> &str {
105         "Invalid GLSL version"
106     }
107 }
108