diff options
Diffstat (limited to 'src/api/win32')
| -rw-r--r-- | src/api/win32/gl.rs | 12 | ||||
| -rw-r--r-- | src/api/win32/init.rs | 382 | ||||
| -rw-r--r-- | src/api/win32/make_current_guard.rs | 52 | ||||
| -rw-r--r-- | src/api/win32/mod.rs | 55 | 
4 files changed, 19 insertions, 482 deletions
diff --git a/src/api/win32/gl.rs b/src/api/win32/gl.rs deleted file mode 100644 index 1354d95..0000000 --- a/src/api/win32/gl.rs +++ /dev/null @@ -1,12 +0,0 @@ -/// WGL bindings -pub mod wgl { -    include!(concat!(env!("OUT_DIR"), "/wgl_bindings.rs")); -} - -/// Functions that are not necessarly always available -pub mod wgl_extra { -    include!(concat!(env!("OUT_DIR"), "/wgl_extra_bindings.rs")); -} - -#[link(name = "opengl32")] -extern {} diff --git a/src/api/win32/init.rs b/src/api/win32/init.rs index e5b0b3a..9223105 100644 --- a/src/api/win32/init.rs +++ b/src/api/win32/init.rs @@ -8,37 +8,32 @@ use std::thread;  use super::callback;  use super::Window;  use super::MonitorID; -use super::ContextWrapper;  use super::WindowWrapper; -use super::make_current_guard::CurrentContextGuard; -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::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; + +use api::wgl::{self, Context};  /// Work-around the fact that HGLRC doesn't implement Send -pub struct ContextHack(pub winapi::HGLRC); +struct ContextHack(winapi::HGLRC);  unsafe impl Send for ContextHack {} -pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<ContextHack>) +pub fn new_window(builder: BuilderAttribs<'static>, builder_sharelists: Option<winapi::HGLRC>)                    -> 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()) @@ -110,57 +105,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,27 +147,8 @@ 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) -            } else { -                f -            } -        } else { -            enumerate_native_pixel_formats(&real_window) -        }; - -        let (id, f) = try!(builder.choose_pixel_format(formats.into_iter().map(|(a, b)| (b, a)))); -        try!(set_pixel_format(&real_window, id)); -        f -    }; - -    // creating the OpenGL context -    let context = try!(create_context(Some((&extra_functions, &builder)), &real_window, -                                      builder_sharelists)); +    //  +    let context = try!(wgl::Context::new(&builder, real_window.0, builder_sharelists));      // calling SetForegroundWindow if fullscreen      if builder.monitor.is_some() { @@ -248,29 +173,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 +241,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/make_current_guard.rs b/src/api/win32/make_current_guard.rs deleted file mode 100644 index 8983899..0000000 --- a/src/api/win32/make_current_guard.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::marker::PhantomData; -use std::io; - -use libc; -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> { -    previous_hdc: winapi::HDC, -    previous_hglrc: winapi::HGLRC, -    marker1: PhantomData<&'a ()>, -    marker2: PhantomData<&'b ()>, -} - -impl<'a, 'b> CurrentContextGuard<'a, 'b> { -    pub unsafe fn make_current(window: &'a WindowWrapper, context: &'b ContextWrapper) -                               -> 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); - -        if result == 0 { -            return Err(CreationError::OsError(format!("wglMakeCurrent function failed: {}", -                                                      format!("{}", io::Error::last_os_error())))); -        } - -        Ok(CurrentContextGuard { -            previous_hdc: previous_hdc, -            previous_hglrc: previous_hglrc, -            marker1: PhantomData, -            marker2: PhantomData, -        }) -    } -} - -impl<'a, 'b> Drop for CurrentContextGuard<'a, 'b> { -    fn drop(&mut self) { -        unsafe { -            gl::wgl::MakeCurrent(self.previous_hdc as *const libc::c_void, -                                 self.previous_hglrc as *const libc::c_void); -        } -    } -} diff --git a/src/api/win32/mod.rs b/src/api/win32/mod.rs index d0caea7..ff42408 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,12 @@ pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};  use winapi;  use user32;  use kernel32; -use gdi32; + +use api::wgl;  mod callback;  mod event; -mod gl;  mod init; -mod make_current_guard;  mod monitor;  /// The Win32 implementation of the main `Window` object. @@ -40,13 +38,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: wgl::Context,      /// Receiver for the events dispatched by the window callback.      events_receiver: Receiver<Event>, @@ -56,27 +48,11 @@ 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); -        } -    } -} -  /// A simple wrapper that destroys the window when it is destroyed.  // FIXME: remove `pub` (https://github.com/rust-lang/rust/issues/23585)  #[doc(hidden)] @@ -103,7 +79,7 @@ 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| w.context.get_hglrc());          init::new_window(builder, sharing)      } @@ -326,38 +302,27 @@ 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); +        self.context.make_current()      }      fn is_current(&self) -> bool { -        unsafe { gl::wgl::GetCurrentContext() == self.context.0 as *const libc::c_void } +        self.context.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 _ -        } +        self.context.get_proc_address(addr)      }      fn swap_buffers(&self) { -        unsafe { -            gdi32::SwapBuffers(self.window.1); -        } +        self.context.swap_buffers()      }      fn get_api(&self) -> Api { -        Api::OpenGl +        self.context.get_api()      }      fn get_pixel_format(&self) -> PixelFormat { -        self.pixel_format.clone() +        self.context.get_pixel_format()      }  }  | 
