aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml3
-rw-r--r--build.rs2
-rw-r--r--examples/vsync.rs46
-rw-r--r--src/x11/window/mod.rs47
4 files changed, 96 insertions, 2 deletions
diff --git a/Cargo.toml b/Cargo.toml
index b7a148c..a277291 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,6 +23,9 @@ gl_common = "*"
gl_generator = "*"
khronos_api = "*"
+[dev-dependencies]
+clock_ticks = "*"
+
[target.arm-linux-androideabi.dependencies.android_glue]
git = "https://github.com/tomaka/android-rs-glue"
diff --git a/build.rs b/build.rs
index f49b47f..15a0f6d 100644
--- a/build.rs
+++ b/build.rs
@@ -39,6 +39,8 @@ fn main() {
khronos_api::GLX_XML,
vec![
"GLX_ARB_create_context".to_string(),
+ "GLX_EXT_swap_control".to_string(),
+ "GLX_SGI_swap_control".to_string()
],
"1.4", "core", &mut file).unwrap();
}
diff --git a/examples/vsync.rs b/examples/vsync.rs
new file mode 100644
index 0000000..ec9ea79
--- /dev/null
+++ b/examples/vsync.rs
@@ -0,0 +1,46 @@
+#[cfg(target_os = "android")]
+#[macro_use]
+extern crate android_glue;
+
+extern crate clock_ticks;
+extern crate glutin;
+
+mod support;
+
+#[cfg(target_os = "android")]
+android_start!(main);
+
+#[cfg(not(feature = "window"))]
+fn main() { println!("This example requires glutin to be compiled with the `window` feature"); }
+
+#[cfg(feature = "window")]
+fn resize_callback(width: u32, height: u32) {
+ println!("Window resized to {}x{}", width, height);
+}
+
+#[cfg(feature = "window")]
+fn main() {
+ println!("Vsync example. This example may panic if your driver or your system forces \
+ you out of vsync. This is intended when `build_strict` is used.");
+
+ let mut window = glutin::WindowBuilder::new().with_vsync().build_strict().unwrap();
+ window.set_window_resize_callback(Some(resize_callback as fn(u32, u32)));
+ unsafe { window.make_current() };
+
+ let context = support::load(&window);
+
+ while !window.is_closed() {
+ let before = clock_ticks::precise_time_ns();
+
+ context.draw_frame((0.0, 1.0, 0.0, 1.0));
+ window.swap_buffers();
+
+ for ev in window.poll_events() {
+ println!("{:?}", ev);
+ }
+
+ let after = clock_ticks::precise_time_ns();
+ println!("Vsync example - Time of previous frame: {}ms",
+ (after - before) as f32 / 1000000.0);
+ }
+}
diff --git a/src/x11/window/mod.rs b/src/x11/window/mod.rs
index f4c296a..d3c5163 100644
--- a/src/x11/window/mod.rs
+++ b/src/x11/window/mod.rs
@@ -298,7 +298,7 @@ impl Window {
// creating GL context
- let context = unsafe {
+ let (context, extra_functions) = unsafe {
let mut attributes = Vec::new();
if builder.gl_version.is_some() {
@@ -345,9 +345,52 @@ impl Window {
return Err(OsError(format!("GL context creation failed")));
}
- context
+ (context, extra_functions)
};
+ // vsync
+ if builder.vsync {
+ unsafe { ffi::glx::MakeCurrent(display, window, context) };
+
+ if extra_functions.SwapIntervalEXT.is_loaded() {
+ // this should be the most common extension
+ unsafe {
+ extra_functions.SwapIntervalEXT(display as *mut _, window, 1);
+ }
+
+ // checking that it worked
+ if builder.strict {
+ let mut swap = unsafe { mem::uninitialized() };
+ unsafe {
+ ffi::glx::QueryDrawable(display, window,
+ ffi::glx_extra::SWAP_INTERVAL_EXT as i32,
+ &mut swap);
+ }
+
+ if swap != 1 {
+ return Err(OsError(format!("Couldn't setup vsync: expected \
+ interval `1` but got `{}`", swap)));
+ }
+ }
+
+ // GLX_MESA_swap_control is not official
+ /*} else if extra_functions.SwapIntervalMESA.is_loaded() {
+ unsafe {
+ extra_functions.SwapIntervalMESA(1);
+ }*/
+
+ } else if extra_functions.SwapIntervalSGI.is_loaded() {
+ unsafe {
+ extra_functions.SwapIntervalSGI(1);
+ }
+
+ } else if builder.strict {
+ return Err(OsError(format!("Couldn't find any available vsync extension")));
+ }
+
+ unsafe { ffi::glx::MakeCurrent(display, 0, ptr::null()) };
+ }
+
// creating the window object
let window = Window {
x: Arc::new(XWindow {