use gl::types::{GLboolean, GLchar, GLenum, GLfloat, GLint, GLsizeiptr, GLuint};
use safex::glx::*;
use safex::xlib::*;
use std::ffi::{c_void, CString};
use std::{mem, ptr};
static VERTEX_DATA: [GLfloat; 6] = [0.0, 0.5, 0.5, -0.5, -0.5, -0.5];
static VS_SRC: &'static str = "
#version 140
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}";
static FS_SRC: &'static str = "
#version 140
out vec4 out_color;
void main() {
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}";
fn compile_shader(src: &str, ty: GLenum) -> GLuint {
let shader;
unsafe {
shader = gl::CreateShader(ty);
let c_str = CString::new(src.as_bytes()).unwrap();
gl::ShaderSource(shader, 1, &c_str.as_ptr(), ptr::null());
gl::CompileShader(shader);
let mut status = gl::FALSE as GLint;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
if status != (gl::TRUE as GLint) {
let mut len = 0;
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::with_capacity(len as usize);
buf.set_len((len as usize) - 1); gl::GetShaderInfoLog(
shader,
len,
ptr::null_mut(),
buf.as_mut_ptr() as *mut GLchar,
);
panic!(
"{}",
std::str::from_utf8(&buf)
.ok()
.expect("ShaderInfoLog not valid utf8")
);
}
}
shader
}
fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
unsafe {
let program = gl::CreateProgram();
gl::AttachShader(program, vs);
gl::AttachShader(program, fs);
gl::LinkProgram(program);
let mut status = gl::FALSE as GLint;
gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
if status != (gl::TRUE as GLint) {
let mut len: GLint = 0;
gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::with_capacity(len as usize);
buf.set_len((len as usize) - 1); gl::GetProgramInfoLog(
program,
len,
ptr::null_mut(),
buf.as_mut_ptr() as *mut GLchar,
);
panic!(
"{}",
std::str::from_utf8(&buf)
.ok()
.expect("ProgramInfoLog not valid utf8")
);
}
program
}
}
fn main() {
let display = Display::open(None);
let screen = Screen::default(&display);
let vi = glx_choose_visual(
&display,
&mut [GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, GLX_NONE],
)
.unwrap();
let window =
Window::new_with_glx(&display, &screen, &vi, None, 0, 0, 200, 200, 1, 0, 0, &vi).unwrap();
let glc = GLXContext::create(&display, &vi, None, gl::TRUE as i32);
glx_make_current(&display, &window, &glc);
gl::load_with(|string| glc.get_proc_address(string).unwrap() as *mut c_void);
let vs = compile_shader(VS_SRC, gl::VERTEX_SHADER);
let fs = compile_shader(FS_SRC, gl::FRAGMENT_SHADER);
let program = link_program(vs, fs);
let mut vao = 0;
let mut vbo = 0;
unsafe {
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
gl::GenBuffers(1, &mut vbo);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
gl::BufferData(
gl::ARRAY_BUFFER,
(VERTEX_DATA.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
mem::transmute(&VERTEX_DATA[0]),
gl::STATIC_DRAW,
);
gl::UseProgram(program);
gl::BindFragDataLocation(program, 0, CString::new("out_color").unwrap().as_ptr());
let pos_attr = gl::GetAttribLocation(program, CString::new("position").unwrap().as_ptr());
gl::EnableVertexAttribArray(pos_attr as GLuint);
gl::VertexAttribPointer(
pos_attr as GLuint,
2,
gl::FLOAT,
gl::FALSE as GLboolean,
0,
ptr::null(),
);
}
window.map(&display);
window.run(|event, control_flow| match event {
WindowEvent::Expose => {
unsafe {
gl::Viewport(0, 0, 100, 100);
gl::ClearColor(0.3, 0.3, 0.3, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::DrawArrays(gl::TRIANGLES, 0, 3);
}
window.glx_swap_buffers();
}
})
}