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