summaryrefslogtreecommitdiffstats
path: root/glow/src/program.rs
diff options
context:
space:
mode:
Diffstat (limited to 'glow/src/program.rs')
-rw-r--r--glow/src/program.rs127
1 files changed, 108 insertions, 19 deletions
diff --git a/glow/src/program.rs b/glow/src/program.rs
index 13676c70..9a02d578 100644
--- a/glow/src/program.rs
+++ b/glow/src/program.rs
@@ -1,29 +1,118 @@
use glow::HasContext;
-pub unsafe fn create(
- gl: &glow::Context,
- shader_sources: &[(u32, &str)],
- attributes: &[(u32, &str)],
-) -> <glow::Context as HasContext>::Program {
- let program = gl.create_program().expect("Cannot create program");
+/// The [`Version`] of a `Program`.
+pub struct Version {
+ vertex: String,
+ fragment: String,
+}
+
+impl Version {
+ pub fn new(gl: &glow::Context) -> Version {
+ let version = gl.version();
- let mut shaders = Vec::with_capacity(shader_sources.len());
+ let (vertex, fragment) = match (
+ version.major,
+ version.minor,
+ version.is_embedded,
+ ) {
+ // OpenGL 3.0+
+ (3, 0 | 1 | 2, false) => (
+ format!("#version 1{}0", version.minor + 3),
+ format!(
+ "#version 1{}0\n#define HIGHER_THAN_300 1",
+ version.minor + 3
+ ),
+ ),
+ // OpenGL 3.3+
+ (3 | 4, _, false) => (
+ format!("#version {}{}0", version.major, version.minor),
+ format!(
+ "#version {}{}0\n#define HIGHER_THAN_300 1",
+ version.major, version.minor
+ ),
+ ),
+ // OpenGL ES 3.0+
+ (3, _, true) => (
+ format!("#version 3{}0 es", version.minor),
+ format!(
+ "#version 3{}0 es\n#define HIGHER_THAN_300 1",
+ version.minor
+ ),
+ ),
+ // OpenGL ES 2.0+
+ (2, _, true) => (
+ String::from(
+ "#version 100\n#define in attribute\n#define out varying",
+ ),
+ String::from("#version 100\n#define in varying"),
+ ),
+ // OpenGL 2.1
+ (2, _, false) => (
+ String::from(
+ "#version 120\n#define in attribute\n#define out varying",
+ ),
+ String::from("#version 120\n#define in varying"),
+ ),
+ // OpenGL 1.1+
+ _ => panic!("Incompatible context version: {:?}", version),
+ };
- for (shader_type, shader_source) in shader_sources.iter() {
- let shader = gl
- .create_shader(*shader_type)
- .expect("Cannot create shader");
+ log::info!("Shader directive: {}", vertex.lines().next().unwrap());
- gl.shader_source(shader, shader_source);
- gl.compile_shader(shader);
+ Version { vertex, fragment }
+ }
+}
+
+pub struct Shader(<glow::Context as HasContext>::Shader);
+
+impl Shader {
+ fn compile(gl: &glow::Context, stage: u32, content: &str) -> Shader {
+ unsafe {
+ let shader = gl.create_shader(stage).expect("Cannot create shader");
- if !gl.get_shader_compile_status(shader) {
- panic!("{}", gl.get_shader_info_log(shader));
+ gl.shader_source(shader, &content);
+ gl.compile_shader(shader);
+
+ if !gl.get_shader_compile_status(shader) {
+ panic!("{}", gl.get_shader_info_log(shader));
+ }
+
+ Shader(shader)
}
+ }
- gl.attach_shader(program, shader);
+ /// Creates a vertex [`Shader`].
+ pub fn vertex(
+ gl: &glow::Context,
+ version: &Version,
+ content: &'static str,
+ ) -> Self {
+ let content = format!("{}\n{}", version.vertex, content);
- shaders.push(shader);
+ Shader::compile(gl, glow::VERTEX_SHADER, &content)
+ }
+
+ /// Creates a fragment [`Shader`].
+ pub fn fragment(
+ gl: &glow::Context,
+ version: &Version,
+ content: &'static str,
+ ) -> Self {
+ let content = format!("{}\n{}", version.fragment, content);
+
+ Shader::compile(gl, glow::FRAGMENT_SHADER, &content)
+ }
+}
+
+pub unsafe fn create(
+ gl: &glow::Context,
+ shaders: &[Shader],
+ attributes: &[(u32, &str)],
+) -> <glow::Context as HasContext>::Program {
+ let program = gl.create_program().expect("Cannot create program");
+
+ for shader in shaders {
+ gl.attach_shader(program, shader.0);
}
for (i, name) in attributes {
@@ -36,8 +125,8 @@ pub unsafe fn create(
}
for shader in shaders {
- gl.detach_shader(program, shader);
- gl.delete_shader(shader);
+ gl.detach_shader(program, shader.0);
+ gl.delete_shader(shader.0);
}
program