mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-25 23:01:30 +11:00
Merge pull request #459 from tomaka/win32-egl-2
Allow creating EGL contexts on win32 with the AMD DLLs
This commit is contained in:
commit
4824333453
10
build.rs
10
build.rs
|
@ -35,6 +35,16 @@ fn main() {
|
||||||
"WGL_EXT_swap_control".to_string(),
|
"WGL_EXT_swap_control".to_string(),
|
||||||
],
|
],
|
||||||
"1.0", "core", &mut file).unwrap();
|
"1.0", "core", &mut file).unwrap();
|
||||||
|
|
||||||
|
let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
|
||||||
|
gl_generator::generate_bindings(gl_generator::StructGenerator,
|
||||||
|
gl_generator::registry::Ns::Egl,
|
||||||
|
gl_generator::Fallbacks::All,
|
||||||
|
khronos_api::EGL_XML,
|
||||||
|
vec![
|
||||||
|
"EGL_KHR_create_context".to_string()
|
||||||
|
],
|
||||||
|
"1.5", "core", &mut file).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if target.contains("linux") {
|
if target.contains("linux") {
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl Window {
|
||||||
return Err(OsError(format!("Android's native window is null")));
|
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 _));
|
native_window as *const _));
|
||||||
|
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
|
@ -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)]
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
use BuilderAttribs;
|
use BuilderAttribs;
|
||||||
|
@ -24,7 +24,7 @@ pub struct Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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_display: Option<ffi::EGLNativeDisplayType>,
|
||||||
native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError>
|
native_window: ffi::EGLNativeWindowType) -> Result<Context, CreationError>
|
||||||
{
|
{
|
||||||
|
|
|
@ -165,7 +165,7 @@ impl Window {
|
||||||
});
|
});
|
||||||
try!(EglContext::new(
|
try!(EglContext::new(
|
||||||
egl,
|
egl,
|
||||||
builder,
|
&builder,
|
||||||
Some(wayland_context.display.ptr() as *const _),
|
Some(wayland_context.display.ptr() as *const _),
|
||||||
(*shell_surface).ptr() as *const _
|
(*shell_surface).ptr() as *const _
|
||||||
))
|
))
|
||||||
|
|
|
@ -4,18 +4,22 @@ use std::io;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
use libc;
|
||||||
|
|
||||||
use super::callback;
|
use super::callback;
|
||||||
use super::Window;
|
use super::Window;
|
||||||
use super::MonitorID;
|
use super::MonitorID;
|
||||||
use super::WindowWrapper;
|
use super::WindowWrapper;
|
||||||
|
use super::Context;
|
||||||
|
|
||||||
|
use Api;
|
||||||
use BuilderAttribs;
|
use BuilderAttribs;
|
||||||
use CreationError;
|
use CreationError;
|
||||||
use CreationError::OsError;
|
use CreationError::OsError;
|
||||||
use CursorState;
|
use CursorState;
|
||||||
|
use GlRequest;
|
||||||
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::{CString, OsStr};
|
||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
|
@ -23,17 +27,22 @@ use winapi;
|
||||||
use kernel32;
|
use kernel32;
|
||||||
use user32;
|
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
|
pub enum RawContext {
|
||||||
struct ContextHack(winapi::HGLRC);
|
Egl(egl::ffi::egl::types::EGLContext),
|
||||||
unsafe impl Send for ContextHack {}
|
Wgl(winapi::HGLRC),
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<winapi::HGLRC>)
|
unsafe impl Send for RawContext {}
|
||||||
|
unsafe impl Sync for RawContext {}
|
||||||
|
|
||||||
|
pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<RawContext>)
|
||||||
-> Result<Window, CreationError>
|
-> Result<Window, CreationError>
|
||||||
{
|
{
|
||||||
let builder_sharelists = builder_sharelists.map(|s| ContextHack(s));
|
|
||||||
|
|
||||||
// initializing variables to be sent to the task
|
// initializing variables to be sent to the task
|
||||||
|
|
||||||
let title = OsStr::new(&builder.title).encode_wide().chain(Some(0).into_iter())
|
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>,
|
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
|
// registering the window class
|
||||||
let class_name = register_window_class();
|
let class_name = register_window_class();
|
||||||
|
|
||||||
|
@ -147,8 +154,65 @@ unsafe fn init(title: Vec<u16>, builder: BuilderAttribs<'static>,
|
||||||
WindowWrapper(handle, hdc)
|
WindowWrapper(handle, hdc)
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
// creating the OpenGL context
|
||||||
let context = try!(wgl::Context::new(&builder, real_window.0, builder_sharelists));
|
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
|
// calling SetForegroundWindow if fullscreen
|
||||||
if builder.monitor.is_some() {
|
if builder.monitor.is_some() {
|
||||||
|
|
|
@ -26,6 +26,10 @@ use user32;
|
||||||
use kernel32;
|
use kernel32;
|
||||||
|
|
||||||
use api::wgl;
|
use api::wgl;
|
||||||
|
use api::wgl::Context as WglContext;
|
||||||
|
use api::egl::Context as EglContext;
|
||||||
|
|
||||||
|
use self::init::RawContext;
|
||||||
|
|
||||||
mod callback;
|
mod callback;
|
||||||
mod event;
|
mod event;
|
||||||
|
@ -38,7 +42,7 @@ pub struct Window {
|
||||||
window: WindowWrapper,
|
window: WindowWrapper,
|
||||||
|
|
||||||
/// OpenGL context.
|
/// OpenGL context.
|
||||||
context: wgl::Context,
|
context: Context,
|
||||||
|
|
||||||
/// Receiver for the events dispatched by the window callback.
|
/// Receiver for the events dispatched by the window callback.
|
||||||
events_receiver: Receiver<Event>,
|
events_receiver: Receiver<Event>,
|
||||||
|
@ -53,6 +57,11 @@ pub struct Window {
|
||||||
unsafe impl Send for Window {}
|
unsafe impl Send for Window {}
|
||||||
unsafe impl Sync for Window {}
|
unsafe impl Sync for Window {}
|
||||||
|
|
||||||
|
enum Context {
|
||||||
|
Egl(EglContext),
|
||||||
|
Wgl(WglContext),
|
||||||
|
}
|
||||||
|
|
||||||
/// A simple wrapper that destroys the window when it is destroyed.
|
/// A simple wrapper that destroys the window when it is destroyed.
|
||||||
// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)
|
// FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -79,7 +88,12 @@ impl Window {
|
||||||
/// See the docs in the crate root file.
|
/// See the docs in the crate root file.
|
||||||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
||||||
let (builder, sharing) = builder.extract_non_static();
|
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)
|
init::new_window(builder, sharing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,27 +316,45 @@ impl Window {
|
||||||
|
|
||||||
impl GlContext for Window {
|
impl GlContext for Window {
|
||||||
unsafe fn make_current(&self) {
|
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 {
|
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 {
|
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) {
|
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 {
|
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 {
|
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(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -523,14 +523,14 @@ impl Window {
|
||||||
Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window,
|
Context::Glx(try!(GlxContext::new(glx.clone(), builder, display.display, window,
|
||||||
fb_config, visual_infos)))
|
fb_config, visual_infos)))
|
||||||
} else if let Some(ref egl) = display.egl {
|
} 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 {
|
} else {
|
||||||
return Err(CreationError::NotSupported);
|
return Err(CreationError::NotSupported);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GlRequest::Specific(Api::OpenGlEs, _) => {
|
GlRequest::Specific(Api::OpenGlEs, _) => {
|
||||||
if let Some(ref egl) = display.egl {
|
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 {
|
} else {
|
||||||
return Err(CreationError::NotSupported);
|
return Err(CreationError::NotSupported);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue