miru_gl/lib.rs
1use std::fmt;
2use std::ops;
3use std::rc::Rc;
4
5#[allow(clippy::all)]
6mod gl {
7 include!(concat!(env!("OUT_DIR"), "/opengl-bindings.rs"));
8}
9
10pub use gl::*;
11
12mod miru {
13 include!(concat!(env!("OUT_DIR"), "/miru-pinned-opengl-version.rs"));
14}
15
16/// Wrapper around Gl type that should be used instead of [`Gl`][1].
17///
18/// This transparent wrapper allows to safely share and use OpenGL functions
19/// without risk of them being called before they're loaded.
20///
21/// \![`Send`][2] nature of [`Rc<T>`][3] also guarantees that context won't be
22/// transferred across thread boundaries, ensuring that functions of a context
23/// can only be called in the same thread they were loaded in.
24///
25/// [1]: struct.Gl.html
26/// [2]: https://doc.rust-lang.org/std/marker/trait.Send.html
27/// [3]: https://doc.rust-lang.org/std/rc/struct.Rc.html
28#[derive(Clone)]
29pub struct MiruGl {
30 inner: Rc<Gl>,
31}
32
33impl MiruGl {
34 /// Loads OpenGL functions and returns shared handle.
35 ///
36 /// # Examples
37 ///
38 /// ~~~ignore
39 /// // the supplied function must be of the type:
40 /// // `&fn(symbol: &'static str) -> *const std::ffi::c_void`
41 /// let gl = miru_gl::MiruGl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
42 /// ~~~
43 #[cfg_attr(tarpaulin, skip)]
44 pub fn load_with<F>(loadfn: F) -> MiruGl
45 where
46 F: FnMut(&'static str) -> *const std::ffi::c_void,
47 {
48 MiruGl {
49 inner: Rc::new(Gl::load_with(loadfn)),
50 }
51 }
52
53 /// Returns OpenGL version used by Miru.
54 ///
55 /// # Examples
56 ///
57 /// ~~~ignore
58 /// let (major, minor) = gl.version();
59 /// ~~~
60 #[cfg_attr(tarpaulin, skip)]
61 pub fn version(&self) -> (u8, u8) {
62 miru::OPENGL_VERSION
63 }
64}
65
66impl fmt::Debug for MiruGl {
67 #[cfg_attr(tarpaulin, skip)]
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 let (major, minor) = self.version();
70 write!(
71 f,
72 "MiruGl: Shared OpenGL {}.{} (Core Profile) api handle",
73 major, minor
74 )
75 }
76}
77
78impl ops::Deref for MiruGl {
79 type Target = Gl;
80
81 #[cfg_attr(tarpaulin, skip)]
82 fn deref(&self) -> &Self::Target {
83 &self.inner
84 }
85}