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 = 42 glx.MakeCurrent(xconn.display as *mut _, drawable, context); 43 44 if res == 0 { 45 let err = xconn.check_errors(); 46 Err(format!("`glXMakeCurrent` failed: {:?}", err)) 47 } else { 48 Ok(ret) 49 } 50 } 51 } 52 old_context(&mut self) -> Option<ffi::GLXContext>53 pub fn old_context(&mut self) -> Option<ffi::GLXContext> { 54 self.possibly_invalid.as_ref().map(|pi| pi.old_context) 55 } 56 invalidate(&mut self)57 pub fn invalidate(&mut self) { 58 self.possibly_invalid.take(); 59 } 60 } 61 62 impl Drop for MakeCurrentGuard { drop(&mut self)63 fn drop(&mut self) { 64 let glx = super::GLX.as_ref().unwrap(); 65 let (drawable, context) = match self.possibly_invalid.take() { 66 Some(inner) => (inner.old_drawable, inner.old_context), 67 None => (0, std::ptr::null()), 68 }; 69 70 let display = match self.old_display { 71 old_display if old_display == std::ptr::null_mut() => self.display, 72 old_display => old_display, 73 }; 74 75 let res = 76 unsafe { glx.MakeCurrent(display as *mut _, drawable, context) }; 77 78 if res == 0 { 79 let err = self.xconn.check_errors(); 80 panic!("`glXMakeCurrent` failed: {:?}", err); 81 } 82 } 83 } 84