diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/x11/ffi.rs | 18 | ||||
-rw-r--r-- | src/x11/mod.rs | 99 |
2 files changed, 96 insertions, 21 deletions
diff --git a/src/x11/ffi.rs b/src/x11/ffi.rs index a31b9c2..d127a27 100644 --- a/src/x11/ffi.rs +++ b/src/x11/ffi.rs @@ -13,7 +13,7 @@ pub type Drawable = XID; // TODO: not sure pub type GLXContext = *const (); pub type GLXContextID = XID; pub type GLXDrawable = XID; -pub type GLXFBConfig = (); +pub type GLXFBConfig = *const (); pub type GLXPbuffer = XID; pub type GLXPixmap = XID; pub type GLXWindow = XID; @@ -204,6 +204,15 @@ pub static GLX_PBUFFER: libc::c_int = 0x8023; pub static GLX_PBUFFER_HEIGHT: libc::c_int = 0x8040; pub static GLX_PBUFFER_WIDTH: libc::c_int = 0x8041; +pub static GLX_CONTEXT_MAJOR_VERSION: libc::c_int = 0x2091; +pub static GLX_CONTEXT_MINOR_VERSION: libc::c_int = 0x2092; +pub static GLX_CONTEXT_FLAGS: libc::c_int = 0x2094; +pub static GLX_CONTEXT_PROFILE_MASK: libc::c_int = 0x9126; +pub static GLX_CONTEXT_DEBUG_BIT: libc::c_int = 0x0001; +pub static GLX_CONTEXT_FORWARD_COMPATIBLE_BIT: libc::c_int = 0x0002; +pub static GLX_CONTEXT_CORE_PROFILE_BIT: libc::c_int = 0x00000001; +pub static GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT: libc::c_int = 0x00000002; + pub static XIMPreeditArea: libc::c_long = 0x0001; pub static XIMPreeditCallbacks: libc::c_long = 0x0002; pub static XIMPreeditPosition: libc::c_long = 0x0004; @@ -1348,6 +1357,7 @@ extern "C" { pub fn XDestroyWindow(display: *mut Display, w: Window); pub fn XFilterEvent(event: *mut XEvent, w: Window) -> Bool; pub fn XFlush(display: *mut Display); + pub fn XFree(data: *const libc::c_void); pub fn XGetGeometry(display: *mut Display, d: Drawable, root_return: *mut Window, x_return: *mut libc::c_int, y_return: *mut libc::c_int, width_return: *mut libc::c_uint, height_return: *mut libc::c_uint, @@ -1384,12 +1394,15 @@ extern "C" { pub fn glXCreateContext(dpy: *mut Display, vis: *const XVisualInfo, shareList: GLXContext, direct: Bool) -> GLXContext; + pub fn glXCreateNewContext(dpy: *mut Display, config: GLXFBConfig, render_type: libc::c_int, + shareList: GLXContext, direct: Bool) -> GLXContext; pub fn glXDestroyContext(dpy: *mut Display, ctx: GLXContext); pub fn glXChooseFBConfig(dpy: *mut Display, screen: libc::c_int, - attrib_list: *const libc::c_int, nelements: *mut libc::c_int); + attrib_list: *const libc::c_int, nelements: *mut libc::c_int) -> *mut GLXFBConfig; pub fn glXChooseVisual(dpy: *mut Display, screen: libc::c_int, attribList: *const libc::c_int) -> *const XVisualInfo; pub fn glXGetProcAddress(procName: *const libc::c_uchar) -> *const (); + pub fn glXGetVisualFromFBConfig(dpy: *mut Display, config: GLXFBConfig) -> *mut XVisualInfo; pub fn glXMakeCurrent(dpy: *mut Display, drawable: GLXDrawable, ctx: GLXContext) -> Bool; pub fn glXSwapBuffers(dpy: *mut Display, drawable: GLXDrawable); @@ -1398,7 +1411,6 @@ extern "C" { /* GLXFBConfig *glXGetFBConfigs (Display *dpy, int screen, int *nelements); int glXGetFBConfigAttrib (Display *dpy, GLXFBConfig config, int attribute, int *value); -XVisualInfo *glXGetVisualFromFBConfig (Display *dpy, GLXFBConfig config); GLXWindow glXCreateWindow (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list); void glXDestroyWindow (Display *dpy, GLXWindow win); GLXPixmap glXCreatePixmap (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list); diff --git a/src/x11/mod.rs b/src/x11/mod.rs index 0311b9a..d2619c9 100644 --- a/src/x11/mod.rs +++ b/src/x11/mod.rs @@ -40,7 +40,6 @@ impl Window { pub fn new(builder: WindowBuilder) -> Result<Window, String> { // TODO: temporary let dimensions = builder.dimensions; - let title = builder.title.as_slice(); // calling XOpenDisplay let display = unsafe { @@ -51,23 +50,46 @@ impl Window { display }; - // TODO: set error handler - - static VISUAL_ATTRIBUTES: [libc::c_int, ..5] = [ - ffi::GLX_RGBA, - ffi::GLX_DEPTH_SIZE, - 24, - ffi::GLX_DOUBLEBUFFER, - 0 - ]; + // TODO: set error handler? + + // getting the FBConfig + let fb_config = unsafe { + static VISUAL_ATTRIBUTES: [libc::c_int, ..23] = [ + ffi::GLX_X_RENDERABLE, 1, + ffi::GLX_DRAWABLE_TYPE, ffi::GLX_WINDOW_BIT, + ffi::GLX_RENDER_TYPE, ffi::GLX_RGBA_BIT, + ffi::GLX_X_VISUAL_TYPE, ffi::GLX_TRUE_COLOR, + ffi::GLX_RED_SIZE, 8, + ffi::GLX_GREEN_SIZE, 8, + ffi::GLX_BLUE_SIZE, 8, + ffi::GLX_ALPHA_SIZE, 8, + ffi::GLX_DEPTH_SIZE, 24, + ffi::GLX_STENCIL_SIZE, 8, + ffi::GLX_DOUBLEBUFFER, 1, + 0 + ]; + + let mut num_fb: libc::c_int = mem::uninitialized(); + + let fb = ffi::glXChooseFBConfig(display, ffi::XDefaultScreen(display), + VISUAL_ATTRIBUTES.as_ptr(), &mut num_fb); + if fb.is_null() { + return Err(format!("glXChooseFBConfig failed")); + } + let preferred_fb = *fb; // TODO: choose more wisely + ffi::XFree(fb as *const libc::c_void); + preferred_fb + }; // getting the visual infos let visual_infos = unsafe { - let vi = ffi::glXChooseVisual(display, 0, VISUAL_ATTRIBUTES.as_ptr()); + let vi = ffi::glXGetVisualFromFBConfig(display, fb_config); if vi.is_null() { return Err(format!("glXChooseVisual failed")); } - vi + let vi_copy = *vi; + ffi::XFree(vi as *const libc::c_void); + vi_copy }; // getting the root window @@ -76,7 +98,7 @@ impl Window { // creating the color map let cmap = unsafe { let cmap = ffi::XCreateColormap(display, root, - (*visual_infos).visual, ffi::AllocNone); + visual_infos.visual, ffi::AllocNone); // TODO: error checking? cmap }; @@ -97,8 +119,8 @@ impl Window { let dimensions = dimensions.unwrap_or((800, 600)); let win = ffi::XCreateWindow(display, root, 50, 50, dimensions.val0() as libc::c_uint, - dimensions.val1() as libc::c_uint, 0, (*visual_infos).depth, ffi::InputOutput, - (*visual_infos).visual, ffi::CWColormap | ffi::CWEventMask, + dimensions.val1() as libc::c_uint, 0, visual_infos.depth, ffi::InputOutput, + visual_infos.visual, ffi::CWColormap | ffi::CWEventMask, &mut set_win_attr); win }; @@ -111,13 +133,30 @@ impl Window { let mut wm_delete_window = ffi::XInternAtom(display, "WM_DELETE_WINDOW".to_c_str().as_ptr() as *const libc::c_char, 0); ffi::XSetWMProtocols(display, window, &mut wm_delete_window, 1); - ffi::XStoreName(display, window, mem::transmute(title.as_slice().as_ptr())); + ffi::XStoreName(display, window, mem::transmute(builder.title.as_slice().as_ptr())); ffi::XFlush(display); wm_delete_window }; - // creating + // getting the pointer to glXCreateContextAttribs + let create_context_attribs = unsafe { + let mut addr = unsafe { ffi::glXGetProcAddress(b"glXCreateContextAttribs".as_ptr() + as *const u8) } as *const (); + + if addr.is_null() { + addr = unsafe { ffi::glXGetProcAddress(b"glXCreateContextAttribsARB".as_ptr() + as *const u8) } as *const (); + } + + addr.to_option().map(|addr| { + let addr: extern "system" fn(*mut ffi::Display, ffi::GLXFBConfig, ffi::GLXContext, + ffi::Bool, *const libc::c_int) -> ffi::GLXContext = unsafe { mem::transmute(addr) }; + addr + }) + }; + + // creating IM let im = unsafe { let im = ffi::XOpenIM(display, ptr::null(), ptr::mut_null(), ptr::mut_null()); if im.is_null() { @@ -142,7 +181,31 @@ impl Window { // creating GL context let context = unsafe { - ffi::glXCreateContext(display, visual_infos, ptr::null(), 1) + let mut attributes = Vec::new(); + + if builder.gl_version.is_some() { + let version = builder.gl_version.as_ref().unwrap(); + attributes.push(ffi::GLX_CONTEXT_MAJOR_VERSION); + attributes.push(version.val0() as libc::c_int); + attributes.push(ffi::GLX_CONTEXT_MINOR_VERSION); + attributes.push(version.val1() as libc::c_int); + } + + attributes.push(0); + + let context = if create_context_attribs.is_some() { + let create_context_attribs = create_context_attribs.unwrap(); + create_context_attribs(display, fb_config, ptr::null(), 1, + attributes.as_ptr()) + } else { + ffi::glXCreateNewContext(display, fb_config, ffi::GLX_RGBA_TYPE, ptr::null(), 1) + }; + + if context.is_null() { + return Err(format!("GL context creation failed")); + } + + context }; // returning |