1 use glutin_egl_sys as ffi;
2 
3 /// A guard for when you want to make the context current. Destroying the guard
4 /// restores the previously-current context.
5 #[derive(Debug)]
6 pub struct MakeCurrentGuard {
7     display: ffi::egl::types::EGLDisplay,
8     old_display: ffi::egl::types::EGLDisplay,
9     possibly_invalid: Option<MakeCurrentGuardInner>,
10 }
11 
12 #[derive(Debug, PartialEq)]
13 struct MakeCurrentGuardInner {
14     old_draw_surface: ffi::egl::types::EGLSurface,
15     old_read_surface: ffi::egl::types::EGLSurface,
16     old_context: ffi::egl::types::EGLContext,
17 }
18 
19 impl MakeCurrentGuard {
new( display: ffi::egl::types::EGLDisplay, draw_surface: ffi::egl::types::EGLSurface, read_surface: ffi::egl::types::EGLSurface, context: ffi::egl::types::EGLContext, ) -> Result<Self, String>20     pub fn new(
21         display: ffi::egl::types::EGLDisplay,
22         draw_surface: ffi::egl::types::EGLSurface,
23         read_surface: ffi::egl::types::EGLSurface,
24         context: ffi::egl::types::EGLContext,
25     ) -> Result<Self, String> {
26         unsafe {
27             let egl = super::EGL.as_ref().unwrap();
28 
29             let mut ret = MakeCurrentGuard {
30                 display,
31                 old_display: egl.GetCurrentDisplay(),
32                 possibly_invalid: Some(MakeCurrentGuardInner {
33                     old_draw_surface: egl
34                         .GetCurrentSurface(ffi::egl::DRAW as i32),
35                     old_read_surface: egl
36                         .GetCurrentSurface(ffi::egl::READ as i32),
37                     old_context: egl.GetCurrentContext(),
38                 }),
39             };
40 
41             if ret.old_display == ffi::egl::NO_DISPLAY {
42                 ret.invalidate();
43             }
44 
45             let res =
46                 egl.MakeCurrent(display, draw_surface, read_surface, context);
47 
48             if res == 0 {
49                 let err = egl.GetError();
50                 Err(format!("`eglMakeCurrent` failed: 0x{:x}", err))
51             } else {
52                 Ok(ret)
53             }
54         }
55     }
56 
if_any_same_then_invalidate( &mut self, draw_surface: ffi::egl::types::EGLSurface, read_surface: ffi::egl::types::EGLSurface, context: ffi::egl::types::EGLContext, )57     pub fn if_any_same_then_invalidate(
58         &mut self,
59         draw_surface: ffi::egl::types::EGLSurface,
60         read_surface: ffi::egl::types::EGLSurface,
61         context: ffi::egl::types::EGLContext,
62     ) {
63         if self.possibly_invalid.is_some() {
64             let pi = self.possibly_invalid.as_ref().unwrap();
65             if pi.old_draw_surface == draw_surface
66                 && draw_surface != ffi::egl::NO_SURFACE
67                 || pi.old_read_surface == read_surface
68                     && read_surface != ffi::egl::NO_SURFACE
69                 || pi.old_context == context
70             {
71                 self.invalidate();
72             }
73         }
74     }
75 
invalidate(&mut self)76     pub fn invalidate(&mut self) {
77         self.possibly_invalid.take();
78     }
79 }
80 
81 impl Drop for MakeCurrentGuard {
drop(&mut self)82     fn drop(&mut self) {
83         let egl = super::EGL.as_ref().unwrap();
84         let (draw_surface, read_surface, context) =
85             match self.possibly_invalid.take() {
86                 Some(inner) => (
87                     inner.old_draw_surface,
88                     inner.old_read_surface,
89                     inner.old_context,
90                 ),
91                 None => (
92                     ffi::egl::NO_SURFACE,
93                     ffi::egl::NO_SURFACE,
94                     ffi::egl::NO_CONTEXT,
95                 ),
96             };
97 
98         let display = match self.old_display {
99             ffi::egl::NO_DISPLAY => self.display,
100             old_display => old_display,
101         };
102 
103         unsafe {
104             let res =
105                 egl.MakeCurrent(display, draw_surface, read_surface, context);
106 
107             if res == 0 {
108                 let err = egl.GetError();
109                 panic!("`eglMakeCurrent` failed: 0x{:x}", err)
110             }
111         }
112     }
113 }
114