suzy/platform/opengl/
primitive.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5macro_rules! gl_object {
6    ($vis:vis $name:ident, $create:ident, $delete:ident, $count:expr) => {
7        $vis struct $name {
8            pub(crate) ids: [
9                $crate::platform::opengl::context::bindings::types::GLuint;
10                $count
11            ],
12            pub(crate) ready: Option<bool>,
13            pub(crate) gl:
14                ::std::rc::Weak<$crate::platform::opengl::OpenGlBindings>,
15        }
16        gl_object! {impl $name, $create, $delete, $count}
17    };
18    (impl $name:ident, $create:ident, $delete:ident, $count:expr) => {
19        impl $name {
20            #[allow(dead_code)]
21            pub fn new() -> Self {
22                Self {
23                    ids: [0; $count],
24                    ready: None,
25                    gl: ::std::rc::Weak::new(),
26                }
27            }
28
29            #[allow(dead_code)]
30            pub fn get(&mut self)
31                -> Option<([
32                    $crate::platform::opengl::context::bindings::types::GLuint;
33                    $count
34                ],
35                    ::std::rc::Rc<$crate::platform::opengl::OpenGlBindings>,
36                )>
37            {
38                self.ready.get_or_insert(false);
39                self.gl.upgrade().map(|gl| (self.ids, gl))
40            }
41
42            #[allow(dead_code)]
43            pub fn mark_ready(&mut self) {
44                self.ready = Some(true);
45            }
46
47            #[allow(dead_code)]
48            pub fn check_ready(
49                &mut self,
50                gl: &::std::rc::Rc<$crate::platform::opengl::OpenGlBindings>,
51            ) -> Option<bool> {
52                let weak_gl = ::std::rc::Rc::downgrade(gl);
53                if !self.gl.ptr_eq(&weak_gl) {
54                    unsafe {
55                        self.invalidate();
56                        gl.$create($count, self.ids.as_mut_ptr());
57                    }
58                    self.ready = self.ready.map(|_| false);
59                    self.gl = weak_gl;
60                }
61                self.ready
62            }
63
64            unsafe fn invalidate(&mut self) {
65                // if we can't get the gl bindings here, it's probably
66                // because the context went away, in which case
67                // it's ok to "leak" the resource, it's already cleaned
68                // up by the context going away
69                if let Some(gl) = self.gl.upgrade() {
70                    gl.$delete($count, self.ids.as_ptr());
71                }
72            }
73        }
74        impl ::std::fmt::Debug for $name {
75            fn fmt(&self, f: &mut ::std::fmt::Formatter)
76                -> Result<(), ::std::fmt::Error>
77            {
78                let mut st = f.debug_struct(stringify!($name));
79                if let Some(true) = self.ready {
80                    st.field("ids", &self.ids);
81                } else {
82                    st.field("ready", &self.ready);
83                }
84                st.finish()
85            }
86        }
87        impl PartialEq for $name {
88            fn eq(&self, other: &Self) -> bool {
89                (self.ids == other.ids) && self.gl.ptr_eq(&other.gl)
90            }
91        }
92        impl Drop for $name {
93            fn drop(&mut self) {
94                unsafe {
95                    self.invalidate();
96                }
97            }
98        }
99    };
100}