1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#[macro_export]
macro_rules! program_cache {
    { $vertex:expr, $fragment:expr } => {
        thread_local!(static SHADER: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, ::glin::Program>> =
                ::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));

        pub fn get_program<'c, R: ::glin::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> &'static ::glin::Program{

            fn new_program<'c, R: ::glin::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> ::glin::Program{
                gl.new_program()
                    .from_src_bindings(&[
                        (::gl::VERTEX_SHADER, shaders::VERTEX_SHADER),
                        (::gl::FRAGMENT_SHADER, shaders::FRAGMENT_SHADER)
                    ], &$crate::default_attribute_bindings()).unwrap()
            }

        	SHADER.with(|cache| {
                let cache = unsafe{ &mut *cache.get() };
                let program = cache
                    .entry(gl.id())
                    .or_insert_with(|| new_program(gl));
                unsafe{ ::std::mem::transmute(program) }
            })
        }

        mod shaders{
            pub static VERTEX_SHADER: &'static str = include_str!($vertex);
            pub static FRAGMENT_SHADER: &'static str = include_str!($fragment);
        }
    };

    { $vertex:expr, $fragment:expr, $getter:ident, $shader:ident  } => {
        thread_local!(static $shader: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, ::glin::Program>> =
                ::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));

        pub fn $getter<'c, R: ::glin::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> &'static ::glin::Program{
            static VERTEX_SHADER: &'static str = include_str!($vertex);
            static FRAGMENT_SHADER: &'static str = include_str!($fragment);

            fn new_program<'c, R: ::glin::RenderSurface>(gl: &$crate::Renderer<'c, R>) -> ::glin::Program{
                gl.new_program()
                    .from_src_bindings(&[
                        (::gl::VERTEX_SHADER, VERTEX_SHADER),
                        (::gl::FRAGMENT_SHADER, FRAGMENT_SHADER)
                    ], &$crate::default_attribute_bindings()).unwrap()
            }

        	$shader.with(|cache| {
                let cache = unsafe{ &mut *cache.get() };
                let program = cache
                    .entry(gl.id())
                    .or_insert_with(|| new_program(gl));
                unsafe{ ::std::mem::transmute(program) }
            })
        }
    }
}

#[macro_export]
macro_rules! geometry_cache{
    {$ty: ty, $mesh: expr} => {
        thread_local!(static GEOMETRY: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, ::glin::SimpleVao<$ty>>> =
            ::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));

        pub fn get_geometry<'r, 'c, R: glin::RenderSurface>(gl: &'r $crate::Renderer<'c, R>) -> &'r mut ::glin::SimpleVao<$ty> {
            GEOMETRY.with(|cache|{
                let cache = unsafe{ &mut *cache.get() };
                let vao = cache.entry(gl.id())
                    .or_insert_with(|| {
                        gl.new_simple_vao().from_data_bindings(
                            &$mesh,
                            &$crate::default_attribute_bindings(),
                            $crate::STATIC_DRAW).unwrap()
                    });
                unsafe{ ::std::mem::transmute(vao) }
            })
        }
    }
}

#[macro_export]
macro_rules! geometry_cache_per_vertex_type {
    {} => {
        thread_local!(static GEOMETRY: ::std::cell::UnsafeCell<::std::collections::HashMap<(usize, ::std::any::TypeId), Box<::std::any::Any>>> =
            ::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));

        pub fn get_geometry<'r, 'c, T: VertexFormat, R: $crate::offscreen_buffer::RenderSurface>(gl: &'r $crate::Renderer<'c, R>, mesh: ::graphics::Mesh<T>) -> &'r mut ::glin::SimpleVao<T> {
            GEOMETRY.with(|cache|{
                let cache = unsafe{ &mut *cache.get() };
                let vao = cache.entry((gl.id(), ::std::any::TypeId::of::<T>()))
                    .or_insert_with(|| {
                        gl.new_simple_vao().from_data_bindings(
                            &$mesh,
                            &$crate::default_attribute_bindings(),
                            $crate::STATIC_DRAW).unwrap()
                    });
                unsafe{ ::std::mem::transmute(vao) }
            })
        }
    }
}


#[macro_export]
macro_rules! image_cache{
    {$getter:ident, $cache_name: ident, $image: expr} => {
        thread_local!(static $cache_name: ::std::cell::UnsafeCell<::std::collections::HashMap<usize, ::glin::Texture>> =
            ::std::cell::UnsafeCell::new(::std::collections::HashMap::new()));

        pub fn $getter<'r, 'c, R: glin::RenderSurface>(gl: &'r $crate::Renderer<'c, R>) -> &'r mut ::glin::Texture {
            $cache_name.with(|cache|{
                let cache = unsafe{ &mut *cache.get() };
                let tex = cache.entry(gl.id())
                    .or_insert_with(|| {
                        gl.new_texture().from_image(&$image, glin::gl::TEXTURE_2D).unwrap()
                    });
                unsafe{ ::std::mem::transmute(tex) }
            })
        }
    }
}