aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/x11/ffi.rs18
-rw-r--r--src/x11/mod.rs99
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