#![cfg(not(feature = "test_headless"))]
#[macro_use]
extern crate glium;
use glium::{Surface};
use glium::index::PrimitiveType;
use glium::program::{ ShaderStage, is_subroutine_supported };
use glium::backend::Facade;
use glium::DrawError;
mod support;
#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
}
implement_vertex!(Vertex, position);
#[test]
fn subroutine_bindings_simple() {
let display = support::build_display();
if !is_subroutine_supported(display.get_context()) {
println!("Backend does not support subroutines");
return
};
let program = program!(&display,
150 => {
vertex: "
#version 150
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
",
fragment: "
#version 150
#extension GL_ARB_shader_subroutine : require
out vec4 fragColor;
subroutine vec4 color_t();
subroutine uniform color_t Color;
subroutine(color_t)
vec4 ColorRed()
{
return vec4(1, 0, 0, 1);
}
subroutine(color_t)
vec4 ColorBlue()
{
return vec4(0, 0, 1, 1);
}
void main()
{
fragColor = Color();
}
"
},
).unwrap();
let vb = glium::VertexBuffer::new(&display, &[
Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] },
Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
]).unwrap();
let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
&[0u16, 1, 2, 2, 1, 3]).unwrap();
let texture = support::build_renderable_texture(&display);
let uniforms = uniform!(
Color: ("ColorBlue", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (0, 0, 255, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));
display.assert_no_error(None);
let uniforms = uniform!(
Color: ("ColorRed", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (255, 0, 0, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));
display.assert_no_error(None);
}
#[test]
fn subroutine_bindings_explicit_location() {
let display = support::build_display();
if !is_subroutine_supported(display.get_context()) {
println!("Backend does not support subroutines");
return
};
let program = program!(&display,
150 => {
vertex: "
#version 150
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
",
fragment: "
#version 150
#extension GL_ARB_shader_subroutine : require
#extension GL_ARB_explicit_uniform_location : require
#extension GL_ARB_explicit_attrib_location : require
out vec4 fragColor;
subroutine vec4 color_t();
layout(location = 5) subroutine uniform color_t Color;
subroutine(color_t)
vec4 ColorRed()
{
return vec4(1, 0, 0, 1);
}
subroutine(color_t)
vec4 ColorBlue()
{
return vec4(0, 0, 1, 1);
}
void main()
{
fragColor = Color();
}
"
},
).unwrap();
let vb = glium::VertexBuffer::new(&display, &[
Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] },
Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
]).unwrap();
let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
&[0u16, 1, 2, 2, 1, 3]).unwrap();
let texture = support::build_renderable_texture(&display);
let uniforms = uniform!(
Color: ("ColorBlue", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (0, 0, 255, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));
display.assert_no_error(None);
let uniforms = uniform!(
Color: ("ColorRed", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (255, 0, 0, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(255, 0, 0, 255));
display.assert_no_error(None);
}
fn build_program_complex(display: &glium::Display) -> glium::Program {
let program = program!(display,
150 => {
vertex: "
#version 150
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
",
fragment: "
#version 150
#extension GL_ARB_shader_subroutine : require
out vec4 fragColor;
subroutine vec4 color_t();
subroutine vec4 modify_t(vec4 color);
subroutine uniform color_t Color;
subroutine uniform modify_t Modify;
subroutine(color_t)
vec4 ColorRed()
{
return vec4(1, 0, 0, 1);
}
subroutine(color_t)
vec4 ColorBlue()
{
return vec4(0, 0, 1, 1);
}
subroutine(modify_t)
vec4 SwapRB(vec4 color)
{
return vec4(color.b, color.g, color.r, color.a);
}
subroutine(modify_t)
vec4 DeleteR(vec4 color)
{
return vec4(0, color.g, color.b, color.a);
}
void main()
{
vec4 color = Color();
fragColor = Modify(color);
}
"
},
).unwrap();
program
}
#[test]
fn subroutine_bindings_multi() {
let display = support::build_display();
if !is_subroutine_supported(display.get_context()) {
println!("Backend does not support subroutines");
return
};
let program = build_program_complex(&display);
let vb = glium::VertexBuffer::new(&display, &[
Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] },
Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
]).unwrap();
let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
&[0u16, 1, 2, 2, 1, 3]).unwrap();
let texture = support::build_renderable_texture(&display);
let uniforms = uniform!(
Color: ("ColorBlue", ShaderStage::Fragment),
Modify: ("DeleteR", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (0, 0, 255, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));
display.assert_no_error(None);
let uniforms = uniform!(
Color: ("ColorRed", ShaderStage::Fragment),
Modify: ("SwapRB", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()).unwrap();
let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
assert_eq!(data[0][0], (0, 0, 255, 255));
assert_eq!(data.last().unwrap().last().unwrap(), &(0, 0, 255, 255));
display.assert_no_error(None);
}
#[test]
fn not_all_subroutine_uniforms_set() {
let display = support::build_display();
if !is_subroutine_supported(display.get_context()) {
println!("Backend does not support subroutines");
return
};
let program = build_program_complex(&display);
let vb = glium::VertexBuffer::new(&display, &[
Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] },
Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
]).unwrap();
let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
&[0u16, 1, 2, 2, 1, 3]).unwrap();
let texture = support::build_renderable_texture(&display);
let uniforms = uniform!(
Color: ("ColorBlue", ShaderStage::Fragment),
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()) {
Err(DrawError::SubroutineUniformMissing{ .. }) => (),
_ => panic!("Drawing should have errored")
}
display.assert_no_error(None);
}
#[test]
fn mismatched_subroutines() {
let display = support::build_display();
if !is_subroutine_supported(display.get_context()) {
println!("Backend does not support subroutines");
return
};
let program = build_program_complex(&display);
let vb = glium::VertexBuffer::new(&display, &[
Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] },
Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] },
]).unwrap();
let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList,
&[0u16, 1, 2, 2, 1, 3]).unwrap();
let texture = support::build_renderable_texture(&display);
let uniforms = uniform!(
Color: ("ColorBlue", ShaderStage::Fragment),
Modify: ("ColorBlue", ShaderStage::Fragment)
);
texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
match texture.as_surface().draw(&vb, &indices, &program, &uniforms,
&Default::default()) {
Err(DrawError::SubroutineNotFound{ .. }) => (),
_ => panic!("Drawing should have errored")
}
display.assert_no_error(None);
}