1#[macro_export]
16macro_rules! assert_no_gl_error {
17 ($display: expr) => {
18 {
19 let message = format!("{}:{}", file!(), line!());
20 $display.assert_no_error(Some(&message[..]));
21 }
22 };
23 ($display: expr, $msg: expr) => {
24 {
25 let message = format!("{}:{} {}", file!(), line!(), $msg);
26 $display.assert_no_error(Some(&message[..]));
27 }
28 };
29 ($display: expr, $fmt: expr, $($arg:tt)+) => {
30 {
31 let message = format!(concat!("{}:{} ", $fmt), file!(), line!(), $($arg)+);
32 $display.assert_no_error(Some(&message[..]));
33 }
34 }
35}
36
37#[macro_export]
51macro_rules! uniform {
52 () => {
53 $crate::uniforms::EmptyUniforms
54 };
55
56 ($field:ident: $value:expr) => {
57 $crate::uniforms::UniformsStorage::new(stringify!($field), $value)
58 };
59
60 ($field1:ident: $value1:expr, $($field:ident: $value:expr),+) => {
61 {
62 let uniforms = $crate::uniforms::UniformsStorage::new(stringify!($field1), $value1);
63 $(
64 let uniforms = uniforms.add(stringify!($field), $value);
65 )+
66 uniforms
67 }
68 };
69
70 ($($field:ident: $value:expr),*,) => {
71 $crate::uniform!($($field: $value),*)
72 };
73}
74
75#[macro_export]
94macro_rules! dynamic_uniform{
95 () => {
96 $crate::uniforms::DynamicUniforms::new()
97 };
98
99 ($($field:ident: $value:expr), *,) => {
100 {
101 let mut tmp = $crate::uniforms::DynamicUniforms::new();
102 $(
103 tmp.add(stringify!($field), $value);
104 )*
105 tmp
106 }
107 };
108}
109
110#[macro_export]
168macro_rules! implement_vertex {
169 ($struct_name:ident, $($field_name:ident),+) => (
170 impl $struct_name {
171 const BINDINGS: $crate::vertex::VertexFormat = &[
172 $(
173 (
174 std::borrow::Cow::Borrowed(stringify!($field_name)),
175 $crate::__glium_offset_of!($struct_name, $field_name),
176 -1,
177 {
178 const fn attr_type_of_val<T: $crate::vertex::Attribute>(_: Option<&T>)
179 -> $crate::vertex::AttributeType
180 {
181 <T as $crate::vertex::Attribute>::TYPE
182 }
183 let field_option = match None::<&$struct_name> {
184 Some(v) => Some(&v.$field_name),
185 None => None
186 };
187 attr_type_of_val(field_option)
188 },
189 false
190 )
191 ),+
192 ];
193 }
194
195 impl $crate::vertex::Vertex for $struct_name {
196 #[inline]
197 fn build_bindings() -> $crate::vertex::VertexFormat {
198 Self::BINDINGS
199 }
200 }
201 );
202
203 ($struct_name:ident, $($field_name:ident normalize($should_normalize:expr)),+) => {
204 impl $struct_name {
205 const BINDINGS: $crate::vertex::VertexFormat = &[
206 $(
207 (
208 std::borrow::Cow::Borrowed(stringify!($field_name)),
209 $crate::__glium_offset_of!($struct_name, $field_name),
210 -1,
211 {
212 const fn attr_type_of_val<T: $crate::vertex::Attribute>(_: Option<&T>)
213 -> $crate::vertex::AttributeType
214 {
215 <T as $crate::vertex::Attribute>::TYPE
216 }
217 let field_option = match None::<&$struct_name> {
218 Some(v) => Some(&v.$field_name),
219 None => None
220 };
221 attr_type_of_val(field_option)
222 },
223 {
224 $should_normalize
225 }
226 )
227 ),+
228 ];
229 }
230 impl $crate::vertex::Vertex for $struct_name {
231 #[inline]
232 fn build_bindings() -> $crate::vertex::VertexFormat {
233 Self::BINDINGS
234 }
235 }
236 };
237
238 ($struct_name:ident, $($field_name:ident location($location:expr)),+) => {
239 impl $struct_name {
240 const BINDINGS: $crate::vertex::VertexFormat = &[
241 $(
242 (
243 std::borrow::Cow::Borrowed(stringify!($field_name)),
244 $crate::__glium_offset_of!($struct_name, $field_name),
245 {
246 $location
247 },
248 {
249 const fn attr_type_of_val<T: $crate::vertex::Attribute>(_: Option<&T>)
250 -> $crate::vertex::AttributeType
251 {
252 <T as $crate::vertex::Attribute>::TYPE
253 }
254 let field_option = match None::<&$struct_name> {
255 Some(v) => Some(&v.$field_name),
256 None => None
257 };
258 attr_type_of_val(field_option)
259 },
260 false
261 )
262 ),+
263 ];
264 }
265
266 impl $crate::vertex::Vertex for $struct_name {
267 #[inline]
268 fn build_bindings() -> $crate::vertex::VertexFormat {
269 Self::BINDINGS
270 }
271 }
272 };
273
274 ($struct_name:ident, $($field_name:ident),+,) => (
275 $crate::implement_vertex!($struct_name, $($field_name),+);
276 );
277}
278
279#[macro_export]
299macro_rules! implement_buffer_content {
301 (__as_item $i:item) => {$i};
302
303 (__impl $struct_name:ident [$($gs:tt)*]) => {
304 implement_buffer_content! { __as_item
305 unsafe impl<$($gs)*> $crate::buffer::Content for $struct_name<$($gs)*> {
306 type Owned = Box<$struct_name<$($gs)*>>;
307
308 #[inline]
309 unsafe fn read<F, E>(size: usize, f: F) -> ::std::result::Result<Box<$struct_name<$($gs)*>>, E>
310 where F: FnOnce(&mut $struct_name<$($gs)*>) -> ::std::result::Result<(), E>
311 {
312 use std::mem;
313
314 assert!(<$struct_name as $crate::buffer::Content>::is_size_suitable(size));
315
316 let mut storage: Vec<u8> = Vec::with_capacity(size);
317 unsafe { storage.set_len(size) };
318 let storage = storage.into_boxed_slice();
319 let mut storage: Box<$struct_name<$($gs)*>> = unsafe { mem::transmute(storage) };
320
321 f(&mut storage)?;
322 Ok(storage)
323 }
324
325 #[inline]
326 fn get_elements_size() -> usize {
327 use std::mem;
328
329 let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
330 mem::size_of_val(fake_ptr)
331 }
332
333 #[inline]
334 fn to_void_ptr(&self) -> *const () {
335 use std::mem;
336 let (ptr, _): (*const (), usize) = unsafe { mem::transmute(self) };
337 ptr
338 }
339
340 #[inline]
341 fn ref_from_ptr(ptr: *mut (), size: usize) -> Option<*mut $struct_name<$($gs)*>> {
342 use std::mem;
343
344 let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
345 let min_size = mem::size_of_val(fake_ptr);
346
347 let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 1usize)) };
348 let step = mem::size_of_val(fake_ptr) - min_size;
349
350 if size < min_size {
351 return None;
352 }
353
354 let variadic = size - min_size;
355 if variadic % step != 0 {
356 return None;
357 }
358
359 Some(unsafe { mem::transmute((ptr, (variadic / step) as usize)) })
360 }
361
362 #[inline]
363 fn is_size_suitable(size: usize) -> bool {
364 use std::mem;
365
366 let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 0usize)) };
367 let min_size = mem::size_of_val(fake_ptr);
368
369 let fake_ptr: &$struct_name = unsafe { mem::transmute((0usize, 1usize)) };
370 let step = mem::size_of_val(fake_ptr) - min_size;
371
372 size > min_size && (size - min_size) % step == 0
373 }
374 }
375 }
376 };
377
378 ($struct_name:ident,) => (
379 $crate::implement_buffer_content!($struct_name);
380 );
381
382 ($struct_name:ident) => (
383 $crate::implement_buffer_content!(__impl $struct_name []);
384 );
385
386 ($struct_name:ident <$t1:tt>) => (
387 $crate::implement_buffer_content!(__impl $struct_name [$t1]);
388 );
389}
390
391#[macro_export]
411macro_rules! implement_uniform_block {
412 (__as_item $i:item) => {$i};
413
414 (__impl $struct_name:ident [$($gs:tt)*], $($field_name:ident),+) => (
415 implement_uniform_block! { __as_item
416 impl<$($gs)*> $crate::uniforms::UniformBlock for $struct_name<$($gs)*> {
417 fn matches(layout: &$crate::program::BlockLayout, base_offset: usize)
418 -> ::std::result::Result<(), $crate::uniforms::LayoutMismatchError>
419 {
420 use std::mem;
421 use $crate::program::BlockLayout;
422 use $crate::uniforms::LayoutMismatchError;
423
424 if let &BlockLayout::Struct { ref members } = layout {
425 for &(ref name, _) in members {
427 if $(name != stringify!($field_name) &&)+ true {
428 return Err(LayoutMismatchError::MissingField {
429 name: name.clone(),
430 });
431 }
432 }
433
434 fn matches_from_ty<T: $crate::uniforms::UniformBlock + ?Sized>(_: Option<&T>,
435 layout: &$crate::program::BlockLayout, base_offset: usize)
436 -> ::std::result::Result<(), $crate::uniforms::LayoutMismatchError>
437 {
438 <T as $crate::uniforms::UniformBlock>::matches(layout, base_offset)
439 }
440
441 $(
443 let reflected_ty = members.iter().find(|&&(ref name, _)| {
444 name == stringify!($field_name)
445 });
446 let reflected_ty = match reflected_ty {
447 Some(t) => &t.1,
448 None => return Err(LayoutMismatchError::MissingField {
449 name: stringify!($field_name).to_owned(),
450 })
451 };
452
453 let input_offset = mem::offset_of!($struct_name, $field_name);
454 let dummy_field = None::<&$struct_name>.map(|v| &v.$field_name);
455
456 match matches_from_ty(dummy_field, reflected_ty, input_offset) {
457 Ok(_) => (),
458 Err(e) => return Err(LayoutMismatchError::MemberMismatch {
459 member: stringify!($field_name).to_owned(),
460 err: Box::new(e),
461 })
462 };
463 )+
464
465 Ok(())
466
467 } else {
468 Err(LayoutMismatchError::LayoutMismatch {
469 expected: layout.clone(),
470 obtained: <Self as $crate::uniforms::UniformBlock>::build_layout(base_offset),
471 })
472 }
473 }
474
475 fn build_layout(base_offset: usize) -> $crate::program::BlockLayout {
476 use $crate::program::BlockLayout;
477
478 fn layout_from_ty<T: $crate::uniforms::UniformBlock + ?Sized>(_: Option<&T>, base_offset: usize)
479 -> BlockLayout
480 {
481 <T as $crate::uniforms::UniformBlock>::build_layout(base_offset)
482 }
483
484 BlockLayout::Struct {
485 members: vec![
486 $(
487 (
488 stringify!($field_name).to_owned(),
489 {
490 let offset = $crate::__glium_offset_of!($struct_name, $field_name);
491 let field_option = None::<&$struct_name>.map(|v| &v.$field_name);
492 layout_from_ty(field_option, offset + base_offset)
493 }
494 ),
495 )+
496 ],
497 }
498 }
499 }
500 }
501 );
502
503 ($struct_name:ident, $($field_name:ident),+,) => (
504 $crate::implement_uniform_block!($struct_name, $($field_name),+);
505 );
506
507 ($struct_name:ident, $($field_name:ident),+) => (
508 $crate::implement_uniform_block!(__impl $struct_name [], $($field_name),+);
509 );
510
511 ($struct_name:ident<$l:tt>, $($field_name:ident),+) => (
512 $crate::implement_uniform_block!(__impl $struct_name [$l], $($field_name),+);
513 );
514}
515
516#[macro_export]
583macro_rules! program {
584 ($facade:expr,) => (
585 Err($crate::program::ProgramChooserCreationError::NoVersion)
586 );
587
588 ($facade:expr,,$($rest:tt)*) => (
589 $crate::program!($facade,$($rest)*)
590 );
591
592 ($facade:expr, $num:tt => $($rest:tt)*) => (
593 {
594 let context = $crate::backend::Facade::get_context($facade);
595 let version = program!(_parse_num_gl $num);
596 $crate::program!(_inner, context, version, $($rest)*)
597 }
598 );
599
600 ($facade:expr, $num:tt es => $($rest:tt)*) => (
601 {
602 let context = $crate::backend::Facade::get_context($facade);
603 let version = program!(_parse_num_gles $num);
604 $crate::program!(_inner, context, version, $($rest)*)
605 }
606 );
607
608 (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+}$($rest:tt)*) => (
609 if $context.is_glsl_version_supported(&$vers) {
610 let __vertex_shader: &str = "";
611 let __tessellation_control_shader: Option<&str> = None;
612 let __tessellation_evaluation_shader: Option<&str> = None;
613 let __geometry_shader: Option<&str> = None;
614 let __fragment_shader: &str = "";
615 let __outputs_srgb: bool = true;
616 let __uses_point_size: bool = false;
617
618 $(
619 $crate::program!(_program_ty $ty, $src, __vertex_shader, __tessellation_control_shader,
620 __tessellation_evaluation_shader, __geometry_shader, __fragment_shader,
621 __outputs_srgb, __uses_point_size);
622 )+
623
624 let input = $crate::program::ProgramCreationInput::SourceCode {
625 vertex_shader: __vertex_shader,
626 tessellation_control_shader: __tessellation_control_shader,
627 tessellation_evaluation_shader: __tessellation_evaluation_shader,
628 geometry_shader: __geometry_shader,
629 fragment_shader: __fragment_shader,
630 transform_feedback_varyings: None,
631 outputs_srgb: __outputs_srgb,
632 uses_point_size: __uses_point_size,
633 };
634
635 $crate::program::Program::new($context, input)
636 .map_err(|err| $crate::program::ProgramChooserCreationError::from(err))
637
638 } else {
639 $crate::program!($context, $($rest)*)
640 }
641 );
642
643 (_inner, $context:ident, $vers:ident, {$($ty:ident:$src:expr),+,}$($rest:tt)*) => (
644 $crate::program!(_inner, $context, $vers, {$($ty:$src),+} $($rest)*);
645 );
646
647 (_program_ty vertex, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
648 let $vs = $src;
649 );
650
651 (_program_ty tessellation_control, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
652 let $tcs = Some($src);
653 );
654
655 (_program_ty tessellation_evaluation, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
656 let $tes = Some($src);
657 );
658
659 (_program_ty geometry, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
660 let $gs = Some($src);
661 );
662
663 (_program_ty fragment, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
664 let $fs = $src;
665 );
666
667 (_program_ty point_size, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
668 let $ps = $src;
669 );
670
671 (_program_ty outputs_srgb, $src:expr, $vs:ident, $tcs:ident, $tes:ident, $gs:ident, $fs:ident, $srgb:ident, $ps:ident) => (
672 let $srgb = $src;
673 );
674
675 (_parse_num_gl $num:expr) => (
676 if $num == 100 {
677 $crate::Version($crate::Api::GlEs, 1, 0)
678 } else {
679 let num: u32 = $num;
680 $crate::Version($crate::Api::Gl, (num / 100) as u8, ((num % 100) / 10) as u8)
681 }
682 );
683
684 (_parse_num_gles $num:expr) => ({
685 let num: u32 = $num;
686 $crate::Version($crate::Api::GlEs, (num / 100) as u8, ((num % 100) / 10) as u8)
687 });
688}
689
690#[cfg(test)]
691mod tests {
692 #[test]
693 fn trailing_comma_impl_uniforms() {
694 let u = uniform!{ a: 5, b: 6, };
695 }
696
697 #[test]
698 fn trailing_comma_impl_vertex() {
699 #[derive(Copy, Clone)]
700 struct Foo {
701 pos: [f32; 2],
702 }
703
704 implement_vertex!(Foo, pos,);
705 }
706
707 #[test]
708 fn assert_no_error_macro() {
709 struct Dummy;
710 impl Dummy {
711 fn assert_no_error(&self, _: Option<&str>) { }
712 }
713
714 assert_no_gl_error!(Dummy);
715
716 assert_no_gl_error!(Dummy, "hi");
717
718 assert_no_gl_error!(Dummy, "{} {}", 1, 2);
719 }
720}