aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/win32
diff options
context:
space:
mode:
authorPierre Krieger <pierre.krieger1708@gmail.com>2015-05-21 18:59:30 +0200
committerPierre Krieger <pierre.krieger1708@gmail.com>2015-05-21 18:59:30 +0200
commit01ecd24fe2dff3c81bfa57e76ebab9a05048e246 (patch)
treee15a00f7e7e15d016f052ec2f3dd47a3ae40ba92 /src/api/win32
parente606281862dfd016051e2ee66e67eddb71c6d0ac (diff)
downloadglutin-01ecd24fe2dff3c81bfa57e76ebab9a05048e246.tar.gz
glutin-01ecd24fe2dff3c81bfa57e76ebab9a05048e246.zip
Allow creating EGL contexts on win32 with the AMD DLLs
Diffstat (limited to 'src/api/win32')
-rw-r--r--src/api/win32/init.rs90
-rw-r--r--src/api/win32/mod.rs48
2 files changed, 117 insertions, 21 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() {
diff --git a/src/api/win32/mod.rs b/src/api/win32/mod.rs
index ff42408..af339c5 100644
--- a/src/api/win32/mod.rs
+++ b/src/api/win32/mod.rs
@@ -26,6 +26,10 @@ use user32;
use kernel32;
use api::wgl;
+use api::wgl::Context as WglContext;
+use api::egl::Context as EglContext;
+
+use self::init::RawContext;
mod callback;
mod event;
@@ -38,7 +42,7 @@ pub struct Window {
window: WindowWrapper,
/// OpenGL context.
- context: wgl::Context,
+ context: Context,
/// Receiver for the events dispatched by the window callback.
events_receiver: Receiver<Event>,
@@ -53,6 +57,11 @@ pub struct Window {
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
+enum Context {
+ Egl(EglContext),
+ Wgl(WglContext),
+}
+
/// A simple wrapper that destroys the window when it is destroyed.
// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)
#[doc(hidden)]
@@ -79,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| w.context.get_hglrc());
+
+ 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)
}
@@ -302,27 +316,45 @@ impl Window {
impl GlContext for Window {
unsafe fn make_current(&self) {
- self.context.make_current()
+ match self.context {
+ Context::Wgl(ref c) => c.make_current(),
+ Context::Egl(ref c) => c.make_current(),
+ }
}
fn is_current(&self) -> bool {
- self.context.is_current()
+ 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 {
- self.context.get_proc_address(addr)
+ 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) {
- self.context.swap_buffers()
+ match self.context {
+ Context::Wgl(ref c) => c.swap_buffers(),
+ Context::Egl(ref c) => c.swap_buffers(),
+ }
}
fn get_api(&self) -> Api {
- self.context.get_api()
+ match self.context {
+ Context::Wgl(ref c) => c.get_api(),
+ Context::Egl(ref c) => c.get_api(),
+ }
}
fn get_pixel_format(&self) -> PixelFormat {
- self.context.get_pixel_format()
+ match self.context {
+ Context::Wgl(ref c) => c.get_pixel_format(),
+ Context::Egl(ref c) => c.get_pixel_format(),
+ }
}
}