5 use sdl2::video::GLProfile;
7 use image::GenericImageView;
9 static WIN_W : u32 = 800;
10 static WIN_H : u32 = 800;
12 static VERTEX_DATA : [GLfloat; 12] = [
22 static TEX_DATA : [GLfloat; 12] = [
32 static NUM_VERTICES : GLint = 6;
33 static VERTEX_LOC : u32 = 0;
34 static TEX_LOC : u32 = 1;
36 static VS : &'static str =
39 in vec2 in_tex_coord;\n\
40 out vec2 tex_coord;\n\
43 tex_coord = in_tex_coord;\n\
46 static FS : &'static str =
48 uniform sampler2D tex;\n\
52 color = texture2D(tex, tex_coord);\n\
55 fn compile_sdr(src: &str, stage:GLenum) -> GLuint {
58 shader = gl::CreateShader(stage);
60 let s = std::ffi::CString::new(src).expect("CString::new failed");;
62 gl::ShaderSource(shader, 1, &s.as_ptr(), std::ptr::null());
63 gl::CompileShader(shader);
65 let mut status = gl::FALSE as GLint;
66 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
69 if status != (gl::TRUE as GLint) {
71 gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
73 let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
74 buf.extend([b' '].iter().cycle().take(len as usize));
75 let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
77 gl::GetShaderInfoLog(shader, len, std::ptr::null_mut(),
78 err.as_ptr() as *mut GLchar);
79 println!("{}", err.to_str().unwrap());
86 fn link_sdr_prog(vs: GLuint, fs: GLuint) -> GLuint {
88 let sdr_prog = gl::CreateProgram();
89 gl::AttachShader(sdr_prog, vs);
90 gl::AttachShader(sdr_prog, fs);
91 gl::LinkProgram(sdr_prog);
93 let mut status = gl::FALSE as GLint;
94 gl::GetProgramiv(sdr_prog, gl::LINK_STATUS, &mut status);
95 if status != (gl::TRUE as GLint) {
96 let mut len: GLint = 0;
97 gl::GetProgramiv(sdr_prog, gl::INFO_LOG_LENGTH, &mut len);
100 let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
101 buf.extend([b' '].iter().cycle().take(len as usize));
102 let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
104 gl::GetProgramInfoLog(sdr_prog, len, std::ptr::null_mut(), err.as_ptr() as *mut GLchar);
105 println!("{}", err.to_str().unwrap());
111 fn gen_tex(fname : String, _id : &mut GLuint) {
112 let img : image::DynamicImage = image::open(&std::path::Path::new(&fname)).ok().expect("Can't open image.\n");
113 let (_w, _h) = img.dimensions();
116 gl::GenTextures(1, _id);
117 gl::BindTexture(gl::TEXTURE_2D, *_id);
118 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
119 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
120 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
121 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
122 gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32,
123 _w as i32, _h as i32, 0,
124 gl::RGBA, gl::UNSIGNED_BYTE,
125 img.to_rgba().into_raw().as_ptr() as *const std::ffi::c_void);
126 gl::BindTexture(gl::TEXTURE_2D, 0);
132 let sdl_ctx = sdl2::init().unwrap();
133 let vid_sys = sdl_ctx.video().unwrap();
134 let gl_attr = vid_sys.gl_attr();
136 gl_attr.set_context_profile(GLProfile::Core);
139 .window("foobar", WIN_W, WIN_H)
140 .opengl() // add opengl flag
145 let _gl_ctx = win.gl_create_context().unwrap();
146 let _gl = gl::load_with(|s| vid_sys.gl_get_proc_address(s) as
147 *const std::os::raw::c_void);
157 let mut tex_igalia : GLuint = 1;
158 let mut tex_guadec : GLuint = 2;
159 let mut tex_sel = tex_igalia;
161 let mut uloc_stex : GLint = -1;
163 gen_tex("data/igalia.png".to_string(), &mut tex_igalia);
164 gen_tex("data/guadec.png".to_string(), &mut tex_guadec);
167 gl::ClearColor(0.0, 0.0, 0.0, 1.0);
168 gl::Enable(gl::BLEND);
169 gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
170 gl::GenVertexArrays(1, &mut vao);
171 gl::BindVertexArray(vao);
173 gl::GenBuffers(1, &mut vbo_pos);
174 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_pos);
175 gl::BufferData(gl::ARRAY_BUFFER, (VERTEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
176 std::mem::transmute(&VERTEX_DATA[0]),
178 gl::BindBuffer(gl::ARRAY_BUFFER, 0);
179 gl::GenBuffers(1, &mut vbo_tex);
180 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_tex);
181 gl::BufferData(gl::ARRAY_BUFFER, (TEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
182 std::mem::transmute(&TEX_DATA[0]),
184 gl::BindBuffer(gl::ARRAY_BUFFER, 0);
186 vs = compile_sdr(VS, gl::VERTEX_SHADER);
187 fs = compile_sdr(FS, gl::FRAGMENT_SHADER);
189 sprog = link_sdr_prog(vs, fs);
191 gl::UseProgram(sprog);
194 let mut event_pump = sdl_ctx.event_pump().unwrap();
196 for event in event_pump.poll_iter() {
197 // handle user input here
199 sdl2::event::Event::Quit {..} |
200 sdl2::event::Event::KeyDown {keycode:
201 Some(sdl2::keyboard::Keycode::Escape), ..} =>
203 sdl2::event::Event::KeyDown {keycode:
204 Some(sdl2::keyboard::Keycode::I), ..} =>
205 tex_sel = tex_igalia,
206 sdl2::event::Event::KeyDown {keycode:
207 Some(sdl2::keyboard::Keycode::G), ..} =>
208 tex_sel = tex_guadec,
213 //TODO FIXME: display
215 let uni_str = std::ffi::CString::new("tex").unwrap();
216 uloc_stex = gl::GetUniformLocation(sprog, uni_str.as_ptr());
218 gl::Uniform1i(uloc_stex, tex_sel as i32);
221 gl::Clear(gl::COLOR_BUFFER_BIT);
222 gl::Viewport(0, 0, WIN_W as i32, WIN_H as i32);
225 gl::EnableVertexAttribArray(VERTEX_LOC);
226 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_pos);
227 gl::VertexAttribPointer(VERTEX_LOC, 2,
228 gl::FLOAT, gl::FALSE,
229 0 as i32, std::ptr::null());
232 gl::EnableVertexAttribArray(TEX_LOC);
233 gl::BindBuffer(gl::ARRAY_BUFFER, vbo_tex);
234 gl::VertexAttribPointer(TEX_LOC, 2,
235 gl::FLOAT, gl::FALSE,
236 0 as i32, std::ptr::null());
238 gl::ActiveTexture(gl::TEXTURE0 + tex_sel);
239 gl::BindTexture(gl::TEXTURE_2D, tex_sel);
241 gl::DrawArrays(gl::TRIANGLES, 0, NUM_VERTICES);
244 win.gl_swap_window();
247 //TODO FIXME: cleanup
249 gl::DeleteProgram(sprog);
250 gl::DeleteShader(vs);
251 gl::DeleteShader(fs);
252 gl::DeleteBuffers(1, &vbo_pos);
253 gl::DeleteBuffers(1, &vbo_tex);
254 gl::DeleteVertexArrays(1, &vao);
255 gl::DeleteTextures(1, &tex_igalia);
256 gl::DeleteTextures(1, &tex_guadec);