6718096000759bfc790f979b9520f0b9ba27d249
[rust_hw] / src / main.rs
1 extern crate sdl2;
2 extern crate gl;
3
4 use sdl2::video::GLProfile;
5 use gl::types::*;
6
7 use std;
8
9 /*enum Vattr {
10         VATTR_VERTEX,
11         VATTR_TEXCOORD
12 }*/
13
14 static WIN_W : u32 = 800;
15 static WIN_H : u32 = 600;
16
17 static VERTEX_DATA : [GLfloat; 12] = [
18         -0.5, -0.5,
19         0.5, -0.5,
20         0.5, 0.5,
21
22         -0.5, -0.5,
23         0.5, 0.5,
24         -0.5, 0.5
25 ];
26
27 static NUM_VERTICES : GLint = 6;
28 static VERTEX_LOC : u32 = 0;
29
30 let tex : u32 = 0;
31
32 static VS : &'static str =
33 "#version 130\n\
34  attribute vec4 pos;\n\
35  void main() {\n\
36     gl_Position = pos;\n\
37  }";
38
39 static FS : &'static str =
40 "#version 130\n\
41  out vec4 color;\n\
42  void main() {\n\
43     color = vec4(0.0, 0.5, 0.8, 1.0);\n\
44  }";
45
46 fn compile_sdr(src: &str, stage:GLenum) -> GLuint {
47     let shader;
48     unsafe {
49         shader = gl::CreateShader(stage);
50
51         let s = std::ffi::CString::new(src).expect("CString::new failed");;
52
53         gl::ShaderSource(shader, 1, &s.as_ptr(), std::ptr::null());
54         gl::CompileShader(shader);
55         // status
56         let mut status = gl::FALSE as GLint;
57         gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
58
59         // error handling
60         if status != (gl::TRUE as GLint) {
61             let mut len = 0;
62             gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
63
64             let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
65             buf.extend([b' '].iter().cycle().take(len as usize));
66             let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
67
68             gl::GetShaderInfoLog(shader, len, std::ptr::null_mut(),
69                                 err.as_ptr() as *mut GLchar);
70             println!("{}", err.to_str().unwrap());
71
72         }
73     }
74     shader
75 }
76
77 fn link_sdr_prog(vs: GLuint, fs: GLuint) -> GLuint {
78     unsafe {
79         let sdr_prog = gl::CreateProgram();
80         gl::AttachShader(sdr_prog, vs);
81         gl::AttachShader(sdr_prog, fs);
82         gl::LinkProgram(sdr_prog);
83
84         let mut status = gl::FALSE as GLint;
85         gl::GetProgramiv(sdr_prog, gl::LINK_STATUS, &mut status);
86         if status != (gl::TRUE as GLint) {
87             let mut len: GLint = 0;
88             gl::GetProgramiv(sdr_prog, gl::INFO_LOG_LENGTH, &mut len);
89
90
91             let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
92             buf.extend([b' '].iter().cycle().take(len as usize));
93             let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
94
95             gl::GetProgramInfoLog(sdr_prog, len, std::ptr::null_mut(), err.as_ptr() as *mut GLchar);
96             println!("{}", err.to_str().unwrap());
97         }
98         sdr_prog
99     }
100 }
101
102 fn main() {
103     let sdl_ctx = sdl2::init().unwrap();
104     let vid_sys = sdl_ctx.video().unwrap();
105     let gl_attr = vid_sys.gl_attr();
106
107     gl_attr.set_context_profile(GLProfile::Core);
108
109     let win = vid_sys
110         .window("foobar", WIN_W, WIN_H)
111         .opengl() // add opengl flag
112         .resizable()
113         .build()
114         .unwrap();
115
116     let _gl_ctx = win.gl_create_context().unwrap();
117     let _gl = gl::load_with(|s| vid_sys.gl_get_proc_address(s) as
118                             *const std::os::raw::c_void);
119
120     let mut vao = 0;
121     let mut vbo = 0;
122
123     let mut sprog;
124     let fs;
125     let vs;
126
127     unsafe {
128         gl::ClearColor(0.3, 0.1, 0.1, 1.0);
129         gl::GenVertexArrays(1, &mut vao);
130         gl::BindVertexArray(vao);
131
132         gl::GenBuffers(1, &mut vbo);
133         gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
134         gl::BufferData(gl::ARRAY_BUFFER, (VERTEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
135                        std::mem::transmute(&VERTEX_DATA[0]),
136                        gl::STATIC_DRAW);
137         gl::BindBuffer(gl::ARRAY_BUFFER, 0);
138
139         vs = compile_sdr(VS, gl::VERTEX_SHADER);
140         fs = compile_sdr(FS, gl::FRAGMENT_SHADER);
141
142         sprog = link_sdr_prog(vs, fs);
143         let att_str = std::ffi::CString::new("position").unwrap();
144
145         gl::BindAttribLocation(sprog, VERTEX_LOC, att_str.as_ptr());
146         sprog = link_sdr_prog(vs, fs);
147
148         gl::UseProgram(sprog);
149     }
150
151     let mut event_pump = sdl_ctx.event_pump().unwrap();
152     'main: loop {
153         for event in event_pump.poll_iter() {
154             // handle user input here
155             match event {
156                 sdl2::event::Event::Quit {..} |
157                 sdl2::event::Event::KeyDown {keycode:
158                     Some(sdl2::keyboard::Keycode::Escape), ..} =>
159                         break 'main,
160                 _ => {},
161             }
162         }
163
164         unsafe {
165             gl::Clear(gl::COLOR_BUFFER_BIT);
166             gl::Viewport(0, 0, WIN_W as i32, WIN_H as i32);
167
168             gl::EnableVertexAttribArray(VERTEX_LOC);
169             gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
170             gl::VertexAttribPointer(VERTEX_LOC, 2,
171                                     gl::FLOAT, gl::FALSE,
172                                     0 as i32, std::ptr::null());
173
174             gl::DrawArrays(gl::TRIANGLES, 0, NUM_VERTICES);
175         }
176
177         win.gl_swap_window();
178     }
179
180     unsafe {
181         gl::DeleteProgram(sprog);
182         gl::DeleteShader(vs);
183         gl::DeleteShader(fs);
184         gl::DeleteBuffers(1, &vbo);
185         gl::DeleteVertexArrays(1, &vao);
186     }
187 }