1 use crate::platform::unix::x11::XConnection; 2 use glutin_glx_sys as ffi; 3 4 use std::sync::Arc; 5 6 /// A guard for when you want to make the context current. Destroying the guard 7 /// restores the previously-current context. 8 #[derive(Debug)] 9 pub struct MakeCurrentGuard { 10 old_display: *mut ffi::Display, 11 display: *mut ffi::Display, 12 xconn: Arc<XConnection>, 13 possibly_invalid: Option<MakeCurrentGuardInner>, 14 } 15 16 #[derive(Debug)] 17 struct MakeCurrentGuardInner { 18 old_drawable: ffi::glx::types::GLXDrawable, 19 old_context: ffi::GLXContext, 20 } 21 22 impl MakeCurrentGuard { new( xconn: &Arc<XConnection>, drawable: ffi::glx::types::GLXDrawable, context: ffi::GLXContext, ) -> Result<Self, String>23 pub fn new( 24 xconn: &Arc<XConnection>, 25 drawable: ffi::glx::types::GLXDrawable, 26 context: ffi::GLXContext, 27 ) -> Result<Self, String> { 28 unsafe { 29 let glx = super::GLX.as_ref().unwrap(); 30 31 let ret = MakeCurrentGuard { 32 old_display: glx.GetCurrentDisplay() as *mut _, 33 display: xconn.display as *mut _, 34 xconn: Arc::clone(xconn), 35 possibly_invalid: Some(MakeCurrentGuardInner { 36 old_drawable: glx.GetCurrentDrawable(), 37 old_context: glx.GetCurrentContext(), 38 }), 39 }; 40 41 let res = glx.MakeCurrent(xconn.display as *mut _, drawable, context); 42 43 if res == 0 { 44 let err = xconn.check_errors(); 45 Err(format!("`glXMakeCurrent` failed: {:?}", err)) 46 } else { 47 Ok(ret) 48 } 49 } 50 } 51 old_context(&mut self) -> Option<ffi::GLXContext>52 pub fn old_context(&mut self) -> Option<ffi::GLXContext> { 53 self.possibly_invalid.as_ref().map(|pi| pi.old_context) 54 } 55 invalidate(&mut self)56 pub fn invalidate(&mut self) { 57 self.possibly_invalid.take(); 58 } 59 } 60 61 impl Drop for MakeCurrentGuard { drop(&mut self)62 fn drop(&mut self) { 63 let glx = super::GLX.as_ref().unwrap(); 64 let (drawable, context) = match self.possibly_invalid.take() { 65 Some(inner) => (inner.old_drawable, inner.old_context), 66 None => (0, std::ptr::null()), 67 }; 68 69 let display = match self.old_display { 70 old_display if old_display == std::ptr::null_mut() => self.display, 71 old_display => old_display, 72 }; 73 74 let res = unsafe { glx.MakeCurrent(display as *mut _, drawable, context) }; 75 76 if res == 0 { 77 let err = self.xconn.check_errors(); 78 panic!("`glXMakeCurrent` failed: {:?}", err); 79 } 80 } 81 } 82