48 width as i32, |
43 width as i32, |
49 height as i32, |
44 height as i32, |
50 0, |
45 0, |
51 format as u32, |
46 format as u32, |
52 ty, |
47 ty, |
53 data.as_ptr() as *const _ |
48 data.as_ptr() as *const _, |
54 ); |
49 ); |
55 |
50 |
56 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32); |
51 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32); |
57 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32); |
52 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32); |
58 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32); |
53 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32); |
59 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32); |
54 gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32); |
60 } |
55 } |
61 |
56 |
62 Texture2D { |
57 Texture2D { handle } |
63 handle |
|
64 } |
|
65 } |
58 } |
66 |
59 |
67 pub fn update(&self, region: Rect, data: &[u8], data_stride: u32, format: u32, ty: u32) { |
60 pub fn update(&self, region: Rect, data: &[u8], data_stride: u32, format: u32, ty: u32) { |
68 unsafe { |
61 unsafe { |
69 gl::BindTexture(gl::TEXTURE_2D, self.handle); |
62 gl::BindTexture(gl::TEXTURE_2D, self.handle); |
70 gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32); |
63 gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32); |
71 gl::TexSubImage2D( |
64 gl::TexSubImage2D( |
72 gl::TEXTURE_2D, |
65 gl::TEXTURE_2D, |
73 0, // texture level |
66 0, // texture level |
74 region.left(), // texture region |
67 region.left(), // texture region |
75 region.top(), |
68 region.top(), |
76 region.width() as i32 - 1, |
69 region.width() as i32 - 1, |
77 region.height() as i32 - 1, |
70 region.height() as i32 - 1, |
78 format, // data format |
71 format, // data format |
79 ty, // data type |
72 ty, // data type |
80 data.as_ptr() as *const _, // data ptr |
73 data.as_ptr() as *const _, // data ptr |
81 ); |
74 ); |
82 } |
75 } |
83 } |
76 } |
84 } |
77 } |
139 self.handle |
128 self.handle |
140 } |
129 } |
141 |
130 |
142 pub fn write_typed<T>(&self, data: &[T]) { |
131 pub fn write_typed<T>(&self, data: &[T]) { |
143 unsafe { |
132 unsafe { |
144 let data = slice::from_raw_parts( |
133 let data = |
145 data.as_ptr() as *const u8, |
134 slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::<T>()); |
146 data.len() * mem::size_of::<T>(), |
135 |
|
136 gl::BindBuffer(self.ty, self.handle); |
|
137 gl::BufferData( |
|
138 self.ty, |
|
139 data.len() as isize, |
|
140 data.as_ptr() as *const _ as *const _, |
|
141 self.usage, |
147 ); |
142 ); |
148 |
143 } |
|
144 } |
|
145 |
|
146 pub fn write(&self, data: &[u8]) { |
|
147 unsafe { |
149 gl::BindBuffer(self.ty, self.handle); |
148 gl::BindBuffer(self.ty, self.handle); |
150 gl::BufferData(self.ty, data.len() as isize, data.as_ptr() as *const _ as *const _, self.usage); |
149 gl::BufferData( |
151 } |
150 self.ty, |
152 } |
151 data.len() as isize, |
153 |
152 data.as_ptr() as *const _ as *const _, |
154 pub fn write(&self, data: &[u8]) { |
153 self.usage, |
155 unsafe { |
154 ); |
156 gl::BindBuffer(self.ty, self.handle); |
|
157 gl::BufferData(self.ty, data.len() as isize, data.as_ptr() as *const _ as *const _, self.usage); |
|
158 } |
155 } |
159 } |
156 } |
160 } |
157 } |
161 |
158 |
162 impl Drop for Buffer { |
159 impl Drop for Buffer { |
190 |
187 |
191 impl Shader { |
188 impl Shader { |
192 pub fn new<'a>( |
189 pub fn new<'a>( |
193 vs: &str, |
190 vs: &str, |
194 ps: Option<&str>, |
191 ps: Option<&str>, |
195 bindings: &[VariableBinding<'a>] |
192 bindings: &[VariableBinding<'a>], |
196 ) -> Result<Self, String> { |
193 ) -> Result<Self, String> { |
197 unsafe fn compile_shader(ty: u32, shdr: &str) -> Result<u32, String> { |
194 unsafe fn compile_shader(ty: u32, shdr: &str) -> Result<u32, String> { |
198 let shader = gl::CreateShader(ty); |
195 let shader = gl::CreateShader(ty); |
199 let len = shdr.len() as i32; |
196 let len = shdr.len() as i32; |
200 let shdr = shdr.as_ptr() as *const i8; |
197 let shdr = shdr.as_ptr() as *const i8; |
215 Err(String::from_utf8_unchecked(log)) |
212 Err(String::from_utf8_unchecked(log)) |
216 } else { |
213 } else { |
217 Ok(shader) |
214 Ok(shader) |
218 } |
215 } |
219 } |
216 } |
220 |
217 |
221 let vs = unsafe { compile_shader(gl::VERTEX_SHADER, vs)? }; |
218 let vs = unsafe { compile_shader(gl::VERTEX_SHADER, vs)? }; |
222 let ps = if let Some(ps) = ps { |
219 let ps = if let Some(ps) = ps { |
223 Some(unsafe { compile_shader(gl::FRAGMENT_SHADER, ps)? }) |
220 Some(unsafe { compile_shader(gl::FRAGMENT_SHADER, ps)? }) |
224 } else { |
221 } else { |
225 None |
222 None |
226 }; |
223 }; |
227 |
224 |
228 unsafe { |
225 unsafe { |
229 let program = gl::CreateProgram(); |
226 let program = gl::CreateProgram(); |
230 |
227 |
231 gl::AttachShader(program, vs); |
228 gl::AttachShader(program, vs); |
232 if let Some(ps) = ps { |
229 if let Some(ps) = ps { |
233 gl::AttachShader(program, ps); |
230 gl::AttachShader(program, ps); |
234 } |
231 } |
235 |
232 |
236 for bind in bindings { |
233 for bind in bindings { |
237 match bind { |
234 match bind { |
238 &VariableBinding::Attribute(ref name, id) => { |
235 &VariableBinding::Attribute(ref name, id) => { |
239 let c_str = CString::new(name.as_bytes()).unwrap(); |
236 let c_str = CString::new(name.as_bytes()).unwrap(); |
240 gl::BindAttribLocation(program, id, c_str.to_bytes_with_nul().as_ptr() as *const _); |
237 gl::BindAttribLocation( |
241 }, |
238 program, |
|
239 id, |
|
240 c_str.to_bytes_with_nul().as_ptr() as *const _, |
|
241 ); |
|
242 } |
242 _ => {} |
243 _ => {} |
243 } |
244 } |
244 } |
245 } |
245 |
246 |
246 gl::LinkProgram(program); |
247 gl::LinkProgram(program); |
268 // after linking we setup sampler bindings as specified in the shader |
269 // after linking we setup sampler bindings as specified in the shader |
269 for bind in bindings { |
270 for bind in bindings { |
270 match bind { |
271 match bind { |
271 VariableBinding::Uniform(name, id) => { |
272 VariableBinding::Uniform(name, id) => { |
272 let c_str = CString::new(name.as_bytes()).unwrap(); |
273 let c_str = CString::new(name.as_bytes()).unwrap(); |
273 let index = gl::GetUniformLocation(program, c_str.to_bytes_with_nul().as_ptr() as *const _); |
274 let index = gl::GetUniformLocation( |
|
275 program, |
|
276 c_str.to_bytes_with_nul().as_ptr() as *const _, |
|
277 ); |
274 |
278 |
275 // TODO: impl for block? |
279 // TODO: impl for block? |
276 }, |
280 } |
277 VariableBinding::UniformBlock(name, id) => { |
281 VariableBinding::UniformBlock(name, id) => { |
278 let c_str = CString::new(name.as_bytes()).unwrap(); |
282 let c_str = CString::new(name.as_bytes()).unwrap(); |
279 let index = gl::GetUniformBlockIndex(program, c_str.to_bytes_with_nul().as_ptr() as *const _); |
283 let index = gl::GetUniformBlockIndex( |
|
284 program, |
|
285 c_str.to_bytes_with_nul().as_ptr() as *const _, |
|
286 ); |
280 |
287 |
281 gl::UniformBlockBinding(program, index, *id); |
288 gl::UniformBlockBinding(program, index, *id); |
282 } |
289 } |
283 VariableBinding::Sampler(name, id) => { |
290 VariableBinding::Sampler(name, id) => { |
284 let c_str = CString::new(name.as_bytes()).unwrap(); |
291 let c_str = CString::new(name.as_bytes()).unwrap(); |
285 let index = gl::GetUniformLocation(program, c_str.to_bytes_with_nul().as_ptr() as *const _); |
292 let index = gl::GetUniformLocation( |
286 |
293 program, |
|
294 c_str.to_bytes_with_nul().as_ptr() as *const _, |
|
295 ); |
|
296 |
287 gl::Uniform1i(index, *id as i32); |
297 gl::Uniform1i(index, *id as i32); |
288 }, |
298 } |
289 _ => {} |
299 _ => {} |
290 } |
300 } |
291 } |
301 } |
292 |
302 |
293 Ok(Shader { |
303 Ok(Shader { program }) |
294 program |
|
295 }) |
|
296 } |
304 } |
297 } |
305 } |
298 |
306 |
299 pub fn bind(&self) { |
307 pub fn bind(&self) { |
300 unsafe { |
308 unsafe { |
303 } |
311 } |
304 |
312 |
305 pub fn set_matrix(&self, name: &str, matrix: *const f32) { |
313 pub fn set_matrix(&self, name: &str, matrix: *const f32) { |
306 unsafe { |
314 unsafe { |
307 let c_str = CString::new(name).unwrap(); |
315 let c_str = CString::new(name).unwrap(); |
308 let index = gl::GetUniformLocation(self.program, c_str.to_bytes_with_nul().as_ptr() as *const _); |
316 let index = gl::GetUniformLocation( |
309 |
317 self.program, |
|
318 c_str.to_bytes_with_nul().as_ptr() as *const _, |
|
319 ); |
|
320 |
310 gl::UniformMatrix4fv(index, 1, gl::FALSE, matrix); |
321 gl::UniformMatrix4fv(index, 1, gl::FALSE, matrix); |
311 } |
322 } |
312 } |
323 } |
313 |
324 |
314 pub fn bind_texture_2d(&self, index: u32, texture: &Texture2D) { |
325 pub fn bind_texture_2d(&self, index: u32, texture: &Texture2D) { |
315 self.bind(); |
326 self.bind(); |
316 |
327 |
317 unsafe { |
328 unsafe { |
318 gl::ActiveTexture(gl::TEXTURE0 + index); |
329 gl::ActiveTexture(gl::TEXTURE0 + index); |
319 gl::BindTexture(gl::TEXTURE_2D, texture.handle); |
330 gl::BindTexture(gl::TEXTURE_2D, texture.handle); |
320 } |
331 } |
321 } |
332 } |
353 } |
364 } |
354 } |
365 } |
355 |
366 |
356 impl InputLayout { |
367 impl InputLayout { |
357 pub fn new(elements: Vec<InputElement>) -> Self { |
368 pub fn new(elements: Vec<InputElement>) -> Self { |
358 InputLayout { |
369 InputLayout { elements } |
359 elements, |
370 } |
360 } |
371 |
361 } |
372 pub fn bind( |
362 |
373 &mut self, |
363 pub fn bind(&mut self, buffers: &[(u32, &Buffer)], index_buffer: Option<&Buffer>) -> LayoutGuard { |
374 buffers: &[(u32, &Buffer)], |
|
375 index_buffer: Option<&Buffer>, |
|
376 ) -> LayoutGuard { |
364 let mut vao = 0; |
377 let mut vao = 0; |
365 |
378 |
366 unsafe { |
379 unsafe { |
367 gl::GenVertexArrays(1, &mut vao); |
380 gl::GenVertexArrays(1, &mut vao); |
368 gl::BindVertexArray(vao); |
381 gl::BindVertexArray(vao); |
369 } |
382 } |
370 |
383 |
371 for &(slot, ref buffer) in buffers { |
384 for &(slot, ref buffer) in buffers { |
372 unsafe { |
385 unsafe { |
373 gl::BindBuffer(buffer.ty(), buffer.handle()); |
386 gl::BindBuffer(buffer.ty(), buffer.handle()); |
374 } |
387 } |
375 |
388 |
376 for attr in self.elements.iter().filter(|a| a.buffer_slot == slot) { |
389 for attr in self.elements.iter().filter(|a| a.buffer_slot == slot) { |
377 unsafe { |
390 unsafe { |
378 gl::EnableVertexAttribArray(attr.shader_slot); |
391 gl::EnableVertexAttribArray(attr.shader_slot); |
379 match attr.format { |
392 match attr.format { |
380 InputFormat::Float(fmt, normalized) => { |
393 InputFormat::Float(fmt, normalized) => { |
381 gl::VertexAttribPointer( |
394 gl::VertexAttribPointer( |
382 attr.shader_slot, |
395 attr.shader_slot, |
383 attr.components as i32, |
396 attr.components as i32, |
384 fmt, |
397 fmt, |
385 if normalized { |
398 if normalized { gl::TRUE } else { gl::FALSE }, |
386 gl::TRUE |
|
387 } else { |
|
388 gl::FALSE |
|
389 }, |
|
390 attr.stride as i32, |
399 attr.stride as i32, |
391 attr.offset as *const _ |
400 attr.offset as *const _, |
392 ); |
401 ); |
393 } |
402 } |
394 InputFormat::Integer(fmt) => { |
403 InputFormat::Integer(fmt) => { |
395 gl::VertexAttribIPointer( |
404 gl::VertexAttribIPointer( |
396 attr.shader_slot, |
405 attr.shader_slot, |
397 attr.components as i32, |
406 attr.components as i32, |
398 fmt, |
407 fmt, |
399 attr.stride as i32, |
408 attr.stride as i32, |
400 attr.offset as *const _ |
409 attr.offset as *const _, |
401 ); |
410 ); |
402 } |
411 } |
403 } |
412 } |
404 |
|
405 } |
413 } |
406 } |
414 } |
407 } |
415 } |
408 |
416 |
409 if let Some(buf) = index_buffer { |
417 if let Some(buf) = index_buffer { |
410 unsafe { |
418 unsafe { |
411 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, buf.handle()); |
419 gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, buf.handle()); |
412 } |
420 } |
413 } |
421 } |
414 |
422 |
415 LayoutGuard { |
423 LayoutGuard { vao } |
416 vao |
424 } |
417 } |
425 } |
418 } |
|
419 } |
|