aboutsummaryrefslogtreecommitdiffstats
path: root/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/api')
-rw-r--r--src/api/android/mod.rs2
-rw-r--r--src/api/egl/mod.rs4
-rw-r--r--src/api/mod.rs1
-rw-r--r--src/api/wayland/mod.rs2
-rw-r--r--src/api/wgl/gl.rs (renamed from src/api/win32/gl.rs)0
-rw-r--r--src/api/wgl/make_current_guard.rs (renamed from src/api/win32/make_current_guard.rs)9
-rw-r--r--src/api/wgl/mod.rs537
-rw-r--r--src/api/win32/init.rs444
-rw-r--r--src/api/win32/mod.rs79
-rw-r--r--src/api/x11/window.rs6
10 files changed, 657 insertions, 427 deletions
diff --git a/src/api/android/mod.rs b/src/api/android/mod.rs
index 9a98322..d1281e3 100644
--- a/src/api/android/mod.rs
+++ b/src/api/android/mod.rs
@@ -110,7 +110,7 @@ impl Window {
return Err(OsError(format!("Android's native window is null")));
}
- let context = try!(EglContext::new(egl::ffi::egl::Egl, builder, None,
+ let context = try!(EglContext::new(egl::ffi::egl::Egl, &builder, None,
native_window as *const _));
let (tx, rx) = channel();
diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs
index a97ef62..3335de0 100644
--- a/src/api/egl/mod.rs
+++ b/src/api/egl/mod.rs
@@ -1,4 +1,4 @@
-#![cfg(any(target_os = "linux", target_os = "android"))]
+#![cfg(any(target_os = "windows", target_os = "linux", target_os = "android"))]
#![allow(unused_variables)]
use BuilderAttribs;
@@ -24,7 +24,7 @@ pub struct Context {
}
impl Context {
- pub fn new(egl: ffi::egl::Egl, builder: BuilderAttribs,
+ pub fn new(egl: ffi::egl::Egl, builder: &BuilderAttribs,
native_display: Option<ffi::EGLNativeDisplayType>,
native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError>
{
diff --git a/src/api/mod.rs b/src/api/mod.rs
index fe43616..db5590a 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -7,5 +7,6 @@ pub mod emscripten;
pub mod glx;
pub mod osmesa;
pub mod wayland;
+pub mod wgl;
pub mod win32;
pub mod x11;
diff --git a/src/api/wayland/mod.rs b/src/api/wayland/mod.rs
index 8a4b5cc..b9bfa18 100644
--- a/src/api/wayland/mod.rs
+++ b/src/api/wayland/mod.rs
@@ -165,7 +165,7 @@ impl Window {
});
try!(EglContext::new(
egl,
- builder,
+ &builder,
Some(wayland_context.display.ptr() as *const _),
(*shell_surface).ptr() as *const _
))
diff --git a/src/api/win32/gl.rs b/src/api/wgl/gl.rs
index 1354d95..1354d95 100644
--- a/src/api/win32/gl.rs
+++ b/src/api/wgl/gl.rs
diff --git a/src/api/win32/make_current_guard.rs b/src/api/wgl/make_current_guard.rs
index 8983899..b890c82 100644
--- a/src/api/win32/make_current_guard.rs
+++ b/src/api/wgl/make_current_guard.rs
@@ -6,9 +6,6 @@ use winapi;
use CreationError;
use super::gl;
-use super::ContextWrapper;
-use super::WindowWrapper;
-
/// A guard for when you want to make the context current. Destroying the guard restores the
/// previously-current context.
pub struct CurrentContextGuard<'a, 'b> {
@@ -19,15 +16,13 @@ pub struct CurrentContextGuard<'a, 'b> {
}
impl<'a, 'b> CurrentContextGuard<'a, 'b> {
- pub unsafe fn make_current(window: &'a WindowWrapper, context: &'b ContextWrapper)
+ pub unsafe fn make_current(hdc: winapi::HDC, context: winapi::HGLRC)
-> Result<CurrentContextGuard<'a, 'b>, CreationError>
{
let previous_hdc = gl::wgl::GetCurrentDC() as winapi::HDC;
let previous_hglrc = gl::wgl::GetCurrentContext() as winapi::HGLRC;
- let result = gl::wgl::MakeCurrent(window.1 as *const libc::c_void,
- context.0 as *const libc::c_void);
-
+ let result = gl::wgl::MakeCurrent(hdc as *const _, context as *const _);
if result == 0 {
return Err(CreationError::OsError(format!("wglMakeCurrent function failed: {}",
format!("{}", io::Error::last_os_error()))));
diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs
new file mode 100644
index 0000000..d1f42d2
--- /dev/null
+++ b/src/api/wgl/mod.rs
@@ -0,0 +1,537 @@
+#![cfg(any(target_os = "windows"))]
+
+use BuilderAttribs;
+use CreationError;
+use GlContext;
+use GlRequest;
+use GlProfile;
+use PixelFormat;
+use Api;
+
+use self::make_current_guard::CurrentContextGuard;
+
+use libc;
+use std::ffi::{CStr, CString, OsStr};
+use std::os::windows::ffi::OsStrExt;
+use std::{mem, ptr};
+use std::io;
+
+use winapi;
+use kernel32;
+use user32;
+use gdi32;
+
+mod make_current_guard;
+mod gl;
+
+/// A WGL context.
+///
+/// Note: should be destroyed before its window.
+pub struct Context {
+ context: ContextWrapper,
+
+ hdc: winapi::HDC,
+
+ /// Binded to `opengl32.dll`.
+ ///
+ /// `wglGetProcAddress` returns null for GL 1.1 functions because they are
+ /// already defined by the system. This module contains them.
+ gl_library: winapi::HMODULE,
+
+ /// The pixel format that has been used to create this context.
+ pixel_format: PixelFormat,
+}
+
+/// A simple wrapper that destroys the window when it is destroyed.
+struct WindowWrapper(winapi::HWND, winapi::HDC);
+
+impl Drop for WindowWrapper {
+ fn drop(&mut self) {
+ unsafe {
+ user32::DestroyWindow(self.0);
+ }
+ }
+}
+
+/// Wraps around a context so that it is destroyed when necessary.
+struct ContextWrapper(winapi::HGLRC);
+
+impl Drop for ContextWrapper {
+ fn drop(&mut self) {
+ unsafe {
+ gl::wgl::DeleteContext(self.0 as *const _);
+ }
+ }
+}
+
+impl Context {
+ /// Attempt to build a new WGL context on a window.
+ ///
+ /// The window must **not** have had `SetPixelFormat` called on it.
+ ///
+ /// # Unsafety
+ ///
+ /// The `window` must continue to exist as long as the resulting `Context` exists.
+ pub unsafe fn new(builder: &BuilderAttribs<'static>, window: winapi::HWND,
+ builder_sharelists: Option<winapi::HGLRC>)
+ -> Result<Context, CreationError>
+ {
+ let hdc = user32::GetDC(window);
+ if hdc.is_null() {
+ let err = Err(CreationError::OsError(format!("GetDC function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ return err;
+ }
+
+ // loading the functions that are not guaranteed to be supported
+ let extra_functions = try!(load_extra_functions(window));
+
+ // getting the list of the supported extensions
+ let extensions = if extra_functions.GetExtensionsStringARB.is_loaded() {
+ let data = extra_functions.GetExtensionsStringARB(hdc as *const _);
+ let data = CStr::from_ptr(data).to_bytes().to_vec();
+ String::from_utf8(data).unwrap()
+
+ } else if extra_functions.GetExtensionsStringEXT.is_loaded() {
+ let data = extra_functions.GetExtensionsStringEXT();
+ let data = CStr::from_ptr(data).to_bytes().to_vec();
+ String::from_utf8(data).unwrap()
+
+ } else {
+ format!("")
+ };
+
+ // calling SetPixelFormat
+ let pixel_format = {
+ let formats = if extensions.split(' ').find(|&i| i == "WGL_ARB_pixel_format")
+ .is_some()
+ {
+ let f = enumerate_arb_pixel_formats(&extra_functions, &extensions, hdc);
+ if f.is_empty() {
+ enumerate_native_pixel_formats(hdc)
+ } else {
+ f
+ }
+ } else {
+ enumerate_native_pixel_formats(hdc)
+ };
+
+ let (id, f) = try!(builder.choose_pixel_format(formats));
+ try!(set_pixel_format(hdc, id));
+ f
+ };
+
+ // creating the OpenGL context
+ let context = try!(create_context(Some((&extra_functions, builder, &extensions)),
+ window, hdc, builder_sharelists));
+
+ // loading the opengl32 module
+ let gl_library = try!(load_opengl32_dll());
+
+ // handling vsync
+ if builder.vsync {
+ // contrary to most extensions, it is permitted to discover the presence of
+ // `WGL_EXT_swap_control` by seeing if the function pointer is available
+ if extra_functions.SwapIntervalEXT.is_loaded() {
+ let _guard = try!(CurrentContextGuard::make_current(hdc, context.0));
+
+ if extra_functions.SwapIntervalEXT(1) == 0 {
+ return Err(CreationError::OsError(format!("wglSwapIntervalEXT failed")));
+ }
+ }
+ }
+
+ Ok(Context {
+ context: context,
+ hdc: hdc,
+ gl_library: gl_library,
+ pixel_format: pixel_format,
+ })
+ }
+
+ /// Returns the raw HGLRC.
+ pub fn get_hglrc(&self) -> winapi::HGLRC {
+ self.context.0
+ }
+}
+
+impl GlContext for Context {
+ unsafe fn make_current(&self) {
+ // TODO: check return value
+ gl::wgl::MakeCurrent(self.hdc as *const _, self.context.0 as *const _);
+ }
+
+ fn is_current(&self) -> bool {
+ unsafe { gl::wgl::GetCurrentContext() == self.context.0 as *const libc::c_void }
+ }
+
+ fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
+ let addr = CString::new(addr.as_bytes()).unwrap();
+ let addr = addr.as_ptr();
+
+ unsafe {
+ let p = gl::wgl::GetProcAddress(addr) as *const _;
+ if !p.is_null() { return p; }
+ kernel32::GetProcAddress(self.gl_library, addr) as *const _
+ }
+ }
+
+ fn swap_buffers(&self) {
+ unsafe {
+ gdi32::SwapBuffers(self.hdc);
+ }
+ }
+
+ fn get_api(&self) -> Api {
+ // FIXME: can be opengl es
+ Api::OpenGl
+ }
+
+ fn get_pixel_format(&self) -> PixelFormat {
+ self.pixel_format.clone()
+ }
+}
+
+unsafe impl Send for Context {}
+unsafe impl Sync for Context {}
+
+/// Creates an OpenGL context.
+///
+/// If `extra` is `Some`, this function will attempt to use the latest WGL functions to create the
+/// context.
+///
+/// Otherwise, only the basic API will be used and the chances of `CreationError::NotSupported`
+/// being returned increase.
+unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'static>, &str)>,
+ _: winapi::HWND, hdc: winapi::HDC, share: Option<winapi::HGLRC>)
+ -> Result<ContextWrapper, CreationError>
+{
+ let share = share.unwrap_or(ptr::null_mut());
+
+ let ctxt = if let Some((extra_functions, builder, extensions)) = extra {
+ if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context").is_some() {
+ let mut attributes = Vec::new();
+
+ match builder.gl_version {
+ GlRequest::Latest => {},
+ GlRequest::Specific(Api::OpenGl, (major, minor)) => {
+ attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
+ attributes.push(major as libc::c_int);
+ attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
+ attributes.push(minor as libc::c_int);
+ },
+ GlRequest::Specific(Api::OpenGlEs, (major, minor)) => {
+ if extensions.split(' ').find(|&i| i == "WGL_EXT_create_context_es2_profile")
+ .is_some()
+ {
+ attributes.push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int);
+ attributes.push(gl::wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT as libc::c_int);
+ } else {
+ return Err(CreationError::NotSupported);
+ }
+
+ attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
+ attributes.push(major as libc::c_int);
+ attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
+ attributes.push(minor as libc::c_int);
+ },
+ GlRequest::Specific(_, _) => return Err(CreationError::NotSupported),
+ GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
+ attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
+ attributes.push(major as libc::c_int);
+ attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
+ attributes.push(minor as libc::c_int);
+ },
+ }
+
+ if let Some(profile) = builder.gl_profile {
+ if extensions.split(' ').find(|&i| i == "WGL_ARB_create_context_profile").is_some()
+ {
+ let flag = match profile {
+ GlProfile::Compatibility =>
+ gl::wgl_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ GlProfile::Core =>
+ gl::wgl_extra::CONTEXT_CORE_PROFILE_BIT_ARB,
+ };
+ attributes.push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int);
+ attributes.push(flag as libc::c_int);
+ } else {
+ return Err(CreationError::NotSupported);
+ }
+ }
+
+ if builder.gl_debug {
+ attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int);
+ attributes.push(gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int);
+ }
+
+ attributes.push(0);
+
+ Some(extra_functions.CreateContextAttribsARB(hdc as *const libc::c_void,
+ share as *const libc::c_void,
+ attributes.as_ptr()))
+
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ let ctxt = match ctxt {
+ Some(ctxt) => ctxt,
+ None => {
+ let ctxt = gl::wgl::CreateContext(hdc as *const libc::c_void);
+ if !ctxt.is_null() && !share.is_null() {
+ gl::wgl::ShareLists(share as *const libc::c_void, ctxt);
+ };
+ ctxt
+ }
+ };
+
+ if ctxt.is_null() {
+ return Err(CreationError::OsError(format!("OpenGL context creation failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ Ok(ContextWrapper(ctxt as winapi::HGLRC))
+}
+
+/// Enumerates the list of pixel formats without using WGL.
+///
+/// Gives less precise results than `enumerate_arb_pixel_formats`.
+unsafe fn enumerate_native_pixel_formats(hdc: winapi::HDC) -> Vec<(libc::c_int, PixelFormat)> {
+ let size_of_pxfmtdescr = mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u32;
+ let num = gdi32::DescribePixelFormat(hdc, 1, size_of_pxfmtdescr, ptr::null_mut());
+
+ let mut result = Vec::new();
+
+ for index in (0 .. num) {
+ let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
+
+ if gdi32::DescribePixelFormat(hdc, index, size_of_pxfmtdescr, &mut output) == 0 {
+ continue;
+ }
+
+ if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 {
+ continue;
+ }
+
+ if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 {
+ continue;
+ }
+
+ if output.iPixelType != winapi::PFD_TYPE_RGBA {
+ continue;
+ }
+
+ result.push((index, PixelFormat {
+ hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0,
+ color_bits: output.cRedBits + output.cGreenBits + output.cBlueBits,
+ alpha_bits: output.cAlphaBits,
+ depth_bits: output.cDepthBits,
+ stencil_bits: output.cStencilBits,
+ stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0,
+ double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0,
+ multisampling: None,
+ srgb: false,
+ }));
+ }
+
+ result
+}
+
+/// Enumerates the list of pixel formats by using extra WGL functions.
+///
+/// Gives more precise results than `enumerate_native_pixel_formats`.
+unsafe fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, extensions: &str,
+ hdc: winapi::HDC) -> Vec<(libc::c_int, PixelFormat)>
+{
+ let get_info = |index: u32, attrib: u32| {
+ let mut value = mem::uninitialized();
+ extra.GetPixelFormatAttribivARB(hdc as *const _, index as libc::c_int,
+ 0, 1, [attrib as libc::c_int].as_ptr(),
+ &mut value);
+ value as u32
+ };
+
+ // getting the number of formats
+ // the `1` is ignored
+ let num = get_info(1, gl::wgl_extra::NUMBER_PIXEL_FORMATS_ARB);
+
+ let mut result = Vec::new();
+
+ for index in (0 .. num) {
+ if get_info(index, gl::wgl_extra::DRAW_TO_WINDOW_ARB) == 0 {
+ continue;
+ }
+ if get_info(index, gl::wgl_extra::SUPPORT_OPENGL_ARB) == 0 {
+ continue;
+ }
+
+ if get_info(index, gl::wgl_extra::ACCELERATION_ARB) == gl::wgl_extra::NO_ACCELERATION_ARB {
+ continue;
+ }
+
+ if get_info(index, gl::wgl_extra::PIXEL_TYPE_ARB) != gl::wgl_extra::TYPE_RGBA_ARB {
+ continue;
+ }
+
+ result.push((index as libc::c_int, PixelFormat {
+ hardware_accelerated: true,
+ color_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8 +
+ get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8 +
+ get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8,
+ alpha_bits: get_info(index, gl::wgl_extra::ALPHA_BITS_ARB) as u8,
+ depth_bits: get_info(index, gl::wgl_extra::DEPTH_BITS_ARB) as u8,
+ stencil_bits: get_info(index, gl::wgl_extra::STENCIL_BITS_ARB) as u8,
+ stereoscopy: get_info(index, gl::wgl_extra::STEREO_ARB) != 0,
+ double_buffer: get_info(index, gl::wgl_extra::DOUBLE_BUFFER_ARB) != 0,
+ multisampling: {
+ if extensions.split(' ').find(|&i| i == "WGL_ARB_multisample").is_some() {
+ match get_info(index, gl::wgl_extra::SAMPLES_ARB) {
+ 0 => None,
+ a => Some(a as u16),
+ }
+ } else {
+ None
+ }
+ },
+ srgb: if extensions.split(' ').find(|&i| i == "WGL_ARB_framebuffer_sRGB").is_some() {
+ get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0
+ } else if extensions.split(' ').find(|&i| i == "WGL_EXT_framebuffer_sRGB").is_some() {
+ get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT) != 0
+ } else {
+ false
+ },
+ }));
+ }
+
+ result
+}
+
+/// Calls `SetPixelFormat` on a window.
+unsafe fn set_pixel_format(hdc: winapi::HDC, id: libc::c_int) -> Result<(), CreationError> {
+ let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
+
+ if gdi32::DescribePixelFormat(hdc, id, mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>()
+ as winapi::UINT, &mut output) == 0
+ {
+ return Err(CreationError::OsError(format!("DescribePixelFormat function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ if gdi32::SetPixelFormat(hdc, id, &output) == 0 {
+ return Err(CreationError::OsError(format!("SetPixelFormat function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ Ok(())
+}
+
+/// Loads the `opengl32.dll` library.
+unsafe fn load_opengl32_dll() -> Result<winapi::HMODULE, CreationError> {
+ let name = OsStr::new("opengl32.dll").encode_wide().chain(Some(0).into_iter())
+ .collect::<Vec<_>>();
+
+ let lib = kernel32::LoadLibraryW(name.as_ptr());
+
+ if lib.is_null() {
+ return Err(CreationError::OsError(format!("LoadLibrary function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ Ok(lib)
+}
+
+/// Loads the WGL functions that are not guaranteed to be supported.
+///
+/// The `window` must be passed because the driver can vary depending on the window's
+/// characteristics.
+unsafe fn load_extra_functions(window: winapi::HWND) -> Result<gl::wgl_extra::Wgl, CreationError> {
+ let (ex_style, style) = (winapi::WS_EX_APPWINDOW, winapi::WS_POPUP |
+ winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN);
+
+ // creating a dummy invisible window
+ let dummy_window = {
+ // getting the rect of the real window
+ let rect = {
+ let mut placement: winapi::WINDOWPLACEMENT = mem::zeroed();
+ placement.length = mem::size_of::<winapi::WINDOWPLACEMENT>() as winapi::UINT;
+ if user32::GetWindowPlacement(window, &mut placement) == 0 {
+ panic!();
+ }
+ placement.rcNormalPosition
+ };
+
+ // getting the class name of the real window
+ let mut class_name = [0u16; 128];
+ if user32::GetClassNameW(window, class_name.as_mut_ptr(), 128) == 0 {
+ return Err(CreationError::OsError(format!("GetClassNameW function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ // this dummy window should match the real one enough to get the same OpenGL driver
+ let win = user32::CreateWindowExW(ex_style, class_name.as_ptr(),
+ b"dummy window\0".as_ptr() as *const _, style,
+ winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ ptr::null_mut(), ptr::null_mut(),
+ kernel32::GetModuleHandleW(ptr::null()),
+ ptr::null_mut());
+
+ if win.is_null() {
+ return Err(CreationError::OsError(format!("CreateWindowEx function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ }
+
+ let hdc = user32::GetDC(win);
+ if hdc.is_null() {
+ let err = Err(CreationError::OsError(format!("GetDC function failed: {}",
+ format!("{}", io::Error::last_os_error()))));
+ return err;
+ }
+
+ WindowWrapper(win, hdc)
+ };
+
+ // getting the pixel format that we will use and setting it
+ {
+ let formats = enumerate_native_pixel_formats(dummy_window.1);
+ let id = try!(choose_dummy_pixel_format(formats.into_iter()));
+ try!(set_pixel_format(dummy_window.1, id));
+ }
+
+ // creating the dummy OpenGL context and making it current
+ let dummy_context = try!(create_context(None, dummy_window.0, dummy_window.1, None));
+ let _current_context = try!(CurrentContextGuard::make_current(dummy_window.1,
+ dummy_context.0));
+
+ // loading the extra WGL functions
+ Ok(gl::wgl_extra::Wgl::load_with(|addr| {
+ let addr = CString::new(addr.as_bytes()).unwrap();
+ let addr = addr.as_ptr();
+ gl::wgl::GetProcAddress(addr) as *const libc::c_void
+ }))
+}
+
+/// Given a list of pixel formats, this function chooses one that is likely to be provided by
+/// the main video driver of the system.
+fn choose_dummy_pixel_format<I>(iter: I) -> Result<libc::c_int, CreationError>
+ where I: Iterator<Item=(libc::c_int, PixelFormat)>
+{
+ let mut backup_id = None;
+
+ for (id, format) in iter {
+ if backup_id.is_none() {
+ backup_id = Some(id);
+ }
+
+ if format.hardware_accelerated {
+ return Ok(id);
+ }
+ }
+
+ backup_id.ok_or(CreationError::NotSupported)
+}
diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs
index e5b0b3a..fb4e181 100644
--- a/src/api/win32/init.rs
+++ b/src/api/win32/init.rs
@@ -4,39 +4,43 @@ use std::io;
use std::ptr;
use std::mem;
use std::thread;
+use libc;
use super::callback;
use super::Window;
use super::MonitorID;
-use super::ContextWrapper;
use super::WindowWrapper;
-use super::make_current_guard::CurrentContextGuard;
+use super::Context;
use Api;
use BuilderAttribs;
use CreationError;
use CreationError::OsError;
use CursorState;
-use GlProfile;
use GlRequest;
-use PixelFormat;
-use std::ffi::{CStr, CString, OsStr};
+use std::ffi::{CString, OsStr};
use std::os::windows::ffi::OsStrExt;
use std::sync::mpsc::channel;
-use libc;
-use super::gl;
use winapi;
use kernel32;
use user32;
-use gdi32;
-/// Work-around the fact that HGLRC doesn't implement Send
-pub struct ContextHack(pub winapi::HGLRC);
-unsafe impl Send for ContextHack {}
+use api::wgl;
+use api::wgl::Context as WglContext;
+use api::egl;
+use api::egl::Context as EglContext;
+
+pub enum RawContext {
+ Egl(egl::ffi::egl::types::EGLContext),
+ Wgl(winapi::HGLRC),
+}
+
+unsafe impl Send for RawContext {}
+unsafe impl Sync for RawContext {}
-pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<ContextHack>)
+pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<RawContext>)
-> Result<Window, CreationError>
{
// initializing variables to be sent to the task
@@ -78,10 +82,8 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<C
}
unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
- builder_sharelists: Option<ContextHack>) -> Result<Window, CreationError>
+ builder_sharelists: Option<RawContext>) -> Result<Window, CreationError>
{
- let builder_sharelists = builder_sharelists.map(|s| s.0);
-
// registering the window class
let class_name = register_window_class();
@@ -110,57 +112,6 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
// adjusting the window coordinates using the style
user32::AdjustWindowRectEx(&mut rect, style, 0, ex_style);
- // the first step is to create a dummy window and a dummy context which we will use
- // to load the pointers to some functions in the OpenGL driver in `extra_functions`
- let extra_functions = {
- // creating a dummy invisible window
- let dummy_window = {
- let handle = user32::CreateWindowExW(ex_style, class_name.as_ptr(),
- title.as_ptr() as winapi::LPCWSTR,
- style | winapi::WS_CLIPSIBLINGS | winapi::WS_CLIPCHILDREN,
- winapi::CW_USEDEFAULT, winapi::CW_USEDEFAULT,
- rect.right - rect.left, rect.bottom - rect.top,
- ptr::null_mut(), ptr::null_mut(), kernel32::GetModuleHandleW(ptr::null()),
- ptr::null_mut());
-
- if handle.is_null() {
- return Err(OsError(format!("CreateWindowEx function failed: {}",
- format!("{}", io::Error::last_os_error()))));
- }
-
- let hdc = user32::GetDC(handle);
- if hdc.is_null() {
- let err = Err(OsError(format!("GetDC function failed: {}",
- format!("{}", io::Error::last_os_error()))));
- return err;
- }
-
- WindowWrapper(handle, hdc)
- };
-
- // getting the pixel format that we will use and setting it
- {
- let formats = enumerate_native_pixel_formats(&dummy_window);
- let id = try!(choose_dummy_pixel_format(formats.into_iter()));
- try!(set_pixel_format(&dummy_window, id));
- }
-
- // creating the dummy OpenGL context and making it current
- let dummy_context = try!(create_context(None, &dummy_window, None));
- let current_context = try!(CurrentContextGuard::make_current(&dummy_window,
- &dummy_context));
-
- // loading the extra WGL functions
- gl::wgl_extra::Wgl::load_with(|addr| {
- use libc;
-
- let addr = CString::new(addr.as_bytes()).unwrap();
- let addr = addr.as_ptr();
-
- gl::wgl::GetProcAddress(addr) as *const libc::c_void
- })
- };
-
// creating the real window this time, by using the functions in `extra_functions`
let real_window = {
let (width, height) = if builder.monitor.is_some() || builder.dimensions.is_some() {
@@ -203,28 +154,66 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
WindowWrapper(handle, hdc)
};
- // calling SetPixelFormat
- let pixel_format = {
- let formats = if extra_functions.GetPixelFormatAttribivARB.is_loaded() {
- let f = enumerate_arb_pixel_formats(&extra_functions, &real_window);
- if f.is_empty() {
- enumerate_native_pixel_formats(&real_window)
+ // creating the OpenGL context
+ let context = match builder.gl_version {
+ GlRequest::Specific(Api::OpenGlEs, (major, minor)) => {
+ // trying to load EGL from the ATI drivers
+
+ // TODO: use LoadLibraryA instead
+ let dll_name = if cfg!(target_pointer_width = "64") {
+ "atio6axx.dll"
} else {
- f
+ "atioglxx.dll"
+ };
+ let dll_name = OsStr::new(dll_name).encode_wide().chain(Some(0).into_iter())
+ .collect::<Vec<_>>();
+ let dll = unsafe { kernel32::LoadLibraryW(dll_name.as_ptr()) };
+
+ if !dll.is_null() {
+ let egl = ::api::egl::ffi::egl::Egl::load_with(|name| {
+ let name = CString::new(name).unwrap();
+ unsafe { kernel32::GetProcAddress(dll, name.as_ptr()) as *const libc::c_void }
+ });
+
+ if let Ok(c) = EglContext::new(egl, &builder, Some(ptr::null()),
+ real_window.0)
+ {
+ Context::Egl(c)
+
+ } else {
+ let builder_sharelists = match builder_sharelists {
+ None => None,
+ Some(RawContext::Wgl(c)) => Some(c),
+ _ => unimplemented!()
+ };
+
+ try!(WglContext::new(&builder, real_window.0, builder_sharelists)
+ .map(Context::Wgl))
+ }
+
+ } else {
+ // falling back to WGL, which is always available
+ let builder_sharelists = match builder_sharelists {
+ None => None,
+ Some(RawContext::Wgl(c)) => Some(c),
+ _ => unimplemented!()
+ };
+
+ try!(WglContext::new(&builder, real_window.0, builder_sharelists)
+ .map(Context::Wgl))
}
- } else {
- enumerate_native_pixel_formats(&real_window)
- };
+ },
+ _ => {
+ let builder_sharelists = match builder_sharelists {
+ None => None,
+ Some(RawContext::Wgl(c)) => Some(c),
+ _ => unimplemented!()
+ };
- let (id, f) = try!(builder.choose_pixel_format(formats.into_iter().map(|(a, b)| (b, a))));
- try!(set_pixel_format(&real_window, id));
- f
+ try!(WglContext::new(&builder, real_window.0, builder_sharelists).map(Context::Wgl))
+ }
};
- // creating the OpenGL context
- let context = try!(create_context(Some((&extra_functions, &builder)), &real_window,
- builder_sharelists));
-
// calling SetForegroundWindow if fullscreen
if builder.monitor.is_some() {
user32::SetForegroundWindow(real_window.0);
@@ -248,29 +237,13 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
rx
};
- // loading the opengl32 module
- let gl_library = try!(load_opengl32_dll());
-
- // handling vsync
- if builder.vsync {
- if extra_functions.SwapIntervalEXT.is_loaded() {
- let _guard = try!(CurrentContextGuard::make_current(&real_window, &context));
-
- if extra_functions.SwapIntervalEXT(1) == 0 {
- return Err(OsError(format!("wglSwapIntervalEXT failed")));
- }
- }
- }
-
// building the struct
Ok(Window {
window: real_window,
context: context,
- gl_library: gl_library,
events_receiver: events_receiver,
is_closed: AtomicBool::new(false),
cursor_state: cursor_state,
- pixel_format: pixel_format,
})
}
@@ -332,276 +305,3 @@ unsafe fn switch_to_fullscreen(rect: &mut winapi::RECT, monitor: &MonitorID)
Ok(())
}
-
-unsafe fn create_context(extra: Option<(&gl::wgl_extra::Wgl, &BuilderAttribs<'static>)>,
- hdc: &WindowWrapper, share: Option<winapi::HGLRC>)
- -> Result<ContextWrapper, CreationError>
-{
- let share = share.unwrap_or(ptr::null_mut());
-
- let ctxt = if let Some((extra_functions, builder)) = extra {
- if extra_functions.CreateContextAttribsARB.is_loaded() {
- let mut attributes = Vec::new();
-
- match builder.gl_version {
- GlRequest::Latest => {},
- GlRequest::Specific(Api::OpenGl, (major, minor)) => {
- attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
- attributes.push(major as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
- attributes.push(minor as libc::c_int);
- },
- GlRequest::Specific(Api::OpenGlEs, (major, minor)) => {
- if is_extension_supported(extra_functions, hdc,
- "WGL_EXT_create_context_es2_profile")
- {
- attributes.push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT as libc::c_int);
- } else {
- return Err(CreationError::NotSupported);
- }
-
- attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
- attributes.push(major as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
- attributes.push(minor as libc::c_int);
- },
- GlRequest::Specific(_, _) => return Err(CreationError::NotSupported),
- GlRequest::GlThenGles { opengl_version: (major, minor), .. } => {
- attributes.push(gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int);
- attributes.push(major as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int);
- attributes.push(minor as libc::c_int);
- },
- }
-
- if let Some(profile) = builder.gl_profile {
- if is_extension_supported(extra_functions, hdc,
- "WGL_ARB_create_context_profile")
- {
- let flag = match profile {
- GlProfile::Compatibility =>
- gl::wgl_extra::CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
- GlProfile::Core =>
- gl::wgl_extra::CONTEXT_CORE_PROFILE_BIT_ARB,
- };
- attributes.push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int);
- attributes.push(flag as libc::c_int);
- } else {
- return Err(CreationError::NotSupported);
- }
- }
-
- if builder.gl_debug {
- attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as libc::c_int);
- attributes.push(gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int);
- }
-
- attributes.push(0);
-
- Some(extra_functions.CreateContextAttribsARB(hdc.1 as *const libc::c_void,
- share as *const libc::c_void,
- attributes.as_ptr()))
-
- } else {
- None
- }
- } else {
- None
- };
-
- let ctxt = match ctxt {
- Some(ctxt) => ctxt,
- None => {
- let ctxt = gl::wgl::CreateContext(hdc.1 as *const libc::c_void);
- if !ctxt.is_null() && !share.is_null() {
- gl::wgl::ShareLists(share as *const libc::c_void, ctxt);
- };
- ctxt
- }
- };
-
- if ctxt.is_null() {
- return Err(OsError(format!("OpenGL context creation failed: {}",
- format!("{}", io::Error::last_os_error()))));
- }
-
- Ok(ContextWrapper(ctxt as winapi::HGLRC))
-}
-
-unsafe fn enumerate_native_pixel_formats(hdc: &WindowWrapper) -> Vec<(PixelFormat, libc::c_int)> {
- let size_of_pxfmtdescr = mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>() as u32;
- let num = gdi32::DescribePixelFormat(hdc.1, 1, size_of_pxfmtdescr, ptr::null_mut());
-
- let mut result = Vec::new();
-
- for index in (0 .. num) {
- let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
-
- if gdi32::DescribePixelFormat(hdc.1, index, size_of_pxfmtdescr, &mut output) == 0 {
- continue;
- }
-
- if (output.dwFlags & winapi::PFD_DRAW_TO_WINDOW) == 0 {
- continue;
- }
-
- if (output.dwFlags & winapi::PFD_SUPPORT_OPENGL) == 0 {
- continue;
- }
-
- if output.iPixelType != winapi::PFD_TYPE_RGBA {
- continue;
- }
-
- result.push((PixelFormat {
- hardware_accelerated: (output.dwFlags & winapi::PFD_GENERIC_FORMAT) == 0,
- color_bits: output.cRedBits + output.cGreenBits + output.cBlueBits,
- alpha_bits: output.cAlphaBits,
- depth_bits: output.cDepthBits,
- stencil_bits: output.cStencilBits,
- stereoscopy: (output.dwFlags & winapi::PFD_STEREO) != 0,
- double_buffer: (output.dwFlags & winapi::PFD_DOUBLEBUFFER) != 0,
- multisampling: None,
- srgb: false,
- }, index));
- }
-
- result
-}
-
-unsafe fn enumerate_arb_pixel_formats(extra: &gl::wgl_extra::Wgl, hdc: &WindowWrapper)
- -> Vec<(PixelFormat, libc::c_int)>
-{
- let get_info = |index: u32, attrib: u32| {
- let mut value = mem::uninitialized();
- extra.GetPixelFormatAttribivARB(hdc.1 as *const libc::c_void, index as libc::c_int,
- 0, 1, [attrib as libc::c_int].as_ptr(),
- &mut value);
- value as u32
- };
-
- // getting the number of formats
- // the `1` is ignored
- let num = get_info(1, gl::wgl_extra::NUMBER_PIXEL_FORMATS_ARB);
-
- let mut result = Vec::new();
-
- for index in (0 .. num) {
- if get_info(index, gl::wgl_extra::DRAW_TO_WINDOW_ARB) == 0 {
- continue;
- }
- if get_info(index, gl::wgl_extra::SUPPORT_OPENGL_ARB) == 0 {
- continue;
- }
-
- if get_info(index, gl::wgl_extra::ACCELERATION_ARB) == gl::wgl_extra::NO_ACCELERATION_ARB {
- continue;
- }
-
- if get_info(index, gl::wgl_extra::PIXEL_TYPE_ARB) != gl::wgl_extra::TYPE_RGBA_ARB {
- continue;
- }
-
- result.push((PixelFormat {
- hardware_accelerated: true,
- color_bits: get_info(index, gl::wgl_extra::RED_BITS_ARB) as u8 +
- get_info(index, gl::wgl_extra::GREEN_BITS_ARB) as u8 +
- get_info(index, gl::wgl_extra::BLUE_BITS_ARB) as u8,
- alpha_bits: get_info(index, gl::wgl_extra::ALPHA_BITS_ARB) as u8,
- depth_bits: get_info(index, gl::wgl_extra::DEPTH_BITS_ARB) as u8,
- stencil_bits: get_info(index, gl::wgl_extra::STENCIL_BITS_ARB) as u8,
- stereoscopy: get_info(index, gl::wgl_extra::STEREO_ARB) != 0,
- double_buffer: get_info(index, gl::wgl_extra::DOUBLE_BUFFER_ARB) != 0,
- multisampling: {
- if is_extension_supported(extra, hdc, "WGL_ARB_multisample") {
- match get_info(index, gl::wgl_extra::SAMPLES_ARB) {
- 0 => None,
- a => Some(a as u16),
- }
- } else {
- None
- }
- },
- srgb: if is_extension_supported(extra, hdc, "WGL_ARB_framebuffer_sRGB") {
- get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB) != 0
- } else if is_extension_supported(extra, hdc, "WGL_EXT_framebuffer_sRGB") {
- get_info(index, gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT) != 0
- } else {
- false
- },
- }, index as libc::c_int));
- }
-
- result
-}
-
-unsafe fn set_pixel_format(hdc: &WindowWrapper, id: libc::c_int) -> Result<(), CreationError> {
- let mut output: winapi::PIXELFORMATDESCRIPTOR = mem::zeroed();
-
- if gdi32::DescribePixelFormat(hdc.1, id, mem::size_of::<winapi::PIXELFORMATDESCRIPTOR>()
- as winapi::UINT, &mut output) == 0
- {
- return Err(OsError(format!("DescribePixelFormat function failed: {}",
- format!("{}", io::Error::last_os_error()))));
- }
-
- if gdi32::SetPixelFormat(hdc.1, id, &output) == 0 {
- return Err(OsError(format!("SetPixelFormat function failed: {}",
- format!("{}", io::Error::last_os_error()))));
- }
-
- Ok(())
-}
-
-unsafe fn load_opengl32_dll() -> Result<winapi::HMODULE, CreationError> {
- let name = OsStr::new("opengl32.dll").encode_wide().chain(Some(0).into_iter())
- .collect::<Vec<_>>();
-
- let lib = kernel32::LoadLibraryW(name.as_ptr());
-
- if lib.is_null() {
- return Err(OsError(format!("LoadLibrary function failed: {}",
- format!("{}", io::Error::last_os_error()))));
- }
-
- Ok(lib)
-}
-
-unsafe fn is_extension_supported(extra: &gl::wgl_extra::Wgl, hdc: &WindowWrapper,
- extension: &str) -> bool
-{
- let extensions = if extra.GetExtensionsStringARB.is_loaded() {
- let data = extra.GetExtensionsStringARB(hdc.1 as *const _);
- let data = CStr::from_ptr(data).to_bytes().to_vec();
- String::from_utf8(data).unwrap()
-
- } else if extra.GetExtensionsStringEXT.is_loaded() {
- let data = extra.GetExtensionsStringEXT();
- let data = CStr::from_ptr(data).to_bytes().to_vec();
- String::from_utf8(data).unwrap()
-
- } else {
- return false;
- };
-
- extensions.split(" ").find(|&e| e == extension).is_some()
-}
-
-fn choose_dummy_pixel_format<I>(iter: I) -> Result<libc::c_int, CreationError>
- where I: Iterator<Item=(PixelFormat, libc::c_int)>
-{
- let mut backup_id = None;
-
- for (format, id) in iter {
- if backup_id.is_none() {
- backup_id = Some(id);
- }
-
- if format.hardware_accelerated {
- return Ok(id);
- }
- }
-
- backup_id.ok_or(CreationError::NotSupported)
-}
diff --git a/src/api/win32/mod.rs b/src/api/win32/mod.rs
index d0caea7..af339c5 100644
--- a/src/api/win32/mod.rs
+++ b/src/api/win32/mod.rs
@@ -3,7 +3,6 @@
use std::sync::atomic::AtomicBool;
use std::mem;
use std::ptr;
-use std::ffi::CString;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::sync::{
@@ -25,13 +24,16 @@ pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};
use winapi;
use user32;
use kernel32;
-use gdi32;
+
+use api::wgl;
+use api::wgl::Context as WglContext;
+use api::egl::Context as EglContext;
+
+use self::init::RawContext;
mod callback;
mod event;
-mod gl;
mod init;
-mod make_current_guard;
mod monitor;
/// The Win32 implementation of the main `Window` object.
@@ -40,13 +42,7 @@ pub struct Window {
window: WindowWrapper,
/// OpenGL context.
- context: ContextWrapper,
-
- /// Binded to `opengl32.dll`.
- ///
- /// `wglGetProcAddress` returns null for GL 1.1 functions because they are
- /// already defined by the system. This module contains them.
- gl_library: winapi::HMODULE,
+ context: Context,
/// Receiver for the events dispatched by the window callback.
events_receiver: Receiver<Event>,
@@ -56,25 +52,14 @@ pub struct Window {
/// The current cursor state.
cursor_state: Arc<Mutex<CursorState>>,
-
- /// The pixel format that has been used to create this window.
- pixel_format: PixelFormat,
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
-/// A simple wrapper that destroys the context when it is destroyed.
-// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)
-#[doc(hidden)]
-pub struct ContextWrapper(pub winapi::HGLRC);
-
-impl Drop for ContextWrapper {
- fn drop(&mut self) {
- unsafe {
- gl::wgl::DeleteContext(self.0 as *const libc::c_void);
- }
- }
+enum Context {
+ Egl(EglContext),
+ Wgl(WglContext),
}
/// A simple wrapper that destroys the window when it is destroyed.
@@ -103,7 +88,12 @@ impl Window {
/// See the docs in the crate root file.
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
let (builder, sharing) = builder.extract_non_static();
- let sharing = sharing.map(|w| init::ContextHack(w.context.0));
+
+ let sharing = sharing.map(|w| match w.context {
+ Context::Wgl(ref c) => RawContext::Wgl(c.get_hglrc()),
+ Context::Egl(_) => unimplemented!(), // FIXME:
+ });
+
init::new_window(builder, sharing)
}
@@ -326,38 +316,45 @@ impl Window {
impl GlContext for Window {
unsafe fn make_current(&self) {
- // TODO: check return value
- gl::wgl::MakeCurrent(self.window.1 as *const libc::c_void,
- self.context.0 as *const libc::c_void);
+ match self.context {
+ Context::Wgl(ref c) => c.make_current(),
+ Context::Egl(ref c) => c.make_current(),
+ }
}
fn is_current(&self) -> bool {
- unsafe { gl::wgl::GetCurrentContext() == self.context.0 as *const libc::c_void }
+ match self.context {
+ Context::Wgl(ref c) => c.is_current(),
+ Context::Egl(ref c) => c.is_current(),
+ }
}
fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
- let addr = CString::new(addr.as_bytes()).unwrap();
- let addr = addr.as_ptr();
-
- unsafe {
- let p = gl::wgl::GetProcAddress(addr) as *const _;
- if !p.is_null() { return p; }
- kernel32::GetProcAddress(self.gl_library, addr) as *const _
+ match self.context {
+ Context::Wgl(ref c) => c.get_proc_address(addr),
+ Context::Egl(ref c) => c.get_proc_address(addr),
}
}
fn swap_buffers(&self) {
- unsafe {
- gdi32::SwapBuffers(self.window.1);
+ match self.context {
+ Context::Wgl(ref c) => c.swap_buffers(),
+ Context::Egl(ref c) => c.swap_buffers(),
}
}
fn get_api(&self) -> Api {
- Api::OpenGl
+ match self.context {
+ Context::Wgl(ref c) => c.get_api(),
+ Context::Egl(ref c) => c.get_api(),
+ }
}
fn get_pixel_format(&self) -> PixelFormat {
- self.pixel_format.clone()
+ match self.context {
+ Context::Wgl(ref c) => c.get_pixel_format(),
+ Context::Egl(ref c) => c.get_pixel_format(),
+ }
}
}
diff --git a/src/api/x11/window.rs b/src/api/x11/window.rs
index f5f3f2f..38838f5 100644
--- a/src/api/x11/window.rs
+++ b/src/api/x11/window.rs
@@ -202,7 +202,7 @@ impl<'a> Iterator for PollEventsIterator<'a> {
(self.window.x.display.xlib.XKeycodeToKeysym)(self.window.x.display.display, event.keycode as ffi::KeyCode, 0)
};
- if (ffi::XK_KP_Space as u64 <= keysym) && (keysym <= ffi::XK_KP_9 as u64) {
+ if (ffi::XK_KP_Space as libc::c_ulong <= keysym) && (keysym <= ffi::XK_KP_9 as libc::c_ulong) {
keysym = kp_keysym
};
@@ -523,14 +523,14 @@ impl Window {
Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window,
fb_config, visual_infos)))
} else if let Some(ref egl) = display.egl {
- Context::Egl(try!(EglContext::new(egl.clone(), builder, Some(display.display as *const _), window as *const _)))
+ Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _), window as *const _)))
} else {
return Err(CreationError::NotSupported);
}
},
GlRequest::Specific(Api::OpenGlEs, _) => {
if let Some(ref egl) = display.egl {
- Context::Egl(try!(EglContext::new(egl.clone(), builder, Some(display.display as *const _), window as *const _)))
+ Context::Egl(try!(EglContext::new(egl.clone(), &builder, Some(display.display as *const _), window as *const _)))
} else {
return Err(CreationError::NotSupported);
}