diff options
author | tomaka <pierre.krieger1708@gmail.com> | 2015-05-21 19:37:10 +0200 |
---|---|---|
committer | tomaka <pierre.krieger1708@gmail.com> | 2015-05-21 19:37:10 +0200 |
commit | 4824333453bfe6f91cdb6eefdd58ef112ef965ab (patch) | |
tree | e15a00f7e7e15d016f052ec2f3dd47a3ae40ba92 /src/api/win32/init.rs | |
parent | e606281862dfd016051e2ee66e67eddb71c6d0ac (diff) | |
parent | 01ecd24fe2dff3c81bfa57e76ebab9a05048e246 (diff) | |
download | glutin-4824333453bfe6f91cdb6eefdd58ef112ef965ab.tar.gz glutin-4824333453bfe6f91cdb6eefdd58ef112ef965ab.zip |
Merge pull request #459 from tomaka/win32-egl-2
Allow creating EGL contexts on win32 with the AMD DLLs
Diffstat (limited to 'src/api/win32/init.rs')
-rw-r--r-- | src/api/win32/init.rs | 90 |
1 files changed, 77 insertions, 13 deletions
diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index 9223105..fb4e181 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -4,18 +4,22 @@ 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::WindowWrapper; +use super::Context; +use Api; use BuilderAttribs; use CreationError; use CreationError::OsError; use CursorState; +use GlRequest; -use std::ffi::OsStr; +use std::ffi::{CString, OsStr}; use std::os::windows::ffi::OsStrExt; use std::sync::mpsc::channel; @@ -23,17 +27,22 @@ use winapi; use kernel32; use user32; -use api::wgl::{self, Context}; +use api::wgl; +use api::wgl::Context as WglContext; +use api::egl; +use api::egl::Context as EglContext; -/// Work-around the fact that HGLRC doesn't implement Send -struct ContextHack(winapi::HGLRC); -unsafe impl Send for ContextHack {} +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<winapi::HGLRC>) +pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<RawContext>) -> Result<Window, CreationError> { - let builder_sharelists = builder_sharelists.map(|s| ContextHack(s)); - // initializing variables to be sent to the task let title = OsStr::new(&builder.title).encode_wide().chain(Some(0).into_iter()) @@ -73,10 +82,8 @@ pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<w } 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(); @@ -147,8 +154,65 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>, WindowWrapper(handle, hdc) }; - // - let context = try!(wgl::Context::new(&builder, real_window.0, builder_sharelists)); + // 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 { + "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)) + } + }, + _ => { + 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)) + } + }; // calling SetForegroundWindow if fullscreen if builder.monitor.is_some() { |