diff --git a/.circleci/config.yml b/.circleci/config.yml index 358370e967..752208fb4d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: android-test: working_directory: ~/glutin docker: - - image: tomaka/cargo-apk + - image: gentz/android-rs-glue steps: - run: apt-get -qq update && apt-get install -y git - checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index c694bd087a..a7fc77f903 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,9 @@ - We no longer load `libegl.so` and `libgl.so` multiple times. - Fixes `Context::is_current` incorrectly returning `false`. - **Breaking:** Renamed `GlContext{,Ext}` to `ContextTrait{,Ext}`. +- **Breaking:** Renamed `GlWindow` to `WindowedContext`. - Implemented context sharing support for Windows and Linux. -- Added `SeparatedContext`. -- **Breaking:** Renamed `GlWindow` to `CombinedContext`. +- Added support for separated contexts. - **Breaking:** Removed `shareable_with_windowed_contexts`. Now you must build OsMesa contexts via a separate extension. - Added `ContextBuilder::build` method. diff --git a/Cargo.toml b/Cargo.toml index fd3045f0a4..812e873d21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ readme = "README.md" repository = "https://github.com/tomaka/glutin" documentation = "https://docs.rs/glutin" build = "build.rs" +edition = "2018" [package.metadata.docs.rs] features = ["icon_loading", "serde"] diff --git a/README.md b/README.md index 67d090c832..56b78bcd44 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,11 @@ glutin = "*" ## [Documentation](https://docs.rs/glutin) -## Try it! +## Usage Examples + +Warning: these are examples for master. For the latest released version, 0.19, view [here](https://github.com/tomaka/glutin/tree/72e8c959c4ff538857d028167b9946b8938bdeaa). + +### Try it! ```bash git clone https://github.com/tomaka/glutin @@ -25,62 +29,65 @@ cd glutin cargo run --example window ``` -## Usage +### Usage Glutin is an OpenGL context creation library and doesn't directly provide OpenGL bindings for you. - ```toml [dependencies] gl = "*" ``` ```rust -extern crate gl; -extern crate glutin; - -use glutin::dpi; -use glutin::GlContext; +use glutin::dpi::*; +use glutin::ContextTrait; fn main() { - let mut events_loop = glutin::EventsLoop::new(); - let window_builder = glutin::WindowBuilder::new() + let mut el = glutin::EventsLoop::new(); + let wb = glutin::WindowBuilder::new() .with_title("Hello, world!") - .with_dimensions(dpi::LogicalSize::new(1024.0, 720.0)); - let context = glutin::ContextBuilder::new().with_vsync(true); - let window = glutin::GlWindow::new(window_builder, context, &events_loop).unwrap(); + .with_dimensions(LogicalSize::new(1024.0, 768.0)); + let combined_context = glutin::ContextBuilder::new() + .with_vsync(true) + .build_combined(wb, &el) + .unwrap(); - unsafe { window.make_current().unwrap() }; + unsafe { + combined_context.make_current().unwrap(); + } unsafe { - gl::load_with(|symbol| window.get_proc_address(symbol) as *const _); + gl::load_with(|symbol| combined_context.get_proc_address(symbol) as *const _); gl::ClearColor(0.0, 1.0, 0.0, 1.0); } - let mut should_be_running = true; - while should_be_running { - events_loop.poll_events(|event| match event { - glutin::Event::WindowEvent { event, .. } => match event { - glutin::WindowEvent::CloseRequested => should_be_running = false, - glutin::WindowEvent::Resized(logical_size) => { - let dpi_factor = window.get_hidpi_factor(); - window.resize(logical_size.to_physical(dpi_factor)); - } - _ => (), - }, - _ => (), + let mut running = true; + while running { + el.poll_events(|event| { + match event { + glutin::Event::WindowEvent{ event, .. } => match event { + glutin::WindowEvent::CloseRequested => running = false, + glutin::WindowEvent::Resized(logical_size) => { + let dpi_factor = combined_context.get_hidpi_factor(); + combined_context.resize(logical_size.to_physical(dpi_factor)); + }, + _ => () + }, + _ => () + } }); - unsafe { gl::Clear(gl::COLOR_BUFFER_BIT) } + unsafe { + gl::Clear(gl::COLOR_BUFFER_BIT); + } - window.swap_buffers().unwrap(); + combined_context.swap_buffers().unwrap(); } } - ``` Note that glutin aims at being a low-level brick in your rendering infrastructure. You are encouraged to write another layer of abstraction between glutin and your application. -glutin is only officially supported on the latest stable version of the Rust compiler. +Glutin is only officially supported on the latest stable version of the Rust compiler. ## Platform-specific notes diff --git a/build.rs b/build.rs index b9faa30a0e..c1f702ee16 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,3 @@ -extern crate gl_generator; - use gl_generator::{Api, Fallbacks, Profile, Registry}; use std::env; use std::fs::File; diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 4e1da451c8..f17d735f9c 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -1,5 +1,3 @@ -extern crate glutin; - mod support; use glutin::ContextTrait; @@ -81,6 +79,6 @@ fn main() { }); gl.draw_frame([1.0, 0.5, 0.7, 1.0]); - let _ = combined_context.swap_buffers(); + combined_context.swap_buffers().unwrap(); } } diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index b1ac0f7f33..0df7a5f45e 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -1,5 +1,3 @@ -extern crate glutin; - mod support; use glutin::ContextTrait; @@ -51,9 +49,9 @@ fn main() { for (index, window) in windows.values().enumerate() { let mut color = [1.0, 0.5, 0.7, 1.0]; color.swap(0, index % 3); - let _ = unsafe { window.0.make_current() }; + unsafe { window.0.make_current().unwrap() }; window.1.draw_frame(color); - let _ = window.0.swap_buffers(); + window.0.swap_buffers().unwrap(); } } } diff --git a/examples/separated_context.rs b/examples/separated_context.rs index 0abbc77b0d..ffc8a77441 100644 --- a/examples/separated_context.rs +++ b/examples/separated_context.rs @@ -1,19 +1,22 @@ -extern crate glutin; - mod support; use glutin::ContextTrait; +use std::sync::Arc; fn main() { - let mut el = glutin::EventsLoop::new(); - let win = glutin::WindowBuilder::new() - .with_title("A fantastic window!") - .build(&el) - .unwrap(); - - let separated_context = glutin::ContextBuilder::new() - .build_separated(&win, &el) - .unwrap(); + let (separated_context, mut el, win) = { + let el = glutin::EventsLoop::new(); + let win = glutin::WindowBuilder::new() + .with_title("A fantastic window!") + .build(&el) + .unwrap(); + let win = Arc::new(win); + + let separated_context = glutin::ContextBuilder::new() + .build_separated(Arc::clone(&win), &el) + .unwrap(); + (separated_context, el, win) + }; unsafe { separated_context.make_current().unwrap() } @@ -52,6 +55,6 @@ fn main() { }); gl.draw_frame([1.0, 0.5, 0.7, 1.0]); - let _ = separated_context.swap_buffers(); + separated_context.swap_buffers().unwrap(); } } diff --git a/examples/separated_context_remake.rs b/examples/separated_context_remake.rs new file mode 100644 index 0000000000..bfe5c78ddb --- /dev/null +++ b/examples/separated_context_remake.rs @@ -0,0 +1,89 @@ +mod support; + +use glutin::{ContextTrait, EventsLoop, Window, WindowedContext}; +use std::mem::ManuallyDrop; +use std::sync::Arc; + +fn make_context( + el: &EventsLoop, + win: &Arc, +) -> (ManuallyDrop, support::Gl) { + let separated_context = glutin::ContextBuilder::new() + //.with_hardware_acceleration(None) + .build_separated(Arc::clone(win), el) + .unwrap(); + + unsafe { separated_context.make_current().unwrap() } + + println!( + "Pixel format of the window's GL context: {:?}", + separated_context.get_pixel_format() + ); + + let gl = support::load(&separated_context.context()); + + (ManuallyDrop::new(separated_context), gl) +} + +fn main() { + let mut el = glutin::EventsLoop::new(); + let win = glutin::WindowBuilder::new() + .with_title("A fantastic window!") + .build(&el) + .unwrap(); + let win = Arc::new(win); + + let (mut separated_context, mut gl) = make_context(&el, &win); + + let mut running = true; + let mut remake = false; + while running { + el.poll_events(|event| { + println!("el {:?}", event); + match event { + glutin::Event::WindowEvent { event, .. } => match event { + glutin::WindowEvent::KeyboardInput { + input: + glutin::KeyboardInput { + virtual_keycode: + Some(glutin::VirtualKeyCode::Escape), + .. + }, + .. + } + | glutin::WindowEvent::CloseRequested => running = false, + glutin::WindowEvent::KeyboardInput { + input: + glutin::KeyboardInput { + virtual_keycode: + Some(glutin::VirtualKeyCode::R), + .. + }, + .. + } => remake = true, + glutin::WindowEvent::Resized(logical_size) => { + let dpi_factor = win.get_hidpi_factor(); + separated_context + .resize(logical_size.to_physical(dpi_factor)); + } + _ => (), + }, + _ => (), + } + }); + + gl.draw_frame([1.0, 0.5, 0.7, 1.0]); + separated_context.swap_buffers().unwrap(); + + if remake { + println!("Remaking context."); + unsafe { + ManuallyDrop::drop(&mut separated_context); + } + let (new_separated_context, new_gl) = make_context(&el, &win); + separated_context = new_separated_context; + gl = new_gl; + remake = false; + } + } +} diff --git a/examples/sharing.rs b/examples/sharing.rs index 6a86208498..c6966be1d8 100644 --- a/examples/sharing.rs +++ b/examples/sharing.rs @@ -1,7 +1,5 @@ //! Requires OpenGL 4.2 minimium. -extern crate glutin; - mod support; use glutin::ContextTrait; @@ -87,7 +85,7 @@ fn main() { combined_context.resize(size); unsafe { - let _ = combined_context.make_current(); + combined_context.swap_buffers().unwrap(); glw.gl.DeleteTextures(1, &render_tex); glw.gl.DeleteFramebuffers(1, &window_fb); diff --git a/examples/transparent.rs b/examples/transparent.rs index e8dbd697b7..6a32b04173 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -1,5 +1,3 @@ -extern crate glutin; - mod support; use glutin::ContextTrait; @@ -51,6 +49,6 @@ fn main() { }); gl.draw_frame([0.0; 4]); - let _ = combined_context.swap_buffers(); + combined_context.swap_buffers().unwrap(); } } diff --git a/examples/window.rs b/examples/window.rs index ead408a951..09f233c0e4 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -1,5 +1,3 @@ -extern crate glutin; - mod support; use glutin::ContextTrait; @@ -39,6 +37,6 @@ fn main() { }); gl.draw_frame([1.0, 0.5, 0.7, 1.0]); - let _ = combined_context.swap_buffers(); + combined_context.swap_buffers().unwrap(); } } diff --git a/src/api/android/ffi.rs b/src/api/android/ffi.rs index 48ea214394..bdeb5d8be5 100644 --- a/src/api/android/ffi.rs +++ b/src/api/android/ffi.rs @@ -1,9 +1,12 @@ -#![allow(dead_code)] -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] -#![allow(non_upper_case_globals)] +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals, +)] use libc; + use std::os::raw; #[link(name = "android")] diff --git a/src/api/android/mod.rs b/src/api/android/mod.rs index d9030979bd..4ffa55f445 100644 --- a/src/api/android/mod.rs +++ b/src/api/android/mod.rs @@ -1,26 +1,19 @@ #![cfg(target_os = "android")] -extern crate android_glue; - -use libc; +mod ffi; -use CreationError::{self, OsError}; +use crate::api::egl::{ffi as egl_ffi, Context as EglContext, NativeDisplay}; +use crate::CreationError::{self, OsError}; +use crate::{ + Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements, +}; +use libc; use winit; +use winit::os::android::EventsLoopExt; -use Api; -use ContextError; -use GlAttributes; -use PixelFormat; -use PixelFormatRequirements; - -use api::egl; -use api::egl::Context as EglContext; use std::cell::Cell; use std::sync::Arc; -use winit::os::android::EventsLoopExt; - -mod ffi; struct AndroidContext { egl_context: EglContext, @@ -65,11 +58,11 @@ impl Context { if native_window.is_null() { return Err(OsError(format!("Android's native window is null"))); } - let native_display = egl::NativeDisplay::Android; - let context = try!(EglContext::new(pf_reqs, &gl_attr, native_display) - .and_then(|p| p.finish(native_window as *const _))); + let native_display = NativeDisplay::Android; + let egl_context = EglContext::new(pf_reqs, &gl_attr, native_display) + .and_then(|p| p.finish(native_window as *const _))?; let ctx = Arc::new(AndroidContext { - egl_context: context, + egl_context, stopped: Some(Cell::new(false)), }); @@ -107,10 +100,10 @@ impl Context { ) -> Result { let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context); let context = - EglContext::new(pf_reqs, &gl_attr, egl::NativeDisplay::Android)?; - let context = context.finish_pbuffer((1, 1))?; // TODO: + EglContext::new(pf_reqs, &gl_attr, NativeDisplay::Android)?; + let egl_context = context.finish_pbuffer((1, 1))?; // TODO: let ctx = Arc::new(AndroidContext { - egl_context: context, + egl_context, stopped: None, }); Ok(Context(ctx)) @@ -172,12 +165,12 @@ impl Context { } #[inline] - pub unsafe fn raw_handle(&self) -> egl::ffi::EGLContext { + pub unsafe fn raw_handle(&self) -> egl_ffi::EGLContext { self.0.egl_context.raw_handle() } #[inline] - pub unsafe fn get_egl_display(&self) -> egl::ffi::EGLDisplay { + pub unsafe fn get_egl_display(&self) -> egl_ffi::EGLDisplay { self.0.egl_context.get_egl_display() } } diff --git a/src/api/caca/mod.rs b/src/api/caca/mod.rs index 986af378aa..a8f9b561d5 100644 --- a/src/api/caca/mod.rs +++ b/src/api/caca/mod.rs @@ -7,18 +7,17 @@ ))] #![allow(unused_variables, dead_code)] -use api::osmesa::OsMesaContext; -use libc; +mod ffi; -use { +use crate::api::osmesa::OsMesaContext; +use crate::{ Api, ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements, }; -use std::path::Path; -use std::ptr; +use libc; -mod ffi; +use std::path::Path; pub struct Context { opengl: OsMesaContext, @@ -36,7 +35,7 @@ impl Context { let gl_attr = gl_attr.clone().map_sharing(|w| &w.opengl); let opengl = OsMesaContext::new(window_outer_size, pf_reqs, &gl_attr)?; - let opengl_dimensions = opengl.get_dimensions(); + let opengl_dims = opengl.get_dimensions(); let libcaca = match ffi::LibCaca::open(&Path::new("libcaca.so.0")) { Err(_) => { @@ -47,7 +46,8 @@ impl Context { Ok(l) => l, }; - let display = unsafe { (libcaca.caca_create_display)(ptr::null_mut()) }; + let display = + unsafe { (libcaca.caca_create_display)(std::ptr::null_mut()) }; if display.is_null() { return Err(CreationError::OsError( @@ -68,9 +68,9 @@ impl Context { let masks = get_masks(); (libcaca.caca_create_dither)( 32, - opengl_dimensions.0 as libc::c_int, - opengl_dimensions.1 as libc::c_int, - opengl_dimensions.0 as libc::c_int * 4, + opengl_dims.0 as libc::c_int, + opengl_dims.1 as libc::c_int, + opengl_dims.0 as libc::c_int * 4, masks.0, masks.1, masks.2, @@ -86,10 +86,10 @@ impl Context { } Ok(Context { - libcaca: libcaca, - display: display, - opengl: opengl, - dither: dither, + libcaca, + display, + opengl, + dither, }) } diff --git a/src/api/dlloader/mod.rs b/src/api/dlloader/mod.rs index ef72b47b50..8b2a55cd18 100644 --- a/src/api/dlloader/mod.rs +++ b/src/api/dlloader/mod.rs @@ -6,12 +6,13 @@ target_os = "netbsd", target_os = "openbsd" ))] + +use libloading::Library; + use std::ffi::CString; use std::ops::{Deref, DerefMut}; use std::sync::Arc; -use libloading::Library; - #[derive(Clone)] pub struct SymWrapper { inner: T, diff --git a/src/api/egl/ffi.rs b/src/api/egl/ffi.rs index a765f858df..e39d8cbc59 100644 --- a/src/api/egl/ffi.rs +++ b/src/api/egl/ffi.rs @@ -1,13 +1,5 @@ #![allow(non_camel_case_types)] -#[cfg(target_os = "windows")] -extern crate winapi; - -pub use self::egl::types::EGLContext; -pub use self::egl::types::EGLDisplay; - -use libc; - pub mod egl { pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t; pub type khronos_uint64_t = super::khronos_uint64_t; @@ -23,6 +15,11 @@ pub mod egl { include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs")); } +pub use self::egl::types::EGLContext; +pub use self::egl::types::EGLDisplay; + +use libc; + pub type khronos_utime_nanoseconds_t = khronos_uint64_t; pub type khronos_uint64_t = libc::uint64_t; pub type khronos_ssize_t = libc::c_long; diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index 92ff5549fc..28bbff29da 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -9,28 +9,12 @@ ))] #![allow(unused_variables)] -use Api; -use ContextError; -use CreationError; -use GlAttributes; -use GlRequest; -use PixelFormat; -use PixelFormatRequirements; -use ReleaseBehavior; -use Robustness; - -use std::cell::Cell; -use std::ffi::{CStr, CString}; -use std::ops::{Deref, DerefMut}; -use std::os::raw::{c_int, c_void}; -use std::{mem, ptr}; - pub mod ffi; #[cfg(not(target_os = "android"))] mod egl { use super::ffi; - use api::dlloader::{SymTrait, SymWrapper}; + use crate::api::dlloader::{SymTrait, SymWrapper}; #[derive(Clone)] pub struct Egl(pub SymWrapper); @@ -73,7 +57,17 @@ mod egl { } } } + pub use self::egl::Egl; +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlRequest, PixelFormat, + PixelFormatRequirements, ReleaseBehavior, Robustness, +}; + +use std::cell::Cell; +use std::ffi::{CStr, CString}; +use std::ops::{Deref, DerefMut}; +use std::os::raw; impl Deref for Egl { type Target = ffi::egl::Egl; @@ -126,7 +120,7 @@ pub struct Context { fn get_native_display( egl: &Egl, native_display: NativeDisplay, -) -> *const c_void { +) -> *const raw::c_void { unsafe { egl.GetDisplay(ffi::egl::DEFAULT_DISPLAY as *mut _) } } @@ -134,7 +128,7 @@ fn get_native_display( fn get_native_display( egl: &Egl, native_display: NativeDisplay, -) -> *const c_void { +) -> *const raw::c_void { // the first step is to query the list of extensions without any display, if // supported let dp_extensions = unsafe { @@ -173,7 +167,7 @@ fn get_native_display( egl.GetPlatformDisplay( ffi::egl::PLATFORM_X11_KHR, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -188,7 +182,7 @@ fn get_native_display( egl.GetPlatformDisplayEXT( ffi::egl::PLATFORM_X11_EXT, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -202,7 +196,7 @@ fn get_native_display( egl.GetPlatformDisplay( ffi::egl::PLATFORM_GBM_KHR, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -216,7 +210,7 @@ fn get_native_display( egl.GetPlatformDisplayEXT( ffi::egl::PLATFORM_GBM_KHR, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -230,7 +224,7 @@ fn get_native_display( egl.GetPlatformDisplay( ffi::egl::PLATFORM_WAYLAND_KHR, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -244,7 +238,7 @@ fn get_native_display( egl.GetPlatformDisplayEXT( ffi::egl::PLATFORM_WAYLAND_EXT, d as *mut _, - ptr::null(), + std::ptr::null(), ) } } @@ -259,7 +253,7 @@ fn get_native_display( egl.GetPlatformDisplay( ffi::egl::PLATFORM_ANDROID_KHR, ffi::egl::DEFAULT_DISPLAY as *mut _, - ptr::null(), + std::ptr::null(), ) } @@ -270,7 +264,7 @@ fn get_native_display( egl.GetPlatformDisplay( ffi::egl::PLATFORM_DEVICE_EXT, display as *mut _, - ptr::null(), + std::ptr::null(), ) } @@ -315,8 +309,8 @@ impl Context { } let egl_version = unsafe { - let mut major: ffi::egl::types::EGLint = mem::uninitialized(); - let mut minor: ffi::egl::types::EGLint = mem::uninitialized(); + let mut major: ffi::egl::types::EGLint = std::mem::uninitialized(); + let mut minor: ffi::egl::types::EGLint = std::mem::uninitialized(); if egl.Initialize(display, &mut major, &mut minor) == 0 { return Err(CreationError::OsError(format!( @@ -408,14 +402,14 @@ impl Context { }; Ok(ContextPrototype { - opengl: opengl, - display: display, - egl_version: egl_version, - extensions: extensions, - api: api, - version: version, - config_id: config_id, - pixel_format: pixel_format, + opengl, + display, + egl_version, + extensions, + api, + version, + config_id, + pixel_format, }) } @@ -430,9 +424,11 @@ impl Context { if ret == 0 { match egl.GetError() as u32 { - ffi::egl::CONTEXT_LOST => return Err(ContextError::ContextLost), + ffi::egl::CONTEXT_LOST => { + return Err(ContextError::ContextLost) + } err => panic!( - "eglMakeCurrent failed (eglGetError returned 0x{:x})", + "make_current: eglMakeCurrent failed (eglGetError returned 0x{:x})", err ), } @@ -465,9 +461,11 @@ impl Context { if ret == 0 { match unsafe { egl.GetError() } as u32 { - ffi::egl::CONTEXT_LOST => return Err(ContextError::ContextLost), + ffi::egl::CONTEXT_LOST => { + return Err(ContextError::ContextLost) + } err => panic!( - "eglSwapBuffers failed (eglGetError returned 0x{:x})", + "swap_buffers: eglSwapBuffers failed (eglGetError returned 0x{:x})", err ), } @@ -513,10 +511,13 @@ impl Context { self.display, self.config_id, native_window, - ptr::null(), + std::ptr::null(), )); if self.surface.get().is_null() { - panic!("on_surface_created: eglCreateWindowSurface failed") + panic!( + "on_surface_created: eglCreateWindowSurface failed with 0x{:x}", + egl.GetError() + ) } let ret = egl.MakeCurrent( self.display, @@ -525,7 +526,10 @@ impl Context { self.context, ); if ret == 0 { - panic!("on_surface_created: eglMakeCurrent failed"); + panic!( + "on_surface_created: eglMakeCurrent failed with 0x{:x}", + egl.GetError() + ) } } @@ -546,7 +550,10 @@ impl Context { ffi::egl::NO_CONTEXT, ); if ret == 0 { - panic!("on_surface_destroyed: eglMakeCurrent failed"); + panic!( + "on_surface_destroyed: eglMakeCurrent failed with 0x{:x}", + egl.GetError() + ) } egl.DestroySurface(self.display, self.surface.get()); @@ -559,10 +566,39 @@ unsafe impl Sync for Context {} impl Drop for Context { fn drop(&mut self) { + // https://stackoverflow.com/questions/54402688/recreate-eglcreatewindowsurface-with-same-native-window let egl = EGL.as_ref().unwrap(); unsafe { - // we don't call MakeCurrent(0, 0) because we are not sure that the - // context is still the current one + // Ok, so we got to call `glFinish` before destroying the context to + // insure it actually gets destroyed. This requires making the this + // context current. + // + // Now, if the user has multiple contexts, and they drop this one + // unintentionally between calls to the other context, this could + // result in a !FUN! time debuging. + // + // Then again, if they're **unintentionally** dropping contexts, I + // think they got bigger problems. + self.make_current().unwrap(); + + let gl_finish_fn = self.get_proc_address("glFinish"); + assert!(gl_finish_fn != std::ptr::null()); + let gl_finish_fn = + std::mem::transmute::<_, extern "system" fn()>(gl_finish_fn); + gl_finish_fn(); + + let ret = egl.MakeCurrent( + self.display, + ffi::egl::NO_SURFACE, + ffi::egl::NO_SURFACE, + ffi::egl::NO_CONTEXT, + ); + if ret == 0 { + panic!( + "drop: eglMakeCurrent failed with 0x{:x}", + egl.GetError() + ) + } egl.DestroyContext(self.display, self.context); egl.DestroySurface(self.display, self.surface.get()); egl.Terminate(self.display); @@ -584,7 +620,7 @@ pub struct ContextPrototype<'a> { impl<'a> ContextPrototype<'a> { pub fn get_native_visual_id(&self) -> ffi::egl::types::EGLint { let egl = EGL.as_ref().unwrap(); - let mut value = unsafe { mem::uninitialized() }; + let mut value = unsafe { std::mem::uninitialized() }; let ret = unsafe { egl.GetConfigAttrib( self.display, @@ -594,7 +630,10 @@ impl<'a> ContextPrototype<'a> { ) }; if ret == 0 { - panic!("eglGetConfigAttrib failed") + panic!( + "get_native_visual_id: eglGetConfigAttrib failed with 0x{:x}", + unsafe { egl.GetError() } + ) }; value } @@ -609,7 +648,7 @@ impl<'a> ContextPrototype<'a> { self.display, self.config_id, native_window, - ptr::null(), + std::ptr::null(), ); if surface.is_null() { return Err(CreationError::OsError(format!( @@ -625,15 +664,15 @@ impl<'a> ContextPrototype<'a> { #[cfg(any(target_os = "android", target_os = "windows"))] pub fn finish_pbuffer( self, - dimensions: (u32, u32), + dims: (u32, u32), ) -> Result { let egl = EGL.as_ref().unwrap(); let attrs = &[ - ffi::egl::WIDTH as c_int, - dimensions.0 as c_int, - ffi::egl::HEIGHT as c_int, - dimensions.1 as c_int, - ffi::egl::NONE as c_int, + ffi::egl::WIDTH as raw::c_int, + dims.0 as raw::c_int, + ffi::egl::HEIGHT as raw::c_int, + dims.1 as raw::c_int, + ffi::egl::NONE as raw::c_int, ]; let surface = unsafe { @@ -659,7 +698,7 @@ impl<'a> ContextPrototype<'a> { ) -> Result { let share = match self.opengl.sharing { Some(ctx) => ctx.context, - None => ptr::null(), + None => std::ptr::null(), }; let context = unsafe { @@ -748,7 +787,7 @@ impl<'a> ContextPrototype<'a> { Ok(Context { display: self.display, - context: context, + context, surface: Cell::new(surface), api: self.api, pixel_format: self.pixel_format, @@ -767,43 +806,43 @@ unsafe fn choose_fbconfig( reqs: &PixelFormatRequirements, ) -> Result<(ffi::egl::types::EGLConfig, PixelFormat), CreationError> { let descriptor = { - let mut out: Vec = Vec::with_capacity(37); + let mut out: Vec = Vec::with_capacity(37); if egl_version >= &(1, 2) { - out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int); - out.push(ffi::egl::RGB_BUFFER as c_int); + out.push(ffi::egl::COLOR_BUFFER_TYPE as raw::c_int); + out.push(ffi::egl::RGB_BUFFER as raw::c_int); } - out.push(ffi::egl::SURFACE_TYPE as c_int); + out.push(ffi::egl::SURFACE_TYPE as raw::c_int); // TODO: Some versions of Mesa report a BAD_ATTRIBUTE error // if we ask for PBUFFER_BIT as well as WINDOW_BIT - out.push((ffi::egl::WINDOW_BIT) as c_int); + out.push((ffi::egl::WINDOW_BIT) as raw::c_int); match (api, version) { (Api::OpenGlEs, Some((3, _))) => { if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } - out.push(ffi::egl::RENDERABLE_TYPE as c_int); - out.push(ffi::egl::OPENGL_ES3_BIT as c_int); - out.push(ffi::egl::CONFORMANT as c_int); - out.push(ffi::egl::OPENGL_ES3_BIT as c_int); + out.push(ffi::egl::RENDERABLE_TYPE as raw::c_int); + out.push(ffi::egl::OPENGL_ES3_BIT as raw::c_int); + out.push(ffi::egl::CONFORMANT as raw::c_int); + out.push(ffi::egl::OPENGL_ES3_BIT as raw::c_int); } (Api::OpenGlEs, Some((2, _))) => { if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } - out.push(ffi::egl::RENDERABLE_TYPE as c_int); - out.push(ffi::egl::OPENGL_ES2_BIT as c_int); - out.push(ffi::egl::CONFORMANT as c_int); - out.push(ffi::egl::OPENGL_ES2_BIT as c_int); + out.push(ffi::egl::RENDERABLE_TYPE as raw::c_int); + out.push(ffi::egl::OPENGL_ES2_BIT as raw::c_int); + out.push(ffi::egl::CONFORMANT as raw::c_int); + out.push(ffi::egl::OPENGL_ES2_BIT as raw::c_int); } (Api::OpenGlEs, Some((1, _))) => { if egl_version >= &(1, 3) { - out.push(ffi::egl::RENDERABLE_TYPE as c_int); - out.push(ffi::egl::OPENGL_ES_BIT as c_int); - out.push(ffi::egl::CONFORMANT as c_int); - out.push(ffi::egl::OPENGL_ES_BIT as c_int); + out.push(ffi::egl::RENDERABLE_TYPE as raw::c_int); + out.push(ffi::egl::OPENGL_ES_BIT as raw::c_int); + out.push(ffi::egl::CONFORMANT as raw::c_int); + out.push(ffi::egl::OPENGL_ES_BIT as raw::c_int); } } (Api::OpenGlEs, _) => unimplemented!(), @@ -811,45 +850,49 @@ unsafe fn choose_fbconfig( if egl_version < &(1, 3) { return Err(CreationError::NoAvailablePixelFormat); } - out.push(ffi::egl::RENDERABLE_TYPE as c_int); - out.push(ffi::egl::OPENGL_BIT as c_int); - out.push(ffi::egl::CONFORMANT as c_int); - out.push(ffi::egl::OPENGL_BIT as c_int); + out.push(ffi::egl::RENDERABLE_TYPE as raw::c_int); + out.push(ffi::egl::OPENGL_BIT as raw::c_int); + out.push(ffi::egl::CONFORMANT as raw::c_int); + out.push(ffi::egl::OPENGL_BIT as raw::c_int); } (_, _) => unimplemented!(), }; if let Some(hardware_accelerated) = reqs.hardware_accelerated { - out.push(ffi::egl::CONFIG_CAVEAT as c_int); + out.push(ffi::egl::CONFIG_CAVEAT as raw::c_int); out.push(if hardware_accelerated { - ffi::egl::NONE as c_int + ffi::egl::NONE as raw::c_int } else { - ffi::egl::SLOW_CONFIG as c_int + ffi::egl::SLOW_CONFIG as raw::c_int }); } if let Some(color) = reqs.color_bits { - out.push(ffi::egl::RED_SIZE as c_int); - out.push((color / 3) as c_int); - out.push(ffi::egl::GREEN_SIZE as c_int); - out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int); - out.push(ffi::egl::BLUE_SIZE as c_int); - out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int); + out.push(ffi::egl::RED_SIZE as raw::c_int); + out.push((color / 3) as raw::c_int); + out.push(ffi::egl::GREEN_SIZE as raw::c_int); + out.push( + (color / 3 + if color % 3 != 0 { 1 } else { 0 }) as raw::c_int, + ); + out.push(ffi::egl::BLUE_SIZE as raw::c_int); + out.push( + (color / 3 + if color % 3 == 2 { 1 } else { 0 }) as raw::c_int, + ); } if let Some(alpha) = reqs.alpha_bits { - out.push(ffi::egl::ALPHA_SIZE as c_int); - out.push(alpha as c_int); + out.push(ffi::egl::ALPHA_SIZE as raw::c_int); + out.push(alpha as raw::c_int); } if let Some(depth) = reqs.depth_bits { - out.push(ffi::egl::DEPTH_SIZE as c_int); - out.push(depth as c_int); + out.push(ffi::egl::DEPTH_SIZE as raw::c_int); + out.push(depth as raw::c_int); } if let Some(stencil) = reqs.stencil_bits { - out.push(ffi::egl::STENCIL_SIZE as c_int); - out.push(stencil as c_int); + out.push(ffi::egl::STENCIL_SIZE as raw::c_int); + out.push(stencil as raw::c_int); } if let Some(true) = reqs.double_buffer { @@ -857,8 +900,8 @@ unsafe fn choose_fbconfig( } if let Some(multisampling) = reqs.multisampling { - out.push(ffi::egl::SAMPLES as c_int); - out.push(multisampling as c_int); + out.push(ffi::egl::SAMPLES as raw::c_int); + out.push(multisampling as raw::c_int); } if reqs.stereoscopy { @@ -866,8 +909,8 @@ unsafe fn choose_fbconfig( } if let Some(xid) = reqs.x11_visual_xid { - out.push(ffi::egl::NATIVE_VISUAL_ID as c_int); - out.push(xid as c_int); + out.push(ffi::egl::NATIVE_VISUAL_ID as raw::c_int); + out.push(xid as raw::c_int); } // FIXME: srgb is not taken into account @@ -880,13 +923,13 @@ unsafe fn choose_fbconfig( } } - out.push(ffi::egl::NONE as c_int); + out.push(ffi::egl::NONE as raw::c_int); out }; // calling `eglChooseConfig` - let mut config_id = mem::uninitialized(); - let mut num_configs = mem::uninitialized(); + let mut config_id = std::mem::uninitialized(); + let mut num_configs = std::mem::uninitialized(); if egl.ChooseConfig( display, descriptor.as_ptr(), @@ -904,7 +947,7 @@ unsafe fn choose_fbconfig( // analyzing each config macro_rules! attrib { ($egl:expr, $display:expr, $config:expr, $attr:expr) => {{ - let mut value = mem::uninitialized(); + let mut value = std::mem::uninitialized(); let res = $egl.GetConfigAttrib( $display, $config, @@ -992,8 +1035,9 @@ unsafe fn create_context( .find(|s| s == &"EGL_KHR_create_context_no_error") .is_some() { - context_attributes - .push(ffi::egl::CONTEXT_OPENGL_NO_ERROR_KHR as c_int); + context_attributes.push( + ffi::egl::CONTEXT_OPENGL_NO_ERROR_KHR as raw::c_int, + ); context_attributes.push(1); } } @@ -1002,12 +1046,12 @@ unsafe fn create_context( if supports_robustness { context_attributes.push( ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY - as c_int, + as raw::c_int, ); context_attributes - .push(ffi::egl::NO_RESET_NOTIFICATION as c_int); - flags = - flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + .push(ffi::egl::NO_RESET_NOTIFICATION as raw::c_int); + flags = flags + | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as raw::c_int; } else { return Err(CreationError::RobustnessNotSupported); } @@ -1017,12 +1061,12 @@ unsafe fn create_context( if supports_robustness { context_attributes.push( ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY - as c_int, + as raw::c_int, ); context_attributes - .push(ffi::egl::NO_RESET_NOTIFICATION as c_int); - flags = - flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + .push(ffi::egl::NO_RESET_NOTIFICATION as raw::c_int); + flags = flags + | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as raw::c_int; } } @@ -1030,12 +1074,12 @@ unsafe fn create_context( if supports_robustness { context_attributes.push( ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY - as c_int, + as raw::c_int, ); context_attributes - .push(ffi::egl::LOSE_CONTEXT_ON_RESET as c_int); - flags = - flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + .push(ffi::egl::LOSE_CONTEXT_ON_RESET as raw::c_int); + flags = flags + | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as raw::c_int; } else { return Err(CreationError::RobustnessNotSupported); } @@ -1045,12 +1089,12 @@ unsafe fn create_context( if supports_robustness { context_attributes.push( ffi::egl::CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY - as c_int, + as raw::c_int, ); context_attributes - .push(ffi::egl::LOSE_CONTEXT_ON_RESET as c_int); - flags = - flags | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as c_int; + .push(ffi::egl::LOSE_CONTEXT_ON_RESET as raw::c_int); + flags = flags + | ffi::egl::CONTEXT_OPENGL_ROBUST_ACCESS as raw::c_int; } } } @@ -1105,7 +1149,7 @@ unsafe fn create_context( ffi::egl::BAD_MATCH | ffi::egl::BAD_ATTRIBUTE => { return Err(CreationError::OpenGlVersionNotSupported); } - e => panic!("eglCreateContext failed: 0x{:x}", e), + e => panic!("create_context: eglCreateContext failed: 0x{:x}", e), } } diff --git a/src/api/glx/mod.rs b/src/api/glx/mod.rs index a61d2f7cba..54c830029f 100644 --- a/src/api/glx/mod.rs +++ b/src/api/glx/mod.rs @@ -6,19 +6,6 @@ target_os = "openbsd" ))] -use { - Api, ContextError, CreationError, GlAttributes, GlProfile, GlRequest, - PixelFormat, PixelFormatRequirements, ReleaseBehavior, Robustness, -}; - -use std::ffi::{CStr, CString}; -use std::sync::Arc; -use std::{mem, ptr, slice}; - -use libc::{self, c_int}; - -use winit::os::unix::x11::XConnection; - pub mod ffi { pub use self::glx::types::GLXContext; pub use x11_dl::xlib::*; @@ -36,7 +23,7 @@ pub mod ffi { mod glx { use super::ffi; - use api::dlloader::{SymTrait, SymWrapper}; + use crate::api::dlloader::{SymTrait, SymWrapper}; use std::ops::{Deref, DerefMut}; #[derive(Clone)] @@ -76,7 +63,19 @@ mod glx { } } } + pub use self::glx::Glx; +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlProfile, GlRequest, + PixelFormat, PixelFormatRequirements, ReleaseBehavior, Robustness, +}; + +use libc; +use winit::os::unix::x11::XConnection; + +use std::ffi::{CStr, CString}; +use std::sync::Arc; +use std::{mem, ptr, slice}; lazy_static! { pub static ref GLX: Option = Glx::new().ok(); @@ -210,8 +209,8 @@ impl Context { } #[inline] - pub fn get_api(&self) -> ::Api { - ::Api::OpenGl + pub fn get_api(&self) -> crate::Api { + crate::Api::OpenGl } #[inline] @@ -232,13 +231,16 @@ impl Drop for Context { fn drop(&mut self) { let glx = GLX.as_ref().unwrap(); unsafe { - if self.is_current() { - glx.MakeCurrent( - self.xconn.display as *mut _, - 0, - ptr::null_mut(), - ); - } + // See `drop` for `crate::api::egl::Context` for rationale. + self.make_current().unwrap(); + + let gl_finish_fn = self.get_proc_address("glFinish"); + assert!(gl_finish_fn != std::ptr::null()); + let gl_finish_fn = + std::mem::transmute::<_, extern "system" fn()>(gl_finish_fn); + gl_finish_fn(); + + glx.MakeCurrent(self.xconn.display as *mut _, 0, ptr::null_mut()); glx.DestroyContext(self.xconn.display as *mut _, self.context); } @@ -453,10 +455,12 @@ fn create_context( let context = if check_ext(extensions, "GLX_ARB_create_context") { let mut attributes = Vec::with_capacity(9); - attributes.push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as c_int); - attributes.push(version.0 as c_int); - attributes.push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as c_int); - attributes.push(version.1 as c_int); + attributes + .push(ffi::glx_extra::CONTEXT_MAJOR_VERSION_ARB as libc::c_int); + attributes.push(version.0 as libc::c_int); + attributes + .push(ffi::glx_extra::CONTEXT_MINOR_VERSION_ARB as libc::c_int); + attributes.push(version.1 as libc::c_int); if let Some(profile) = profile { let flag = match profile { @@ -468,9 +472,10 @@ fn create_context( } }; - attributes - .push(ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as c_int); - attributes.push(flag as c_int); + attributes.push( + ffi::glx_extra::CONTEXT_PROFILE_MASK_ARB as libc::c_int, + ); + attributes.push(flag as libc::c_int); } let flags = { @@ -482,28 +487,28 @@ fn create_context( Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => { attributes.push( - ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int, + ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int, ); attributes.push( ffi::glx_extra::NO_RESET_NOTIFICATION_ARB - as c_int, + as libc::c_int, ); flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB - as c_int; + as libc::c_int; } Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => { attributes.push( - ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int, + ffi::glx_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as libc::c_int, ); attributes.push( ffi::glx_extra::LOSE_CONTEXT_ON_RESET_ARB - as c_int, + as libc::c_int, ); flags = flags | ffi::glx_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB - as c_int; + as libc::c_int; } Robustness::NotRobust => (), Robustness::NoError => (), @@ -519,14 +524,14 @@ fn create_context( } if debug { - flags = - flags | ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as c_int; + flags = flags + | ffi::glx_extra::CONTEXT_DEBUG_BIT_ARB as libc::c_int; } flags }; - attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as c_int); + attributes.push(ffi::glx_extra::CONTEXT_FLAGS_ARB as libc::c_int); attributes.push(flags); attributes.push(0); @@ -572,83 +577,91 @@ unsafe fn choose_fbconfig( transparent: bool, ) -> Result<(ffi::glx::types::GLXFBConfig, PixelFormat), ()> { let descriptor = { - let mut out: Vec = Vec::with_capacity(37); + let mut out: Vec = Vec::with_capacity(37); - out.push(ffi::glx::X_RENDERABLE as c_int); + out.push(ffi::glx::X_RENDERABLE as libc::c_int); out.push(1); // TODO: If passed an visual xid, maybe we should stop assuming // TRUE_COLOR. - out.push(ffi::glx::X_VISUAL_TYPE as c_int); - out.push(ffi::glx::TRUE_COLOR as c_int); + out.push(ffi::glx::X_VISUAL_TYPE as libc::c_int); + out.push(ffi::glx::TRUE_COLOR as libc::c_int); if let Some(xid) = reqs.x11_visual_xid { - out.push(ffi::glx::VISUAL_ID as c_int); - out.push(xid as c_int); + out.push(ffi::glx::VISUAL_ID as libc::c_int); + out.push(xid as libc::c_int); } - out.push(ffi::glx::DRAWABLE_TYPE as c_int); - out.push(ffi::glx::WINDOW_BIT as c_int); + out.push(ffi::glx::DRAWABLE_TYPE as libc::c_int); + out.push(ffi::glx::WINDOW_BIT as libc::c_int); - out.push(ffi::glx::RENDER_TYPE as c_int); + out.push(ffi::glx::RENDER_TYPE as libc::c_int); if reqs.float_color_buffer { if check_ext(extensions, "GLX_ARB_fbconfig_float") { - out.push(ffi::glx_extra::RGBA_FLOAT_BIT_ARB as c_int); + out.push(ffi::glx_extra::RGBA_FLOAT_BIT_ARB as libc::c_int); } else { return Err(()); } } else { - out.push(ffi::glx::RGBA_BIT as c_int); + out.push(ffi::glx::RGBA_BIT as libc::c_int); } if let Some(color) = reqs.color_bits { - out.push(ffi::glx::RED_SIZE as c_int); - out.push((color / 3) as c_int); - out.push(ffi::glx::GREEN_SIZE as c_int); - out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int); - out.push(ffi::glx::BLUE_SIZE as c_int); - out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int); + out.push(ffi::glx::RED_SIZE as libc::c_int); + out.push((color / 3) as libc::c_int); + out.push(ffi::glx::GREEN_SIZE as libc::c_int); + out.push( + (color / 3 + if color % 3 != 0 { 1 } else { 0 }) as libc::c_int, + ); + out.push(ffi::glx::BLUE_SIZE as libc::c_int); + out.push( + (color / 3 + if color % 3 == 2 { 1 } else { 0 }) as libc::c_int, + ); } if let Some(alpha) = reqs.alpha_bits { - out.push(ffi::glx::ALPHA_SIZE as c_int); - out.push(alpha as c_int); + out.push(ffi::glx::ALPHA_SIZE as libc::c_int); + out.push(alpha as libc::c_int); } if let Some(depth) = reqs.depth_bits { - out.push(ffi::glx::DEPTH_SIZE as c_int); - out.push(depth as c_int); + out.push(ffi::glx::DEPTH_SIZE as libc::c_int); + out.push(depth as libc::c_int); } if let Some(stencil) = reqs.stencil_bits { - out.push(ffi::glx::STENCIL_SIZE as c_int); - out.push(stencil as c_int); + out.push(ffi::glx::STENCIL_SIZE as libc::c_int); + out.push(stencil as libc::c_int); } let double_buffer = reqs.double_buffer.unwrap_or(true); - out.push(ffi::glx::DOUBLEBUFFER as c_int); + out.push(ffi::glx::DOUBLEBUFFER as libc::c_int); out.push(if double_buffer { 1 } else { 0 }); if let Some(multisampling) = reqs.multisampling { if check_ext(extensions, "GLX_ARB_multisample") { - out.push(ffi::glx_extra::SAMPLE_BUFFERS_ARB as c_int); + out.push(ffi::glx_extra::SAMPLE_BUFFERS_ARB as libc::c_int); out.push(if multisampling == 0 { 0 } else { 1 }); - out.push(ffi::glx_extra::SAMPLES_ARB as c_int); - out.push(multisampling as c_int); + out.push(ffi::glx_extra::SAMPLES_ARB as libc::c_int); + out.push(multisampling as libc::c_int); } else { return Err(()); } } - out.push(ffi::glx::STEREO as c_int); + out.push(ffi::glx::STEREO as libc::c_int); out.push(if reqs.stereoscopy { 1 } else { 0 }); if reqs.srgb { if check_ext(extensions, "GLX_ARB_framebuffer_sRGB") { - out.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int); + out.push( + ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int, + ); out.push(1); } else if check_ext(extensions, "GLX_EXT_framebuffer_sRGB") { - out.push(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as c_int); + out.push( + ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as libc::c_int, + ); out.push(1); } else { return Err(()); @@ -660,18 +673,19 @@ unsafe fn choose_fbconfig( ReleaseBehavior::None => { if check_ext(extensions, "GLX_ARB_context_flush_control") { out.push( - ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int, + ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_ARB + as libc::c_int, ); out.push( ffi::glx_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB - as c_int, + as libc::c_int, ); } } } - out.push(ffi::glx::CONFIG_CAVEAT as c_int); - out.push(ffi::glx::DONT_CARE as c_int); + out.push(ffi::glx::CONFIG_CAVEAT as libc::c_int); + out.push(ffi::glx::DONT_CARE as libc::c_int); out.push(0); out @@ -718,7 +732,7 @@ unsafe fn choose_fbconfig( res? }; - let get_attrib = |attrib: c_int| -> i32 { + let get_attrib = |attrib: libc::c_int| -> i32 { let mut value = 0; glx.GetFBConfigAttrib(display as *mut _, fb_config, attrib, &mut value); // TODO: check return value @@ -726,25 +740,29 @@ unsafe fn choose_fbconfig( }; let pf_desc = PixelFormat { - hardware_accelerated: get_attrib(ffi::glx::CONFIG_CAVEAT as c_int) - != ffi::glx::SLOW_CONFIG as c_int, - color_bits: get_attrib(ffi::glx::RED_SIZE as c_int) as u8 - + get_attrib(ffi::glx::GREEN_SIZE as c_int) as u8 - + get_attrib(ffi::glx::BLUE_SIZE as c_int) as u8, - alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as c_int) as u8, - depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as c_int) as u8, - stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as c_int) as u8, - stereoscopy: get_attrib(ffi::glx::STEREO as c_int) != 0, - double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as c_int) != 0, - multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as c_int) != 0 { - Some(get_attrib(ffi::glx::SAMPLES as c_int) as u16) + hardware_accelerated: get_attrib( + ffi::glx::CONFIG_CAVEAT as libc::c_int, + ) != ffi::glx::SLOW_CONFIG as libc::c_int, + color_bits: get_attrib(ffi::glx::RED_SIZE as libc::c_int) as u8 + + get_attrib(ffi::glx::GREEN_SIZE as libc::c_int) as u8 + + get_attrib(ffi::glx::BLUE_SIZE as libc::c_int) as u8, + alpha_bits: get_attrib(ffi::glx::ALPHA_SIZE as libc::c_int) as u8, + depth_bits: get_attrib(ffi::glx::DEPTH_SIZE as libc::c_int) as u8, + stencil_bits: get_attrib(ffi::glx::STENCIL_SIZE as libc::c_int) as u8, + stereoscopy: get_attrib(ffi::glx::STEREO as libc::c_int) != 0, + double_buffer: get_attrib(ffi::glx::DOUBLEBUFFER as libc::c_int) != 0, + multisampling: if get_attrib(ffi::glx::SAMPLE_BUFFERS as libc::c_int) + != 0 + { + Some(get_attrib(ffi::glx::SAMPLES as libc::c_int) as u16) } else { None }, - srgb: get_attrib(ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int) - != 0 + srgb: get_attrib( + ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as libc::c_int, + ) != 0 || get_attrib( - ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as c_int, + ffi::glx_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as libc::c_int, ) != 0, }; diff --git a/src/api/ios/ffi.rs b/src/api/ios/ffi.rs index e8381518c6..68a23cb073 100644 --- a/src/api/ios/ffi.rs +++ b/src/api/ios/ffi.rs @@ -1,13 +1,13 @@ #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] -use std::os::raw::*; +pub mod gles { + include!(concat!(env!("OUT_DIR"), "/gles2_bindings.rs")); +} use objc::runtime::Object; use objc::{Encode, Encoding}; -pub mod gles { - include!(concat!(env!("OUT_DIR"), "/gles2_bindings.rs")); -} +use std::os::raw; pub type id = *mut Object; pub const nil: id = 0 as id; @@ -88,10 +88,16 @@ extern "C" { pub static kEAGLDrawablePropertyRetainedBacking: id; } -pub const RTLD_LAZY: c_int = 0x001; -pub const RTLD_GLOBAL: c_int = 0x100; +pub const RTLD_LAZY: raw::c_int = 0x001; +pub const RTLD_GLOBAL: raw::c_int = 0x100; extern "C" { - pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void; - pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; + pub fn dlopen( + filename: *const raw::c_char, + flag: raw::c_int, + ) -> *mut raw::c_void; + pub fn dlsym( + handle: *mut raw::c_void, + symbol: *const raw::c_char, + ) -> *mut raw::c_void; } diff --git a/src/api/ios/mod.rs b/src/api/ios/mod.rs index f4c16f5891..2f46f8ec15 100644 --- a/src/api/ios/mod.rs +++ b/src/api/ios/mod.rs @@ -1,3 +1,5 @@ +#![cfg(target_os = "ios")] + //! iOS support //! //! # Building app @@ -58,26 +60,22 @@ //! Also note that app will not receive Destroyed event if suspended, it will be //! SIGKILL'ed -#![cfg(target_os = "ios")] - -use std::ffi::CString; -use std::io; -use std::mem; -use std::os::raw::*; - -use objc::declare::ClassDecl; -use objc::runtime::{Class, Object, Sel, BOOL, NO, YES}; +mod ffi; +pub use self::ffi::id; +use self::ffi::*; -use os::ios::{WindowBuilderExt, WindowExt}; -use os::ContextTraitExt; -use { +use crate::os::ios::{WindowBuilderExt, WindowExt}; +use crate::os::ContextTraitExt; +use crate::{ Api, ContextError, CreationError, EventsLoop, GlAttributes, GlRequest, PixelFormat, PixelFormatRequirements, Window, WindowBuilder, }; -mod ffi; -pub use self::ffi::id; -use self::ffi::*; +use objc::declare::ClassDecl; +use objc::runtime::{Class, Object, Sel, BOOL, NO, YES}; + +use std::ffi::CString; +use std::os::raw; #[derive(Debug, PartialEq)] enum ColorFormat { @@ -276,7 +274,7 @@ impl Context { ].as_ptr() count: 2 ]; - let _ = self.make_current(); + self.make_current().unwrap(); let view = self.view; let scale_factor = window.get_hidpi_factor() as CGFloat; @@ -286,7 +284,7 @@ impl Context { let _: () = msg_send![layer, setDrawableProperties: draw_props]; let gl = gles::Gles2::load_with(|symbol| { - self.get_proc_address(symbol) as *const c_void + self.get_proc_address(symbol) as *const raw::c_void }); let mut color_render_buf: gles::types::GLuint = 0; let mut frame_buf: gles::types::GLuint = 0; @@ -326,8 +324,8 @@ impl Context { if res == YES { Ok(()) } else { - Err(ContextError::IoError(io::Error::new( - io::ErrorKind::Other, + Err(ContextError::IoError(std::io::Error::new( + std::io::ErrorKind::Other, "`EAGLContext presentRenderbuffer` failed", ))) } @@ -364,8 +362,8 @@ impl Context { if res == YES { Ok(()) } else { - Err(ContextError::IoError(io::Error::new( - io::ErrorKind::Other, + Err(ContextError::IoError(std::io::Error::new( + std::io::ErrorKind::Other, "`EAGLContext setCurrentContext` failed", ))) } @@ -384,8 +382,10 @@ impl Context { .expect("proc name contained interior nul byte"); let path = b"/System/Library/Frameworks/OpenGLES.framework/OpenGLES\0"; let addr = unsafe { - let lib = - dlopen(path.as_ptr() as *const c_char, RTLD_LAZY | RTLD_GLOBAL); + let lib = dlopen( + path.as_ptr() as *const raw::c_char, + RTLD_LAZY | RTLD_GLOBAL, + ); dlsym(lib, proc_name_c.as_ptr()) as *const _ }; // debug!("proc {} -> {:?}", proc_name, addr); @@ -418,7 +418,7 @@ fn create_view_class() { extern "C" fn layer_class(_: &Class, _: Sel) -> *const Class { unsafe { - mem::transmute( + std::mem::transmute( Class::get("CAEAGLLayer") .expect("Failed to get class `CAEAGLLayer`"), ) @@ -449,14 +449,14 @@ impl Drop for Context { } impl ContextTraitExt for Context { - type Handle = *mut c_void; + type Handle = *mut raw::c_void; #[inline] unsafe fn raw_handle(&self) -> Self::Handle { - self.eagl_context as *mut c_void + self.eagl_context as *mut raw::c_void } #[inline] - unsafe fn get_egl_display(&self) -> Option<*const c_void> { + unsafe fn get_egl_display(&self) -> Option<*const raw::c_void> { None } } diff --git a/src/api/osmesa/mod.rs b/src/api/osmesa/mod.rs index 9c46729544..d43ac46922 100644 --- a/src/api/osmesa/mod.rs +++ b/src/api/osmesa/mod.rs @@ -6,28 +6,19 @@ target_os = "openbsd" ))] -extern crate osmesa_sys; +pub mod ffi { + pub use osmesa_sys::OSMesaContext; +} + +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlProfile, GlRequest, + PixelFormat, PixelFormatRequirements, Robustness, +}; use libc; -use Api; -use ContextError; -use CreationError; -use GlAttributes; -use GlProfile; -use GlRequest; -use PixelFormat; -use PixelFormatRequirements; -use Robustness; - -use std::error::Error; -use std::ffi::CString; -use std::fmt::{Debug, Display, Error as FormatError, Formatter}; -use std::os::raw::c_void; -use std::{mem, ptr}; -pub mod ffi { - pub use super::osmesa_sys::OSMesaContext; -} +use std::ffi::CString; +use std::os::raw; pub struct OsMesaContext { context: osmesa_sys::OSMesaContext, @@ -39,8 +30,8 @@ pub struct OsMesaContext { #[derive(Debug)] struct NoEsOrWebGlSupported; -impl Display for NoEsOrWebGlSupported { - fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> { +impl std::fmt::Display for NoEsOrWebGlSupported { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!( f, "OsMesa only works with desktop OpenGL; OpenGL ES or WebGL are not supported" @@ -48,7 +39,7 @@ impl Display for NoEsOrWebGlSupported { } } -impl Error for NoEsOrWebGlSupported { +impl std::error::Error for NoEsOrWebGlSupported { fn description(&self) -> &str { "OsMesa only works with desktop OpenGL" } @@ -58,18 +49,18 @@ impl Error for NoEsOrWebGlSupported { struct LoadingError(String); impl LoadingError { - fn new(d: D) -> Self { + fn new(d: D) -> Self { LoadingError(format!("{:?}", d)) } } -impl Display for LoadingError { - fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> { +impl std::fmt::Display for LoadingError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!(f, "Failed to load OsMesa dynamic library: {}", self.0) } } -impl Error for LoadingError { +impl std::error::Error for LoadingError { fn description(&self) -> &str { "The library or a symbol of it could not be loaded" } @@ -77,7 +68,7 @@ impl Error for LoadingError { impl OsMesaContext { pub fn new( - dimensions: (u32, u32), + dims: (u32, u32), _pf_reqs: &PixelFormatRequirements, opengl: &GlAttributes<&OsMesaContext>, ) -> Result { @@ -143,15 +134,15 @@ impl OsMesaContext { attribs.push(0); Ok(OsMesaContext { - width: dimensions.0, - height: dimensions.1, - buffer: ::std::iter::repeat(unsafe { mem::uninitialized() }) - .take((dimensions.0 * dimensions.1) as usize) + width: dims.0, + height: dims.1, + buffer: std::iter::repeat(unsafe { std::mem::uninitialized() }) + .take((dims.0 * dims.1) as usize) .collect(), context: unsafe { let ctx = osmesa_sys::OSMesaCreateContextAttribs( attribs.as_ptr(), - ptr::null_mut(), + std::ptr::null_mut(), ); if ctx.is_null() { return Err(CreationError::OsError( @@ -201,9 +192,9 @@ impl OsMesaContext { pub fn get_proc_address(&self, addr: &str) -> *const () { unsafe { let c_str = CString::new(addr.as_bytes().to_vec()).unwrap(); - mem::transmute(osmesa_sys::OSMesaGetProcAddress(mem::transmute( - c_str.as_ptr(), - ))) + std::mem::transmute(osmesa_sys::OSMesaGetProcAddress( + std::mem::transmute(c_str.as_ptr()), + )) } } @@ -218,7 +209,7 @@ impl OsMesaContext { } #[inline] - pub unsafe fn raw_handle(&self) -> *mut c_void { + pub unsafe fn raw_handle(&self) -> *mut raw::c_void { self.context as *mut _ } } diff --git a/src/api/wgl/make_current_guard.rs b/src/api/wgl/make_current_guard.rs index 7a54e67df9..bb01d07bde 100644 --- a/src/api/wgl/make_current_guard.rs +++ b/src/api/wgl/make_current_guard.rs @@ -1,11 +1,12 @@ -use std::io; -use std::marker::PhantomData; -use std::os::raw::c_void; +use super::gl; +use crate::CreationError; use winapi::shared::windef::{HDC, HGLRC}; -use CreationError; -use super::gl; +use std::io; +use std::marker::PhantomData; +use std::os::raw; + /// A guard for when you want to make the context current. Destroying the guard /// restores the previously-current context. pub struct CurrentContextGuard<'a, 'b> { @@ -44,8 +45,8 @@ impl<'a, 'b> Drop for CurrentContextGuard<'a, 'b> { fn drop(&mut self) { unsafe { gl::wgl::MakeCurrent( - self.previous_hdc as *const c_void, - self.previous_hglrc as *const c_void, + self.previous_hdc as *const raw::c_void, + self.previous_hglrc as *const raw::c_void, ); } } diff --git a/src/api/wgl/mod.rs b/src/api/wgl/mod.rs index 781e529765..769212c494 100644 --- a/src/api/wgl/mod.rs +++ b/src/api/wgl/mod.rs @@ -1,22 +1,14 @@ #![cfg(any(target_os = "windows"))] -use Api; -use ContextError; -use CreationError; -use GlAttributes; -use GlProfile; -use GlRequest; -use PixelFormat; -use PixelFormatRequirements; -use ReleaseBehavior; -use Robustness; +mod gl; +mod make_current_guard; -use self::make_current_guard::CurrentContextGuard; +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlProfile, GlRequest, + PixelFormat, PixelFormatRequirements, ReleaseBehavior, Robustness, +}; -use std::ffi::{CStr, CString, OsStr}; -use std::os::raw::{c_int, c_void}; -use std::os::windows::ffi::OsStrExt; -use std::{io, mem, ptr}; +use self::make_current_guard::CurrentContextGuard; use winapi::shared::minwindef::HMODULE; use winapi::shared::minwindef::*; @@ -26,8 +18,9 @@ use winapi::um::libloaderapi::*; use winapi::um::wingdi::*; use winapi::um::winuser::*; -mod gl; -mod make_current_guard; +use std::ffi::{CStr, CString, OsStr}; +use std::os::raw; +use std::os::windows::ffi::OsStrExt; /// A WGL context. /// @@ -74,8 +67,6 @@ impl Drop for ContextWrapper { 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` @@ -90,7 +81,7 @@ impl Context { if hdc.is_null() { let err = Err(CreationError::OsError(format!( "GetDC function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); return err; } @@ -111,14 +102,16 @@ impl Context { format!("") }; - // calling SetPixelFormat - let pixel_format = { - let (id, f) = if extensions - .split(' ') - .find(|&i| i == "WGL_ARB_pixel_format") - .is_some() - { - choose_arb_pixel_format( + let use_arb_for_pixel_format = extensions + .split(' ') + .find(|&i| i == "WGL_ARB_pixel_format") + .is_some(); + + // calling SetPixelFormat, if not already done + let mut pixel_format_id = GetPixelFormat(hdc); + if pixel_format_id == 0 { + let id = if use_arb_for_pixel_format { + choose_arb_pixel_format_id( &extra_functions, &extensions, hdc, @@ -126,20 +119,33 @@ impl Context { ) .map_err(|_| CreationError::NoAvailablePixelFormat)? } else { - choose_native_pixel_format(hdc, pf_reqs) + choose_native_pixel_format_id(hdc, pf_reqs) .map_err(|_| CreationError::NoAvailablePixelFormat)? }; set_pixel_format(hdc, id)?; - f + pixel_format_id = id; + } + + let pixel_format = if use_arb_for_pixel_format { + choose_arb_pixel_format( + &extra_functions, + &extensions, + hdc, + pixel_format_id, + ) + .map_err(|_| CreationError::NoAvailablePixelFormat)? + } else { + choose_native_pixel_format(hdc, pf_reqs, pixel_format_id) + .map_err(|_| CreationError::NoAvailablePixelFormat)? }; // creating the OpenGL context - let context = try!(create_context( + let context = create_context( Some((&extra_functions, pf_reqs, opengl, &extensions)), window, - hdc - )); + hdc, + )?; // loading the opengl32 module let gl_library = load_opengl32_dll()?; @@ -162,10 +168,10 @@ impl Context { } Ok(Context { - context: context, - hdc: hdc, - gl_library: gl_library, - pixel_format: pixel_format, + context, + hdc, + gl_library, + pixel_format, }) } @@ -184,14 +190,14 @@ impl Context { { Ok(()) } else { - Err(ContextError::IoError(io::Error::last_os_error())) + Err(ContextError::IoError(std::io::Error::last_os_error())) } } #[inline] pub fn is_current(&self) -> bool { unsafe { - gl::wgl::GetCurrentContext() == self.context.0 as *const c_void + gl::wgl::GetCurrentContext() == self.context.0 as *const raw::c_void } } @@ -214,7 +220,7 @@ impl Context { // if unsafe { SwapBuffers(self.hdc) } != 0 { // Ok(()) // } else { - // Err(ContextError::IoError(io::Error::last_os_error())) + // Err(ContextError::IoError(std::io::Error::last_os_error())) // } unsafe { SwapBuffers(self.hdc) }; Ok(()) @@ -255,7 +261,7 @@ unsafe fn create_context( let share; if let Some((extra_functions, _pf_reqs, opengl, extensions)) = extra { - share = opengl.sharing.unwrap_or(ptr::null_mut()); + share = opengl.sharing.unwrap_or(std::ptr::null_mut()); if extensions .split(' ') @@ -268,13 +274,13 @@ unsafe fn create_context( GlRequest::Latest => {} GlRequest::Specific(Api::OpenGl, (major, minor)) => { attributes.push( - gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as raw::c_int, ); - attributes.push(major as c_int); + attributes.push(major as raw::c_int); attributes.push( - gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as raw::c_int, ); - attributes.push(minor as c_int); + attributes.push(minor as raw::c_int); } GlRequest::Specific(Api::OpenGlEs, (major, minor)) => { if extensions @@ -283,23 +289,25 @@ unsafe fn create_context( .is_some() { attributes.push( - gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as c_int, + gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB + as raw::c_int, ); attributes.push( - gl::wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT as c_int, + gl::wgl_extra::CONTEXT_ES2_PROFILE_BIT_EXT + as raw::c_int, ); } else { return Err(CreationError::OpenGlVersionNotSupported); } attributes.push( - gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as raw::c_int, ); - attributes.push(major as c_int); + attributes.push(major as raw::c_int); attributes.push( - gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as raw::c_int, ); - attributes.push(minor as c_int); + attributes.push(minor as raw::c_int); } GlRequest::Specific(_, _) => { return Err(CreationError::OpenGlVersionNotSupported); @@ -309,13 +317,13 @@ unsafe fn create_context( .. } => { attributes.push( - gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MAJOR_VERSION_ARB as raw::c_int, ); - attributes.push(major as c_int); + attributes.push(major as raw::c_int); attributes.push( - gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as c_int, + gl::wgl_extra::CONTEXT_MINOR_VERSION_ARB as raw::c_int, ); - attributes.push(minor as c_int); + attributes.push(minor as raw::c_int); } } @@ -333,9 +341,10 @@ unsafe fn create_context( gl::wgl_extra::CONTEXT_CORE_PROFILE_BIT_ARB } }; - attributes - .push(gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as c_int); - attributes.push(flag as c_int); + attributes.push( + gl::wgl_extra::CONTEXT_PROFILE_MASK_ARB as raw::c_int, + ); + attributes.push(flag as raw::c_int); } else { return Err(CreationError::NotSupported( "required extension \"WGL_ARB_create_context_profile\" not found", @@ -356,28 +365,28 @@ unsafe fn create_context( Robustness::RobustNoResetNotification | Robustness::TryRobustNoResetNotification => { attributes.push( - gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int, + gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as raw::c_int, ); attributes.push( gl::wgl_extra::NO_RESET_NOTIFICATION_ARB - as c_int, + as raw::c_int, ); flags = flags | gl::wgl_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB - as c_int; + as raw::c_int; } Robustness::RobustLoseContextOnReset | Robustness::TryRobustLoseContextOnReset => { attributes.push( - gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as c_int, + gl::wgl_extra::CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB as raw::c_int, ); attributes.push( gl::wgl_extra::LOSE_CONTEXT_ON_RESET_ARB - as c_int, + as raw::c_int, ); flags = flags | gl::wgl_extra::CONTEXT_ROBUST_ACCESS_BIT_ARB - as c_int; + as raw::c_int; } Robustness::NotRobust => (), Robustness::NoError => (), @@ -393,50 +402,50 @@ unsafe fn create_context( } if opengl.debug { - flags = - flags | gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as c_int; + flags = flags + | gl::wgl_extra::CONTEXT_DEBUG_BIT_ARB as raw::c_int; } flags }; - attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as c_int); + attributes.push(gl::wgl_extra::CONTEXT_FLAGS_ARB as raw::c_int); attributes.push(flags); attributes.push(0); let ctx = extra_functions.CreateContextAttribsARB( - hdc as *const c_void, - share as *const c_void, + hdc as *const raw::c_void, + share as *const raw::c_void, attributes.as_ptr(), ); if ctx.is_null() { return Err(CreationError::OsError(format!( "wglCreateContextAttribsARB failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } else { return Ok(ContextWrapper(ctx as HGLRC)); } } } else { - share = ptr::null_mut(); + share = std::ptr::null_mut(); } - let ctx = gl::wgl::CreateContext(hdc as *const c_void); + let ctx = gl::wgl::CreateContext(hdc as *const raw::c_void); if ctx.is_null() { return Err(CreationError::OsError(format!( "wglCreateContext failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } if !share.is_null() { - if gl::wgl::ShareLists(share as *const c_void, ctx) == 0 { + if gl::wgl::ShareLists(share as *const raw::c_void, ctx) == 0 { return Err(CreationError::OsError(format!( "wglShareLists failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } }; @@ -447,10 +456,10 @@ unsafe fn create_context( /// Chooses a pixel formats without using WGL. /// /// Gives less precise results than `enumerate_arb_pixel_formats`. -unsafe fn choose_native_pixel_format( +unsafe fn choose_native_pixel_format_id( hdc: HDC, reqs: &PixelFormatRequirements, -) -> Result<(c_int, PixelFormat), ()> { +) -> Result { // TODO: hardware acceleration is not handled // handling non-supported stuff @@ -478,7 +487,7 @@ unsafe fn choose_native_pixel_format( // building the descriptor to pass to ChoosePixelFormat let descriptor = PIXELFORMATDESCRIPTOR { - nSize: mem::size_of::() as u16, + nSize: std::mem::size_of::() as u16, nVersion: 1, dwFlags: { let f1 = match reqs.double_buffer { @@ -522,12 +531,20 @@ unsafe fn choose_native_pixel_format( return Err(()); } + Ok(pf_id) +} + +unsafe fn choose_native_pixel_format( + hdc: HDC, + reqs: &PixelFormatRequirements, + pf_id: raw::c_int, +) -> Result { // querying back the capabilities of what windows told us - let mut output: PIXELFORMATDESCRIPTOR = mem::zeroed(); + let mut output: PIXELFORMATDESCRIPTOR = std::mem::zeroed(); if DescribePixelFormat( hdc, pf_id, - mem::size_of::() as u32, + std::mem::size_of::() as u32, &mut output, ) == 0 { @@ -581,75 +598,75 @@ unsafe fn choose_native_pixel_format( } } - Ok((pf_id, pf_desc)) + Ok(pf_desc) } /// Enumerates the list of pixel formats by using extra WGL functions. /// /// Gives more precise results than `enumerate_native_pixel_formats`. -unsafe fn choose_arb_pixel_format( +unsafe fn choose_arb_pixel_format_id( extra: &gl::wgl_extra::Wgl, extensions: &str, hdc: HDC, reqs: &PixelFormatRequirements, -) -> Result<(c_int, PixelFormat), ()> { +) -> Result { let descriptor = { - let mut out: Vec = Vec::with_capacity(37); + let mut out: Vec = Vec::with_capacity(37); - out.push(gl::wgl_extra::DRAW_TO_WINDOW_ARB as c_int); + out.push(gl::wgl_extra::DRAW_TO_WINDOW_ARB as raw::c_int); out.push(1); - out.push(gl::wgl_extra::SUPPORT_OPENGL_ARB as c_int); + out.push(gl::wgl_extra::SUPPORT_OPENGL_ARB as raw::c_int); out.push(1); - out.push(gl::wgl_extra::PIXEL_TYPE_ARB as c_int); + out.push(gl::wgl_extra::PIXEL_TYPE_ARB as raw::c_int); if reqs.float_color_buffer { if extensions .split(' ') .find(|&i| i == "WGL_ARB_pixel_format_float") .is_some() { - out.push(gl::wgl_extra::TYPE_RGBA_FLOAT_ARB as c_int); + out.push(gl::wgl_extra::TYPE_RGBA_FLOAT_ARB as raw::c_int); } else { return Err(()); } } else { - out.push(gl::wgl_extra::TYPE_RGBA_ARB as c_int); + out.push(gl::wgl_extra::TYPE_RGBA_ARB as raw::c_int); } if let Some(hardware_accelerated) = reqs.hardware_accelerated { - out.push(gl::wgl_extra::ACCELERATION_ARB as c_int); + out.push(gl::wgl_extra::ACCELERATION_ARB as raw::c_int); out.push(if hardware_accelerated { - gl::wgl_extra::FULL_ACCELERATION_ARB as c_int + gl::wgl_extra::FULL_ACCELERATION_ARB as raw::c_int } else { - gl::wgl_extra::NO_ACCELERATION_ARB as c_int + gl::wgl_extra::NO_ACCELERATION_ARB as raw::c_int }); } if let Some(color) = reqs.color_bits { - out.push(gl::wgl_extra::COLOR_BITS_ARB as c_int); - out.push(color as c_int); + out.push(gl::wgl_extra::COLOR_BITS_ARB as raw::c_int); + out.push(color as raw::c_int); } if let Some(alpha) = reqs.alpha_bits { - out.push(gl::wgl_extra::ALPHA_BITS_ARB as c_int); - out.push(alpha as c_int); + out.push(gl::wgl_extra::ALPHA_BITS_ARB as raw::c_int); + out.push(alpha as raw::c_int); } if let Some(depth) = reqs.depth_bits { - out.push(gl::wgl_extra::DEPTH_BITS_ARB as c_int); - out.push(depth as c_int); + out.push(gl::wgl_extra::DEPTH_BITS_ARB as raw::c_int); + out.push(depth as raw::c_int); } if let Some(stencil) = reqs.stencil_bits { - out.push(gl::wgl_extra::STENCIL_BITS_ARB as c_int); - out.push(stencil as c_int); + out.push(gl::wgl_extra::STENCIL_BITS_ARB as raw::c_int); + out.push(stencil as raw::c_int); } // Prefer double buffering if unspecified (probably shouldn't once you // can choose) let double_buffer = reqs.double_buffer.unwrap_or(true); - out.push(gl::wgl_extra::DOUBLE_BUFFER_ARB as c_int); + out.push(gl::wgl_extra::DOUBLE_BUFFER_ARB as raw::c_int); out.push(if double_buffer { 1 } else { 0 }); if let Some(multisampling) = reqs.multisampling { @@ -658,16 +675,16 @@ unsafe fn choose_arb_pixel_format( .find(|&i| i == "WGL_ARB_multisample") .is_some() { - out.push(gl::wgl_extra::SAMPLE_BUFFERS_ARB as c_int); + out.push(gl::wgl_extra::SAMPLE_BUFFERS_ARB as raw::c_int); out.push(if multisampling == 0 { 0 } else { 1 }); - out.push(gl::wgl_extra::SAMPLES_ARB as c_int); - out.push(multisampling as c_int); + out.push(gl::wgl_extra::SAMPLES_ARB as raw::c_int); + out.push(multisampling as raw::c_int); } else { return Err(()); } } - out.push(gl::wgl_extra::STEREO_ARB as c_int); + out.push(gl::wgl_extra::STEREO_ARB as raw::c_int); out.push(if reqs.stereoscopy { 1 } else { 0 }); if reqs.srgb { @@ -676,14 +693,18 @@ unsafe fn choose_arb_pixel_format( .find(|&i| i == "WGL_ARB_framebuffer_sRGB") .is_some() { - out.push(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as c_int); + out.push( + gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_ARB as raw::c_int, + ); out.push(1); } else if extensions .split(' ') .find(|&i| i == "WGL_EXT_framebuffer_sRGB") .is_some() { - out.push(gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as c_int); + out.push( + gl::wgl_extra::FRAMEBUFFER_SRGB_CAPABLE_EXT as raw::c_int, + ); out.push(1); } else { return Err(()); @@ -699,11 +720,12 @@ unsafe fn choose_arb_pixel_format( .is_some() { out.push( - gl::wgl_extra::CONTEXT_RELEASE_BEHAVIOR_ARB as c_int, + gl::wgl_extra::CONTEXT_RELEASE_BEHAVIOR_ARB + as raw::c_int, ); out.push( gl::wgl_extra::CONTEXT_RELEASE_BEHAVIOR_NONE_ARB - as c_int, + as raw::c_int, ); } } @@ -713,12 +735,12 @@ unsafe fn choose_arb_pixel_format( out }; - let mut format_id = mem::uninitialized(); - let mut num_formats = mem::uninitialized(); + let mut format_id = std::mem::uninitialized(); + let mut num_formats = std::mem::uninitialized(); if extra.ChoosePixelFormatARB( hdc as *const _, descriptor.as_ptr(), - ptr::null(), + std::ptr::null(), 1, &mut format_id, &mut num_formats, @@ -731,14 +753,23 @@ unsafe fn choose_arb_pixel_format( return Err(()); } + Ok(format_id) +} + +unsafe fn choose_arb_pixel_format( + extra: &gl::wgl_extra::Wgl, + extensions: &str, + hdc: HDC, + format_id: raw::c_int, +) -> Result { let get_info = |attrib: u32| { - let mut value = mem::uninitialized(); + let mut value = std::mem::uninitialized(); extra.GetPixelFormatAttribivARB( hdc as *const _, - format_id as c_int, + format_id as raw::c_int, 0, 1, - [attrib as c_int].as_ptr(), + [attrib as raw::c_int].as_ptr(), &mut value, ); value as u32 @@ -786,30 +817,33 @@ unsafe fn choose_arb_pixel_format( }, }; - Ok((format_id, pf_desc)) + Ok(pf_desc) } /// Calls `SetPixelFormat` on a window. -unsafe fn set_pixel_format(hdc: HDC, id: c_int) -> Result<(), CreationError> { - let mut output: PIXELFORMATDESCRIPTOR = mem::zeroed(); +unsafe fn set_pixel_format( + hdc: HDC, + id: raw::c_int, +) -> Result<(), CreationError> { + let mut output: PIXELFORMATDESCRIPTOR = std::mem::zeroed(); if DescribePixelFormat( hdc, id, - mem::size_of::() as UINT, + std::mem::size_of::() as UINT, &mut output, ) == 0 { return Err(CreationError::OsError(format!( "DescribePixelFormat function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } if SetPixelFormat(hdc, id, &output) == 0 { return Err(CreationError::OsError(format!( "SetPixelFormat function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } @@ -828,7 +862,7 @@ unsafe fn load_opengl32_dll() -> Result { if lib.is_null() { return Err(CreationError::OsError(format!( "LoadLibrary function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } @@ -851,8 +885,8 @@ unsafe fn load_extra_functions( let dummy_window = { // getting the rect of the real window let rect = { - let mut placement: WINDOWPLACEMENT = mem::zeroed(); - placement.length = mem::size_of::() as UINT; + let mut placement: WINDOWPLACEMENT = std::mem::zeroed(); + placement.length = std::mem::size_of::() as UINT; if GetWindowPlacement(window, &mut placement) == 0 { panic!(); } @@ -864,18 +898,18 @@ unsafe fn load_extra_functions( if GetClassNameW(window, class_name.as_mut_ptr(), 128) == 0 { return Err(CreationError::OsError(format!( "GetClassNameW function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } // access to class information of the real window - let instance = GetModuleHandleW(ptr::null()); - let mut class: WNDCLASSEXW = mem::zeroed(); + let instance = GetModuleHandleW(std::ptr::null()); + let mut class: WNDCLASSEXW = std::mem::zeroed(); if GetClassInfoExW(instance, class_name.as_ptr(), &mut class) == 0 { return Err(CreationError::OsError(format!( "GetClassInfoExW function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } @@ -886,7 +920,7 @@ unsafe fn load_extra_functions( .chain(Some(0).into_iter()) .collect::>(); - class.cbSize = mem::size_of::() as UINT; + class.cbSize = std::mem::size_of::() as UINT; class.lpszClassName = class_name.as_ptr(); class.lpfnWndProc = Some(DefWindowProcW); @@ -911,16 +945,16 @@ unsafe fn load_extra_functions( CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, - ptr::null_mut(), - ptr::null_mut(), - GetModuleHandleW(ptr::null()), - ptr::null_mut(), + std::ptr::null_mut(), + std::ptr::null_mut(), + GetModuleHandleW(std::ptr::null()), + std::ptr::null_mut(), ); if win.is_null() { return Err(CreationError::OsError(format!( "CreateWindowEx function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); } @@ -928,7 +962,7 @@ unsafe fn load_extra_functions( if hdc.is_null() { let err = Err(CreationError::OsError(format!( "GetDC function failed: {}", - format!("{}", io::Error::last_os_error()) + format!("{}", std::io::Error::last_os_error()) ))); return err; } @@ -951,16 +985,16 @@ unsafe fn load_extra_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 c_void + gl::wgl::GetProcAddress(addr) as *const raw::c_void })) } /// This function chooses a pixel format that is likely to be provided by /// the main video driver of the system. -fn choose_dummy_pixel_format(hdc: HDC) -> Result { +fn choose_dummy_pixel_format(hdc: HDC) -> Result { // building the descriptor to pass to ChoosePixelFormat let descriptor = PIXELFORMATDESCRIPTOR { - nSize: mem::size_of::() as u16, + nSize: std::mem::size_of::() as u16, nVersion: 1, dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, iPixelType: PFD_TYPE_RGBA, diff --git a/src/context.rs b/src/context.rs index 28f772c24c..1569471f0d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -8,7 +8,6 @@ use super::*; /// # Example /// /// ```no_run -/// # extern crate glutin; /// # use glutin::ContextTrait; /// # fn main() { /// # let el = glutin::EventsLoop::new(); diff --git a/src/lib.rs b/src/lib.rs index 1968a2eccb..867ae46482 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,15 @@ //! The purpose of this library is to provide an OpenGL context on as many //! platforms as possible. //! -//! # Building a CombinedContext +//! # Building a WindowedContext //! -//! A `CombinedContext` is composed of a `Window` and an OpenGL `Context`. +//! A `WindowedContext` is composed of a `Window` and an OpenGL `Context`. //! //! Due to some operating-system-specific quirks, glutin prefers control over //! the order of creation of the `Context` and `Window`. Here is an example of -//! building a CombinedContext the prefered way: +//! building a WindowedContext the prefered way: //! //! ```no_run -//! # extern crate glutin; //! # fn main() { //! let el = glutin::EventsLoop::new(); //! let wb = glutin::WindowBuilder::new() @@ -26,71 +25,40 @@ //! window, however that may result in an suboptimal configuration of the window //! on some platforms. In that case use "SeparatedContext". -#[macro_use] -extern crate lazy_static; -#[cfg(any( - target_os = "linux", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd" -))] -#[macro_use] -extern crate shared_library; -#[cfg(target_os = "windows")] -extern crate winapi; -#[cfg(any(target_os = "macos", target_os = "ios"))] -#[macro_use] -extern crate objc; -#[cfg(target_os = "macos")] -extern crate cgl; -#[cfg(target_os = "macos")] -extern crate cocoa; -#[cfg(target_os = "macos")] -extern crate core_foundation; -#[cfg(target_os = "macos")] -extern crate core_graphics; -extern crate libc; #[cfg(any( target_os = "windows", target_os = "linux", + target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] -extern crate libloading; +#[macro_use] +extern crate lazy_static; #[cfg(any( target_os = "linux", - target_os = "freebsd", target_os = "dragonfly", - target_os = "netbsd", - target_os = "openbsd" -))] -extern crate wayland_client; -extern crate winit; -#[cfg(any( - target_os = "linux", target_os = "freebsd", - target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd" ))] -extern crate x11_dl; +#[macro_use] +extern crate shared_library; +#[cfg(any(target_os = "macos", target_os = "ios"))] +#[macro_use] +extern crate objc; + +pub mod os; mod api; -mod combined; mod context; mod platform; -mod separated; - -pub mod os; +mod windowed; -pub use combined::CombinedContext; -pub use context::Context; -pub use separated::SeparatedContext; +pub use crate::context::Context; +pub use crate::windowed::{WindowRef, WindowedContext}; -use std::io; pub use winit::{ dpi, AvailableMonitorsIter, AxisId, ButtonId, ControlFlow, CreationError as WindowCreationError, DeviceEvent, DeviceId, ElementState, @@ -100,6 +68,9 @@ pub use winit::{ WindowBuilder, WindowEvent, WindowId, }; +use std::io; +use std::sync::Arc; + /// A trait for types associated with a GL context. pub trait ContextTrait where @@ -290,17 +261,17 @@ impl<'a> ContextBuilder<'a> { self, wb: WindowBuilder, el: &EventsLoop, - ) -> Result { - CombinedContext::new(wb, self, el) + ) -> Result { + WindowedContext::new(wb, self, el) } /// Builds a separated context. pub fn build_separated( self, - win: &Window, + win: Arc, el: &EventsLoop, - ) -> Result { - SeparatedContext::new(win, self, el) + ) -> Result { + WindowedContext::new_separated(win, self, el) } } @@ -476,11 +447,10 @@ impl GlRequest { /// Extract the desktop GL version, if any. pub fn to_gl_version(&self) -> Option<(u8, u8)> { match self { - &GlRequest::Specific(Api::OpenGl, version) => Some(version), - &GlRequest::GlThenGles { - opengl_version: version, - .. - } => Some(version), + &GlRequest::Specific(Api::OpenGl, opengl_version) => Some(opengl_version), + &GlRequest::GlThenGles { opengl_version, .. } => { + Some(opengl_version) + } _ => None, } } diff --git a/src/os/android.rs b/src/os/android.rs index 70ed8041ad..19c5835e1d 100644 --- a/src/os/android.rs +++ b/src/os/android.rs @@ -1,11 +1,10 @@ #![cfg(any(target_os = "android"))] -pub use winit::os::android::{WindowBuilderExt, WindowExt}; - -pub use api::egl::ffi::EGLContext; +pub use crate::api::egl::ffi::EGLContext; +use crate::os::ContextTraitExt; +use crate::Context; -use os::ContextTraitExt; -use Context; +pub use winit::os::android::{WindowBuilderExt, WindowExt}; use std::os::raw; diff --git a/src/os/macos.rs b/src/os/macos.rs index 0096eba2c7..362402e6f1 100644 --- a/src/os/macos.rs +++ b/src/os/macos.rs @@ -1,17 +1,17 @@ #![cfg(target_os = "macos")] +use crate::os::ContextTraitExt; +use crate::Context; + pub use winit::os::macos::ActivationPolicy; pub use winit::os::macos::MonitorIdExt; pub use winit::os::macos::WindowBuilderExt; pub use winit::os::macos::WindowExt; -use os::ContextTraitExt; -use Context; - -use std::os::raw::c_void; +use std::os::raw; impl ContextTraitExt for Context { - type Handle = *mut c_void; + type Handle = *mut raw::c_void; #[inline] unsafe fn raw_handle(&self) -> Self::Handle { @@ -19,7 +19,7 @@ impl ContextTraitExt for Context { } #[inline] - unsafe fn get_egl_display(&self) -> Option<*const c_void> { + unsafe fn get_egl_display(&self) -> Option<*const raw::c_void> { None } } diff --git a/src/os/unix.rs b/src/os/unix.rs index 58619edd0b..d7fd27434a 100644 --- a/src/os/unix.rs +++ b/src/os/unix.rs @@ -6,9 +6,11 @@ target_os = "openbsd" ))] -pub use api::egl::ffi::EGLContext; -pub use api::glx::ffi::GLXContext; -pub use platform::RawHandle; +pub use crate::api::egl::ffi::EGLContext; +pub use crate::api::glx::ffi::GLXContext; +use crate::os::ContextTraitExt; +pub use crate::platform::RawHandle; +use crate::Context; pub use winit::os::unix::EventsLoopExt; pub use winit::os::unix::MonitorIdExt; @@ -17,9 +19,6 @@ pub use winit::os::unix::WindowExt; pub use winit::os::unix::XNotSupported; pub use winit::os::unix::XWindowType; -use os::ContextTraitExt; -use Context; - use std::os::raw; impl ContextTraitExt for Context { diff --git a/src/os/windows.rs b/src/os/windows.rs index 0bd866431f..3888ff24f9 100644 --- a/src/os/windows.rs +++ b/src/os/windows.rs @@ -1,18 +1,17 @@ #![cfg(target_os = "windows")] +pub use crate::api::egl::ffi::EGLContext; +use crate::os::ContextTraitExt; +pub use crate::platform::RawHandle; +use crate::Context; + pub use winapi::shared::windef::HGLRC; pub use winit::os::windows::{ DeviceIdExt, MonitorIdExt, WindowBuilderExt, WindowExt, }; -pub use api::egl::ffi::EGLContext; -pub use platform::RawHandle; - use std::os::raw; -use os::ContextTraitExt; -use Context; - impl ContextTraitExt for Context { type Handle = RawHandle; diff --git a/src/platform/android/mod.rs b/src/platform/android/mod.rs index 87cfd9a687..b0bf565840 100644 --- a/src/platform/android/mod.rs +++ b/src/platform/android/mod.rs @@ -1,5 +1,4 @@ #![cfg(target_os = "android")] +pub use crate::api::android::*; pub use winit::EventsLoop; - -pub use api::android::*; diff --git a/src/platform/emscripten/ffi.rs b/src/platform/emscripten/ffi.rs index c8065c6d7c..2e5a507a3f 100644 --- a/src/platform/emscripten/ffi.rs +++ b/src/platform/emscripten/ffi.rs @@ -1,6 +1,4 @@ -#![allow(dead_code)] -#![allow(non_snake_case)] -#![allow(non_camel_case_types)] +#![allow(dead_code, non_snake_case, non_camel_case_types)] use libc; diff --git a/src/platform/emscripten/mod.rs b/src/platform/emscripten/mod.rs index ac5d139086..4e49906f0d 100644 --- a/src/platform/emscripten/mod.rs +++ b/src/platform/emscripten/mod.rs @@ -1,13 +1,15 @@ #![cfg(target_os = "emscripten")] -use std::ffi::CString; +mod ffi; -use {Api, ContextError, CreationError, GlAttributes, GlRequest}; -use {PixelFormat, PixelFormatRequirements}; +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlRequest, PixelFormat, + PixelFormatRequirements, +}; use winit; -mod ffi; +use std::ffi::CString; pub enum Context { Window(ffi::EMSCRIPTEN_WEBGL_CONTEXT_HANDLE), @@ -30,9 +32,8 @@ impl Context { // getting the default values of attributes let mut attributes = unsafe { - use std::mem; let mut attributes: ffi::EmscriptenWebGLContextAttributes = - mem::uninitialized(); + std::mem::uninitialized(); ffi::emscripten_webgl_init_context_attributes(&mut attributes); attributes }; @@ -46,14 +47,15 @@ impl Context { // creating the context let context = unsafe { - use std::{mem, ptr}; // TODO: correct first parameter based on the window - let context = - ffi::emscripten_webgl_create_context(ptr::null(), &attributes); + let context = ffi::emscripten_webgl_create_context( + std::ptr::null(), + &attributes, + ); if context <= 0 { return Err(CreationError::OsError(format!( "Error while calling emscripten_webgl_create_context: {}", - error_to_str(mem::transmute(context)) + error_to_str(std::mem::transmute(context)) ))); } context diff --git a/src/platform/ios/mod.rs b/src/platform/ios/mod.rs index 5aa740ba5b..aceb3c79db 100644 --- a/src/platform/ios/mod.rs +++ b/src/platform/ios/mod.rs @@ -1,3 +1,3 @@ #![cfg(target_os = "ios")] -pub use api::ios::*; +pub use crate::api::ios::*; diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 4f55b6147c..e458f4d1a7 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -6,10 +6,12 @@ target_os = "openbsd" ))] +mod wayland; +mod x11; + use self::x11::X11Context; -use api::egl; -use api::glx; -use { +use crate::api::{egl, glx, osmesa}; +use crate::{ ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements, }; @@ -17,10 +19,6 @@ use { use winit; use winit::os::unix::EventsLoopExt; -mod wayland; -mod x11; -use api::osmesa; - use std::os::raw; /// Context handles available on Unix-like platforms. @@ -55,7 +53,9 @@ impl Context { Context::OsMesa(_) => Ok(()), _ => { let msg = "Cannot share an OSMesa context with a non-OSMesa context"; - return Err(CreationError::PlatformSpecific(msg.into())); + return Err(CreationError::PlatformSpecific( + msg.into(), + )); } }, ContextType::X11 => match *c { @@ -64,7 +64,9 @@ impl Context { } _ => { let msg = "Cannot share an X11 context with a non-X11 context"; - return Err(CreationError::PlatformSpecific(msg.into())); + return Err(CreationError::PlatformSpecific( + msg.into(), + )); } }, ContextType::Wayland => match *c { @@ -72,7 +74,9 @@ impl Context { | Context::HeadlessWayland(_, _) => Ok(()), _ => { let msg = "Cannot share a Wayland context with a non-Wayland context"; - return Err(CreationError::PlatformSpecific(msg.into())); + return Err(CreationError::PlatformSpecific( + msg.into(), + )); } }, } @@ -225,7 +229,7 @@ impl Context { } #[inline] - pub fn get_api(&self) -> ::Api { + pub fn get_api(&self) -> crate::Api { match *self { Context::WindowedX11(ref ctx) | Context::HeadlessX11(_, ref ctx) => ctx.get_api(), @@ -274,6 +278,7 @@ impl Context { #[inline] fn new_osmesa( + dims: (u32, u32), pf_reqs: &PixelFormatRequirements, gl_attr: &GlAttributes<&Context>, ) -> Result { @@ -282,13 +287,16 @@ impl Context { &Context::OsMesa(ref ctx) => ctx, _ => unreachable!(), }); - osmesa::OsMesaContext::new((1, 1), pf_reqs, &gl_attr) + osmesa::OsMesaContext::new(dims, pf_reqs, &gl_attr) .map(|context| Context::OsMesa(context)) } } pub trait OsMesaContextExt { - fn new_osmesa(cb: crate::ContextBuilder) -> Result + fn new_osmesa( + dims: (u32, u32), + cb: crate::ContextBuilder, + ) -> Result where Self: Sized; } @@ -300,13 +308,16 @@ impl OsMesaContextExt for crate::Context { /// generally happens because the underlying platform doesn't support a /// requested feature. #[inline] - fn new_osmesa(cb: crate::ContextBuilder) -> Result + fn new_osmesa( + dims: (u32, u32), + cb: crate::ContextBuilder, + ) -> Result where Self: Sized, { let crate::ContextBuilder { pf_reqs, gl_attr } = cb; let gl_attr = gl_attr.map_sharing(|ctx| &ctx.context); - Context::new_osmesa(&pf_reqs, &gl_attr) + Context::new_osmesa(dims, &pf_reqs, &gl_attr) .map(|context| crate::Context { context }) } } diff --git a/src/platform/linux/wayland.rs b/src/platform/linux/wayland.rs index 1837438fef..aa27c75c84 100644 --- a/src/platform/linux/wayland.rs +++ b/src/platform/linux/wayland.rs @@ -1,14 +1,16 @@ -use api::egl::{self, ffi, Context as EglContext}; -use std::os::raw; -use std::sync::Arc; -use wayland_client::egl as wegl; -use winit; -use winit::os::unix::WindowExt; -use { +use crate::api::egl::{ffi, Context as EglContext, NativeDisplay}; +use crate::{ ContextError, CreationError, GlAttributes, PixelFormat, PixelFormatRequirements, }; +use wayland_client::egl as wegl; +use winit; +use winit::os::unix::WindowExt; + +use std::os::raw; +use std::sync::Arc; + pub struct Context { egl_surface: Arc, context: EglContext, @@ -52,7 +54,7 @@ impl Context { }; let context = { let gl_attr = gl_attr.clone().map_sharing(|c| &c.context); - let native_display = egl::NativeDisplay::Wayland(Some( + let native_display = NativeDisplay::Wayland(Some( window.get_wayland_display().unwrap() as *const _, )); EglContext::new(pf_reqs, &gl_attr, native_display) @@ -60,7 +62,7 @@ impl Context { }; let context = Context { egl_surface: Arc::new(egl_surface), - context: context, + context, }; Ok(context) } @@ -91,7 +93,7 @@ impl Context { } #[inline] - pub fn get_api(&self) -> ::Api { + pub fn get_api(&self) -> crate::Api { self.context.get_api() } diff --git a/src/platform/linux/x11.rs b/src/platform/linux/x11.rs index b591ec0b11..d9e3611762 100644 --- a/src/platform/linux/x11.rs +++ b/src/platform/linux/x11.rs @@ -1,33 +1,29 @@ -pub use winit::os::unix::x11::{XConnection, XError, XNotSupported}; - -use std::os::raw; -use std::sync::Arc; -use std::{error, fmt, mem, ptr}; - -use winit; -use winit::os::unix::{EventsLoopExt, WindowBuilderExt, WindowExt}; - -use { +use crate::api::egl::{Context as EglContext, NativeDisplay, EGL}; +use crate::api::glx::{ffi, Context as GlxContext, GLX}; +use crate::{ Api, ContextError, CreationError, GlAttributes, GlRequest, PixelFormat, PixelFormatRequirements, }; -use api::egl; -use api::egl::{Context as EglContext, EGL}; -use api::glx::{ffi, Context as GlxContext, GLX}; +use winit; +pub use winit::os::unix::x11::{XConnection, XError, XNotSupported}; +use winit::os::unix::{EventsLoopExt, WindowBuilderExt, WindowExt}; + +use std::os::raw; +use std::sync::Arc; #[derive(Debug)] struct NoX11Connection; -impl error::Error for NoX11Connection { +impl std::error::Error for NoX11Connection { fn description(&self) -> &str { "failed to get x11 connection" } } -impl fmt::Display for NoX11Connection { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(error::Error::description(self)) +impl std::fmt::Display for NoX11Connection { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(std::error::Error::description(self)) } } @@ -49,8 +45,6 @@ unsafe impl Sync for Context {} impl Drop for Context { fn drop(&mut self) { unsafe { - // we don't call MakeCurrent(0, 0) because we are not sure that the - // context is still the current one self.context = X11Context::None; (self.xconn.xlib.XFreeColormap)(self.xconn.display, self.colormap); @@ -80,8 +74,8 @@ impl Context { // start the context building process enum Prototype<'a> { - Glx(::api::glx::ContextPrototype<'a>), - Egl(::api::egl::ContextPrototype<'a>), + Glx(crate::api::glx::ContextPrototype<'a>), + Egl(crate::api::egl::ContextPrototype<'a>), } let builder = gl_attr.clone(); @@ -112,9 +106,8 @@ impl Context { X11Context::Egl(ref c) => c, _ => panic!(), }); - let native_display = egl::NativeDisplay::X11(Some( - xconn.display as *const _, - )); + let native_display = + NativeDisplay::X11(Some(xconn.display as *const _)); Prototype::Egl(EglContext::new( pf_reqs, &builder_egl_u, @@ -135,9 +128,7 @@ impl Context { Prototype::Egl(EglContext::new( pf_reqs, &builder_egl_u, - egl::NativeDisplay::X11(Some( - xconn.display as *const _, - )), + NativeDisplay::X11(Some(xconn.display as *const _)), )?) } else { return Err(CreationError::NotSupported( @@ -157,7 +148,8 @@ impl Context { let visual_infos = match context { Prototype::Glx(ref p) => p.get_visual_infos().clone(), Prototype::Egl(ref p) => { - let mut template: ffi::XVisualInfo = unsafe { mem::zeroed() }; + let mut template: ffi::XVisualInfo = + unsafe { std::mem::zeroed() }; template.visualid = p.get_native_visual_id() as ffi::VisualID; let mut num_visuals = 0; @@ -175,7 +167,7 @@ impl Context { assert!(!vi.is_null()); assert!(num_visuals == 1); - let vi_copy = unsafe { ptr::read(vi as *const _) }; + let vi_copy = unsafe { std::ptr::read(vi as *const _) }; unsafe { (xconn.xlib.XFree)(vi as *mut _); } @@ -246,7 +238,7 @@ impl Context { let xlib_window = window.get_xlib_window().unwrap(); let attrs = { - let mut attrs = unsafe { ::std::mem::uninitialized() }; + let mut attrs = unsafe { std::mem::uninitialized() }; unsafe { (xconn.xlib.XGetWindowAttributes)( xconn.display, @@ -265,8 +257,8 @@ impl Context { // start the context building process enum Prototype<'a> { - Glx(::api::glx::ContextPrototype<'a>), - Egl(::api::egl::ContextPrototype<'a>), + Glx(crate::api::glx::ContextPrototype<'a>), + Egl(crate::api::egl::ContextPrototype<'a>), } let builder = gl_attr.clone(); @@ -299,9 +291,8 @@ impl Context { X11Context::Egl(ref c) => c, _ => panic!(), }); - let native_display = egl::NativeDisplay::X11(Some( - xconn.display as *const _, - )); + let native_display = + NativeDisplay::X11(Some(xconn.display as *const _)); Prototype::Egl(EglContext::new( &pf_reqs, &builder_egl_u, @@ -322,9 +313,7 @@ impl Context { Prototype::Egl(EglContext::new( &pf_reqs, &builder_egl_u, - egl::NativeDisplay::X11(Some( - xconn.display as *const _, - )), + NativeDisplay::X11(Some(xconn.display as *const _)), )?) } else { return Err(CreationError::NotSupported( @@ -399,7 +388,7 @@ impl Context { match self.context { X11Context::Glx(ref ctx) => ctx.get_proc_address(addr), X11Context::Egl(ref ctx) => ctx.get_proc_address(addr), - X11Context::None => ptr::null(), + X11Context::None => std::ptr::null(), } } diff --git a/src/platform/macos/helpers.rs b/src/platform/macos/helpers.rs index 011e8af980..7ab23590df 100644 --- a/src/platform/macos/helpers.rs +++ b/src/platform/macos/helpers.rs @@ -1,11 +1,10 @@ +use crate::{ + CreationError, GlAttributes, GlProfile, GlRequest, PixelFormatRequirements, + ReleaseBehavior, +}; + use cocoa::appkit::*; use cocoa::base::nil; -use CreationError; -use GlAttributes; -use GlProfile; -use GlRequest; -use PixelFormatRequirements; -use ReleaseBehavior; pub fn get_gl_profile( opengl: &GlAttributes<&T>, diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index edce0bcc91..33c8e0cb6f 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -1,13 +1,9 @@ #![cfg(target_os = "macos")] -pub use winit::MonitorId; - -use ContextError; -use CreationError; -use GlAttributes; -use PixelFormat; -use PixelFormatRequirements; -use Robustness; +use crate::{ + ContextError, CreationError, GlAttributes, PixelFormat, + PixelFormatRequirements, Robustness, +}; use cgl::{ kCGLCECrashOnRemovedFunctions, kCGLCPSurfaceOpacity, CGLEnable, @@ -22,11 +18,13 @@ use core_foundation::bundle::{ }; use core_foundation::string::CFString; use objc::runtime::{BOOL, NO}; + use winit; use winit::os::macos::WindowExt; +pub use winit::MonitorId; use std::ops::Deref; -use std::os::raw::c_void; +use std::os::raw; use std::str::FromStr; mod helpers; @@ -284,8 +282,8 @@ impl Context { } #[inline] - pub fn get_api(&self) -> ::Api { - ::Api::OpenGl + pub fn get_api(&self) -> crate::Api { + crate::Api::OpenGl } #[inline] @@ -297,7 +295,7 @@ impl Context { } #[inline] - pub unsafe fn raw_handle(&self) -> *mut c_void { + pub unsafe fn raw_handle(&self) -> *mut raw::c_void { match *self { Context::WindowedContext(ref c) => *c.context.deref() as *mut _, Context::HeadlessContext(ref c) => *c.context.deref() as *mut _, diff --git a/src/platform/windows/mod.rs b/src/platform/windows/mod.rs index 9876ee1c1a..d666f9c85d 100644 --- a/src/platform/windows/mod.rs +++ b/src/platform/windows/mod.rs @@ -1,29 +1,23 @@ #![cfg(target_os = "windows")] -use std::os::raw; -use std::ptr; +use crate::{ + Api, ContextError, CreationError, GlAttributes, GlRequest, PixelFormat, + PixelFormatRequirements, +}; + +use crate::api::egl::{ffi, Context as EglContext, NativeDisplay, EGL}; +use crate::api::wgl::Context as WglContext; +use crate::os::windows::WindowExt; use winapi::shared::windef::{HGLRC, HWND}; use winit; -use Api; -use ContextError; -use CreationError; -use GlAttributes; -use GlRequest; -use PixelFormat; -use PixelFormatRequirements; - -use api::egl; -use api::egl::Context as EglContext; -use api::egl::EGL; -use api::wgl::Context as WglContext; -use os::windows::WindowExt; +use std::os::raw; /// Context handles available on Windows. #[derive(Clone, Debug)] pub enum RawHandle { - Egl(egl::ffi::EGLContext), + Egl(ffi::EGLContext), Wgl(HGLRC), } @@ -95,7 +89,7 @@ impl Context { EglContext::new( &pf_reqs, &gl_attr_egl, - egl::NativeDisplay::Other(Some(ptr::null())), + NativeDisplay::Other(Some(std::ptr::null())), ) .and_then(|p| p.finish(w)) .map(|c| Context::Egl(c)) @@ -110,7 +104,7 @@ impl Context { if let Ok(c) = EglContext::new( &pf_reqs, &gl_attr_egl, - egl::NativeDisplay::Other(Some(ptr::null())), + NativeDisplay::Other(Some(std::ptr::null())), ) .and_then(|p| p.finish(w)) { @@ -160,7 +154,7 @@ impl Context { _ => unreachable!(), }); - let native_display = egl::NativeDisplay::Other(None); + let native_display = NativeDisplay::Other(None); let context = EglContext::new(pf_reqs, &gl_attr_egl, native_display) .and_then(|prototype| prototype.finish_pbuffer((1, 1))) diff --git a/src/separated.rs b/src/separated.rs deleted file mode 100644 index 99230d16a9..0000000000 --- a/src/separated.rs +++ /dev/null @@ -1,126 +0,0 @@ -use super::*; - -/// Represents an OpenGL context which has been associated with a preexisting -/// window. -/// -/// # Example -/// -/// ```no_run -/// # extern crate glutin; -/// # use glutin::ContextTrait; -/// # fn main() { -/// let mut el = glutin::EventsLoop::new(); -/// let win = glutin::WindowBuilder::new().build(&el).unwrap(); -/// let separated_context = glutin::ContextBuilder::new() -/// .build_separated(&win, &el) -/// .unwrap(); -/// -/// unsafe { separated_context.make_current().unwrap() }; -/// -/// loop { -/// el.poll_events(|event| { -/// match event { -/// // process events here -/// _ => (), -/// } -/// }); -/// -/// // draw everything here -/// -/// separated_context.swap_buffers(); -/// std::thread::sleep(std::time::Duration::from_millis(17)); -/// } -/// # } -/// ``` -pub struct SeparatedContext { - context: Context, -} - -impl SeparatedContext { - /// Builds the GL context using the passed `Window`, returning the context - /// as a `SeparatedContext`. - /// - /// One notable limitation of the Wayland backend when it comes to shared - /// contexts is that both contexts must use the same events loop. - /// - /// Errors can occur in two scenarios: - /// - If the window could not be created (via permission denied, - /// incompatible system, out of memory, etc.). This should be very rare. - /// - If the OpenGL context could not be created. This generally happens - /// because the underlying platform doesn't support a requested feature. - pub fn new( - window: &Window, - cb: ContextBuilder, - el: &EventsLoop, - ) -> Result { - let ContextBuilder { pf_reqs, gl_attr } = cb; - let gl_attr = gl_attr.map_sharing(|ctx| &ctx.context); - - platform::Context::new_separated(window, el, &pf_reqs, &gl_attr).map( - |context| SeparatedContext { - context: Context { context }, - }, - ) - } - - /// Borrow the inner GL `Context`. - pub fn context(&self) -> &Context { - &self.context - } - - /// Swaps the buffers in case of double or triple buffering. - /// - /// You should call this function every time you have finished rendering, or - /// the image may not be displayed on the screen. - /// - /// **Warning**: if you enabled vsync, this function will block until the - /// next time the screen is refreshed. However drivers can choose to - /// override your vsync settings, which means that you can't know in - /// advance whether `swap_buffers` will block or not. - pub fn swap_buffers(&self) -> Result<(), ContextError> { - self.context.context.swap_buffers() - } - - /// Returns the pixel format of the main framebuffer of the context. - pub fn get_pixel_format(&self) -> PixelFormat { - self.context.context.get_pixel_format() - } - - /// Resize the context. - /// - /// Some platforms (macOS, Wayland) require being manually updated when - /// their window or surface is resized. - /// - /// The easiest way of doing this is to take every `Resized` window event - /// that is received with a `LogicalSize` and convert it to a - /// `PhysicalSize` and pass it into this function. - pub fn resize(&self, size: dpi::PhysicalSize) { - let (width, height) = size.into(); - self.context.context.resize(width, height); - } -} - -impl ContextTrait for SeparatedContext { - unsafe fn make_current(&self) -> Result<(), ContextError> { - self.context.make_current() - } - - fn is_current(&self) -> bool { - self.context.is_current() - } - - fn get_proc_address(&self, addr: &str) -> *const () { - self.context.get_proc_address(addr) - } - - fn get_api(&self) -> Api { - self.context.get_api() - } -} - -impl std::ops::Deref for SeparatedContext { - type Target = Context; - fn deref(&self) -> &Self::Target { - &self.context - } -} diff --git a/src/combined.rs b/src/windowed.rs similarity index 67% rename from src/combined.rs rename to src/windowed.rs index b0b646eaf6..fb9867168c 100644 --- a/src/combined.rs +++ b/src/windowed.rs @@ -5,7 +5,6 @@ use super::*; /// # Example /// /// ```no_run -/// # extern crate glutin; /// # use glutin::ContextTrait; /// # fn main() { /// let mut el = glutin::EventsLoop::new(); @@ -31,14 +30,19 @@ use super::*; /// } /// # } /// ``` -pub struct CombinedContext { +pub struct WindowedContext { context: Context, - window: Window, + window: WindowRef, } -impl CombinedContext { +pub enum WindowRef { + Owned(Window), + Arced(Arc), +} + +impl WindowedContext { /// Builds the given window along with the associated GL context, returning - /// the pair as a `CombinedContext`. + /// the pair as a `WindowedContext`. /// /// One notable limitation of the Wayland backend when it comes to shared /// contexts is that both contexts must use the same events loop. @@ -56,15 +60,42 @@ impl CombinedContext { let ContextBuilder { pf_reqs, gl_attr } = cb; let gl_attr = gl_attr.map_sharing(|ctx| &ctx.context); platform::Context::new(wb, el, &pf_reqs, &gl_attr).map( - |(window, context)| CombinedContext { - window, + |(window, context)| WindowedContext { + window: WindowRef::Owned(window), + context: Context { context }, + }, + ) + } + + /// Builds the GL context using the passed `Window`, returning the context + /// as a `WindowedContext`. + /// + /// One notable limitation of the Wayland backend when it comes to shared + /// contexts is that both contexts must use the same events loop. + /// + /// Errors can occur in two scenarios: + /// - If the window could not be created (via permission denied, + /// incompatible system, out of memory, etc.). This should be very rare. + /// - If the OpenGL context could not be created. This generally happens + /// because the underlying platform doesn't support a requested feature. + pub fn new_separated( + window: Arc, + cb: ContextBuilder, + el: &EventsLoop, + ) -> Result { + let ContextBuilder { pf_reqs, gl_attr } = cb; + let gl_attr = gl_attr.map_sharing(|ctx| &ctx.context); + + platform::Context::new_separated(&*window, el, &pf_reqs, &gl_attr).map( + |context| WindowedContext { + window: WindowRef::Arced(window), context: Context { context }, }, ) } /// Borrow the inner `Window`. - pub fn window(&self) -> &Window { + pub fn window(&self) -> &WindowRef { &self.window } @@ -105,7 +136,7 @@ impl CombinedContext { } } -impl ContextTrait for CombinedContext { +impl ContextTrait for WindowedContext { unsafe fn make_current(&self) -> Result<(), ContextError> { self.context.make_current() } @@ -123,9 +154,19 @@ impl ContextTrait for CombinedContext { } } -impl std::ops::Deref for CombinedContext { - type Target = Window; +impl std::ops::Deref for WindowedContext { + type Target = WindowRef; fn deref(&self) -> &Self::Target { &self.window } } + +impl std::ops::Deref for WindowRef { + type Target = Window; + fn deref(&self) -> &Self::Target { + match self { + WindowRef::Owned(ref w) => w, + WindowRef::Arced(w) => &*w, + } + } +}