glutin/lib.rs
1//! The purpose of this library is to provide an OpenGL context on as many
2//! platforms as possible.
3//!
4//! # Building a window
5//!
6//! There are two ways to create a window:
7//!
8//! - Calling `Window::new()`.
9//! - Calling `let builder = WindowBuilder::new()` then `builder.build()`.
10//!
11//! The first way is the simpliest way and will give you default values.
12//!
13//! The second way allows you to customize the way your window and GL context
14//! will look and behave.
15//!
16//! # Features
17//!
18//! This crate has two Cargo features: `window` and `headless`.
19//!
20//! - `window` allows you to create regular windows and enables the `WindowBuilder` object.
21//! - `headless` allows you to do headless rendering, and enables
22//! the `HeadlessRendererBuilder` object.
23//!
24//! By default only `window` is enabled.
25
26#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd", target_os = "windows"))]
27#[macro_use]
28extern crate lazy_static;
29
30#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
31#[macro_use]
32extern crate shared_library;
33
34extern crate libc;
35
36#[cfg(target_os = "windows")]
37extern crate winapi;
38#[cfg(target_os = "windows")]
39extern crate kernel32;
40#[cfg(target_os = "windows")]
41extern crate shell32;
42#[cfg(target_os = "windows")]
43extern crate gdi32;
44#[cfg(target_os = "windows")]
45extern crate user32;
46#[cfg(target_os = "windows")]
47extern crate dwmapi;
48#[cfg(any(target_os = "macos", target_os = "ios"))]
49#[macro_use]
50extern crate objc;
51#[cfg(target_os = "macos")]
52extern crate cgl;
53#[cfg(target_os = "macos")]
54extern crate cocoa;
55#[cfg(target_os = "macos")]
56extern crate core_foundation;
57#[cfg(target_os = "macos")]
58extern crate core_graphics;
59#[cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
60extern crate x11_dl;
61#[cfg(all(feature = "image",
62 any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd")))]
63extern crate image;
64
65pub use events::*;
66pub use headless::{HeadlessRendererBuilder, HeadlessContext};
67pub use window::{WindowProxy, PollEventsIterator, WaitEventsIterator};
68pub use window::{AvailableMonitorsIter, MonitorId, get_available_monitors, get_primary_monitor};
69pub use native_monitor::NativeMonitorId;
70
71use std::io;
72#[cfg(all(not(target_os = "macos"),not(target_os = "ios")))]
73use std::cmp::Ordering;
74use std::path::PathBuf;
75
76mod api;
77mod platform;
78mod events;
79mod headless;
80mod window;
81
82pub mod os;
83
84/// Represents an OpenGL context and the Window or environment around it.
85///
86/// # Example
87///
88/// ```ignore
89/// let window = Window::new().unwrap();
90///
91/// unsafe { window.make_current() };
92///
93/// loop {
94/// for event in window.poll_events() {
95/// match(event) {
96/// // process events here
97/// _ => ()
98/// }
99/// }
100///
101/// // draw everything here
102///
103/// window.swap_buffers();
104/// std::old_io::timer::sleep(17);
105/// }
106/// ```
107pub struct Window {
108 window: platform::Window,
109}
110
111/// Object that allows you to build windows.
112#[derive(Clone)]
113pub struct WindowBuilder<'a> {
114 /// The attributes to use to create the window.
115 pub window: WindowAttributes,
116
117 /// The attributes to use to create the context.
118 pub opengl: GlAttributes<&'a platform::Window>,
119
120 // Should be made public once it's stabilized.
121 pf_reqs: PixelFormatRequirements,
122
123 /// Platform-specific configuration.
124 platform_specific: platform::PlatformSpecificWindowBuilderAttributes,
125}
126
127/// Trait that describes objects that have access to an OpenGL context.
128pub trait GlContext {
129 /// Sets the context as the current context.
130 unsafe fn make_current(&self) -> Result<(), ContextError>;
131
132 /// Returns true if this context is the current one in this thread.
133 fn is_current(&self) -> bool;
134
135 /// Returns the address of an OpenGL function.
136 fn get_proc_address(&self, addr: &str) -> *const ();
137
138 /// Swaps the buffers in case of double or triple buffering.
139 ///
140 /// You should call this function every time you have finished rendering, or the image
141 /// may not be displayed on the screen.
142 ///
143 /// **Warning**: if you enabled vsync, this function will block until the next time the screen
144 /// is refreshed. However drivers can choose to override your vsync settings, which means that
145 /// you can't know in advance whether `swap_buffers` will block or not.
146 fn swap_buffers(&self) -> Result<(), ContextError>;
147
148 /// Returns the OpenGL API being used.
149 fn get_api(&self) -> Api;
150
151 /// Returns the pixel format of the main framebuffer of the context.
152 fn get_pixel_format(&self) -> PixelFormat;
153}
154
155/// Error that can happen while creating a window or a headless renderer.
156#[derive(Debug)]
157pub enum CreationError {
158 OsError(String),
159 /// TODO: remove this error
160 NotSupported,
161 NoBackendAvailable(Box<std::error::Error + Send>),
162 RobustnessNotSupported,
163 OpenGlVersionNotSupported,
164 NoAvailablePixelFormat,
165}
166
167impl CreationError {
168 fn to_string(&self) -> &str {
169 match *self {
170 CreationError::OsError(ref text) => &text,
171 CreationError::NotSupported => "Some of the requested attributes are not supported",
172 CreationError::NoBackendAvailable(_) => "No backend is available",
173 CreationError::RobustnessNotSupported => "You requested robustness, but it is \
174 not supported.",
175 CreationError::OpenGlVersionNotSupported => "The requested OpenGL version is not \
176 supported.",
177 CreationError::NoAvailablePixelFormat => "Couldn't find any pixel format that matches \
178 the criterias.",
179 }
180 }
181}
182
183impl std::fmt::Display for CreationError {
184 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
185 formatter.write_str(self.to_string())
186 }
187}
188
189impl std::error::Error for CreationError {
190 fn description(&self) -> &str {
191 self.to_string()
192 }
193
194 fn cause(&self) -> Option<&std::error::Error> {
195 match *self {
196 CreationError::NoBackendAvailable(ref err) => Some(&**err),
197 _ => None
198 }
199 }
200}
201
202/// Error that can happen when manipulating an OpenGL context.
203#[derive(Debug)]
204pub enum ContextError {
205 IoError(io::Error),
206 ContextLost,
207}
208
209impl ContextError {
210 fn to_string(&self) -> &str {
211 use std::error::Error;
212 match *self {
213 ContextError::IoError(ref err) => err.description(),
214 ContextError::ContextLost => "Context lost"
215 }
216 }
217}
218
219impl std::fmt::Display for ContextError {
220 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
221 formatter.write_str(self.to_string())
222 }
223}
224
225impl std::error::Error for ContextError {
226 fn description(&self) -> &str {
227 self.to_string()
228 }
229}
230
231/// All APIs related to OpenGL that you can possibly get while using glutin.
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum Api {
234 /// The classical OpenGL. Available on Windows, Linux, OS/X.
235 OpenGl,
236 /// OpenGL embedded system. Available on Linux, Android.
237 OpenGlEs,
238 /// OpenGL for the web. Very similar to OpenGL ES.
239 WebGl,
240}
241
242/// Describes the requested OpenGL context profiles.
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
244pub enum GlProfile {
245 /// Include all the immediate more functions and definitions.
246 Compatibility,
247 /// Include all the future-compatible functions and definitions.
248 Core,
249}
250
251/// Describes the OpenGL API and version that are being requested when a context is created.
252#[derive(Debug, Copy, Clone)]
253pub enum GlRequest {
254 /// Request the latest version of the "best" API of this platform.
255 ///
256 /// On desktop, will try OpenGL.
257 Latest,
258
259 /// Request a specific version of a specific API.
260 ///
261 /// Example: `GlRequest::Specific(Api::OpenGl, (3, 3))`.
262 Specific(Api, (u8, u8)),
263
264 /// If OpenGL is available, create an OpenGL context with the specified `opengl_version`.
265 /// Else if OpenGL ES or WebGL is available, create a context with the
266 /// specified `opengles_version`.
267 GlThenGles {
268 /// The version to use for OpenGL.
269 opengl_version: (u8, u8),
270 /// The version to use for OpenGL ES.
271 opengles_version: (u8, u8),
272 },
273}
274
275impl GlRequest {
276 /// Extract the desktop GL version, if any.
277 pub fn to_gl_version(&self) -> Option<(u8, u8)> {
278 match self {
279 &GlRequest::Specific(Api::OpenGl, version) => Some(version),
280 &GlRequest::GlThenGles { opengl_version: version, .. } => Some(version),
281 _ => None,
282 }
283 }
284}
285
286/// The minimum core profile GL context. Useful for getting the minimum
287/// required GL version while still running on OSX, which often forbids
288/// the compatibility profile features.
289pub static GL_CORE: GlRequest = GlRequest::Specific(Api::OpenGl, (3, 2));
290
291/// Specifies the tolerance of the OpenGL context to faults. If you accept raw OpenGL commands
292/// and/or raw shader code from an untrusted source, you should definitely care about this.
293#[derive(Debug, Copy, Clone, PartialEq, Eq)]
294pub enum Robustness {
295 /// Not everything is checked. Your application can crash if you do something wrong with your
296 /// shaders.
297 NotRobust,
298
299 /// The driver doesn't check anything. This option is very dangerous. Please know what you're
300 /// doing before using it. See the `GL_KHR_no_error` extension.
301 ///
302 /// Since this option is purely an optimisation, no error will be returned if the backend
303 /// doesn't support it. Instead it will automatically fall back to `NotRobust`.
304 NoError,
305
306 /// Everything is checked to avoid any crash. The driver will attempt to avoid any problem,
307 /// but if a problem occurs the behavior is implementation-defined. You are just guaranteed not
308 /// to get a crash.
309 RobustNoResetNotification,
310
311 /// Same as `RobustNoResetNotification` but the context creation doesn't fail if it's not
312 /// supported.
313 TryRobustNoResetNotification,
314
315 /// Everything is checked to avoid any crash. If a problem occurs, the context will enter a
316 /// "context lost" state. It must then be recreated. For the moment, glutin doesn't provide a
317 /// way to recreate a context with the same window :-/
318 RobustLoseContextOnReset,
319
320 /// Same as `RobustLoseContextOnReset` but the context creation doesn't fail if it's not
321 /// supported.
322 TryRobustLoseContextOnReset,
323}
324
325/// The behavior of the driver when you change the current context.
326#[derive(Debug, Copy, Clone, PartialEq, Eq)]
327pub enum ReleaseBehavior {
328 /// Doesn't do anything. Most notably doesn't flush.
329 None,
330
331 /// Flushes the context that was previously current as if `glFlush` was called.
332 Flush,
333}
334
335#[derive(Debug, Copy, Clone, PartialEq)]
336pub enum MouseCursor {
337 /// The platform-dependent default cursor.
338 Default,
339 /// A simple crosshair.
340 Crosshair,
341 /// A hand (often used to indicate links in web browsers).
342 Hand,
343 /// Self explanatory.
344 Arrow,
345 /// Indicates something is to be moved.
346 Move,
347 /// Indicates text that may be selected or edited.
348 Text,
349 /// Program busy indicator.
350 Wait,
351 /// Help indicator (often rendered as a "?")
352 Help,
353 /// Progress indicator. Shows that processing is being done. But in contrast
354 /// with "Wait" the user may still interact with the program. Often rendered
355 /// as a spinning beach ball, or an arrow with a watch or hourglass.
356 Progress,
357
358 /// Cursor showing that something cannot be done.
359 NotAllowed,
360 ContextMenu,
361 NoneCursor,
362 Cell,
363 VerticalText,
364 Alias,
365 Copy,
366 NoDrop,
367 Grab,
368 Grabbing,
369 AllScroll,
370 ZoomIn,
371 ZoomOut,
372
373 /// Indicate that some edge is to be moved. For example, the 'SeResize' cursor
374 /// is used when the movement starts from the south-east corner of the box.
375 EResize,
376 NResize,
377 NeResize,
378 NwResize,
379 SResize,
380 SeResize,
381 SwResize,
382 WResize,
383 EwResize,
384 NsResize,
385 NeswResize,
386 NwseResize,
387 ColResize,
388 RowResize,
389}
390
391/// Describes how glutin handles the cursor.
392#[derive(Debug, Copy, Clone, PartialEq)]
393pub enum CursorState {
394 /// Normal cursor behavior.
395 Normal,
396
397 /// The cursor will be invisible when over the window.
398 Hide,
399
400 /// Grabs the mouse cursor. The cursor's motion will be confined to this
401 /// window and the window has exclusive access to further events regarding
402 /// the cursor.
403 ///
404 /// This is useful for first-person cameras for example.
405 Grab,
406}
407
408/// Describes a possible format. Unused.
409#[allow(missing_docs)]
410#[derive(Debug, Clone)]
411pub struct PixelFormat {
412 pub hardware_accelerated: bool,
413 pub color_bits: u8,
414 pub alpha_bits: u8,
415 pub depth_bits: u8,
416 pub stencil_bits: u8,
417 pub stereoscopy: bool,
418 pub double_buffer: bool,
419 pub multisampling: Option<u16>,
420 pub srgb: bool,
421}
422
423/// Describes how the backend should choose a pixel format.
424// TODO: swap method? (swap, copy)
425#[derive(Clone, Debug)]
426pub struct PixelFormatRequirements {
427 /// If true, only hardware-accelerated formats will be conisdered. If false, only software
428 /// renderers. `None` means "don't care". Default is `Some(true)`.
429 pub hardware_accelerated: Option<bool>,
430
431 /// Minimum number of bits for the color buffer, excluding alpha. `None` means "don't care".
432 /// The default is `Some(24)`.
433 pub color_bits: Option<u8>,
434
435 /// If true, the color buffer must be in a floating point format. Default is `false`.
436 ///
437 /// Using floating points allows you to write values outside of the `[0.0, 1.0]` range.
438 pub float_color_buffer: bool,
439
440 /// Minimum number of bits for the alpha in the color buffer. `None` means "don't care".
441 /// The default is `Some(8)`.
442 pub alpha_bits: Option<u8>,
443
444 /// Minimum number of bits for the depth buffer. `None` means "don't care".
445 /// The default value is `Some(24)`.
446 pub depth_bits: Option<u8>,
447
448 /// Minimum number of bits for the depth buffer. `None` means "don't care".
449 /// The default value is `Some(8)`.
450 pub stencil_bits: Option<u8>,
451
452 /// If true, only double-buffered formats will be considered. If false, only single-buffer
453 /// formats. `None` means "don't care". The default is `Some(true)`.
454 pub double_buffer: Option<bool>,
455
456 /// Contains the minimum number of samples per pixel in the color, depth and stencil buffers.
457 /// `None` means "don't care". Default is `None`.
458 /// A value of `Some(0)` indicates that multisampling must not be enabled.
459 pub multisampling: Option<u16>,
460
461 /// If true, only stereoscopic formats will be considered. If false, only non-stereoscopic
462 /// formats. The default is `false`.
463 pub stereoscopy: bool,
464
465 /// If true, only sRGB-capable formats will be considered. If false, don't care.
466 /// The default is `false`.
467 pub srgb: bool,
468
469 /// The behavior when changing the current context. Default is `Flush`.
470 pub release_behavior: ReleaseBehavior,
471}
472
473impl Default for PixelFormatRequirements {
474 #[inline]
475 fn default() -> PixelFormatRequirements {
476 PixelFormatRequirements {
477 hardware_accelerated: Some(true),
478 color_bits: Some(24),
479 float_color_buffer: false,
480 alpha_bits: Some(8),
481 depth_bits: Some(24),
482 stencil_bits: Some(8),
483 double_buffer: None,
484 multisampling: None,
485 stereoscopy: false,
486 srgb: false,
487 release_behavior: ReleaseBehavior::Flush,
488 }
489 }
490}
491
492/// A wrapper for a native window pointer.
493#[derive(Debug, Clone)]
494pub struct WindowID {
495 pub window: *mut libc::c_void,
496}
497
498impl WindowID {
499 pub fn new(window: *mut libc::c_void) -> WindowID {
500 WindowID {
501 window: window
502 }
503 }
504}
505
506unsafe impl Send for WindowID {}
507unsafe impl Sync for WindowID {}
508
509/// Attributes to use when creating a window.
510#[derive(Clone)]
511pub struct WindowAttributes {
512 /// The dimensions of the window. If this is `None`, some platform-specific dimensions will be
513 /// used.
514 ///
515 /// The default is `None`.
516 pub dimensions: Option<(u32, u32)>,
517
518 /// The minimum dimensions a window can be, If this is `None`, the window will have no minimum dimensions (aside from reserved).
519 ///
520 /// The default is `None`.
521 pub min_dimensions: Option<(u32, u32)>,
522
523 /// The maximum dimensions a window can be, If this is `None`, the maximum will have no maximum or will be set to the primary monitor's dimensions by the platform.
524 ///
525 /// The default is `None`.
526 pub max_dimensions: Option<(u32, u32)>,
527
528 /// If `Some`, the window will be in fullscreen mode with the given monitor.
529 ///
530 /// The default is `None`.
531 pub monitor: Option<platform::MonitorId>,
532
533 /// The title of the window in the title bar.
534 ///
535 /// The default is `"glutin window"`.
536 pub title: String,
537
538 /// Whether the window should be immediately visible upon creation.
539 ///
540 /// The default is `true`.
541 pub visible: bool,
542
543 /// Whether the the window should be transparent. If this is true, writing colors
544 /// with alpha values different than `1.0` will produce a transparent window.
545 ///
546 /// The default is `false`.
547 pub transparent: bool,
548
549 /// Whether the window should have borders and bars.
550 ///
551 /// The default is `true`.
552 pub decorations: bool,
553
554 /// [iOS only] Enable multitouch, see [UIView#multipleTouchEnabled]
555 /// (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instp/UIView/multipleTouchEnabled)
556 pub multitouch: bool,
557
558 /// A path to an icon for the window. This may not be supported on every windowing system.
559 /// If present, this path must reference a PNG file.
560 ///
561 /// The default is `None`.
562 pub icon: Option<PathBuf>,
563
564 /// Parent Window.
565 ///
566 /// The default is `None`.
567 pub parent: Option<WindowID>,
568}
569
570impl Default for WindowAttributes {
571 #[inline]
572 fn default() -> WindowAttributes {
573 WindowAttributes {
574 dimensions: None,
575 min_dimensions: None,
576 max_dimensions: None,
577 monitor: None,
578 title: "glutin window".to_owned(),
579 visible: true,
580 transparent: false,
581 decorations: true,
582 multitouch: false,
583 icon: None,
584 parent: None,
585 }
586 }
587}
588
589/// Attributes to use when creating an OpenGL context.
590#[derive(Clone)]
591pub struct GlAttributes<S> {
592 /// An existing context to share the new the context with.
593 ///
594 /// The default is `None`.
595 pub sharing: Option<S>,
596
597 /// Version to try create. See `GlRequest` for more infos.
598 ///
599 /// The default is `Latest`.
600 pub version: GlRequest,
601
602 /// OpenGL profile to use.
603 ///
604 /// The default is `None`.
605 pub profile: Option<GlProfile>,
606
607 /// Whether to enable the `debug` flag of the context.
608 ///
609 /// Debug contexts are usually slower but give better error reporting.
610 ///
611 /// The default is `true` in debug mode and `false` in release mode.
612 pub debug: bool,
613
614 /// How the OpenGL context should detect errors.
615 ///
616 /// The default is `NotRobust` because this is what is typically expected when you create an
617 /// OpenGL context. However for safety you should consider `TryRobustLoseContextOnReset`.
618 pub robustness: Robustness,
619
620 /// Whether to use vsync. If vsync is enabled, calling `swap_buffers` will block until the
621 /// screen refreshes. This is typically used to prevent screen tearing.
622 ///
623 /// The default is `false`.
624 pub vsync: bool,
625}
626
627impl<S> GlAttributes<S> {
628 /// Turns the `sharing` parameter into another type by calling a closure.
629 #[inline]
630 pub fn map_sharing<F, T>(self, f: F) -> GlAttributes<T> where F: FnOnce(S) -> T {
631 GlAttributes {
632 sharing: self.sharing.map(f),
633 version: self.version,
634 profile: self.profile,
635 debug: self.debug,
636 robustness: self.robustness,
637 vsync: self.vsync,
638 }
639 }
640}
641
642impl<S> Default for GlAttributes<S> {
643 #[inline]
644 fn default() -> GlAttributes<S> {
645 GlAttributes {
646 sharing: None,
647 version: GlRequest::Latest,
648 profile: None,
649 debug: cfg!(debug_assertions),
650 robustness: Robustness::NotRobust,
651 vsync: false,
652 }
653 }
654}
655
656mod native_monitor {
657 /// Native platform identifier for a monitor. Different platforms use fundamentally different types
658 /// to represent a monitor ID.
659 #[derive(Clone, PartialEq, Eq)]
660 pub enum NativeMonitorId {
661 /// Cocoa and X11 use a numeric identifier to represent a monitor.
662 Numeric(u32),
663
664 /// Win32 uses a Unicode string to represent a monitor.
665 Name(String),
666
667 /// Other platforms (Android) don't support monitor identification.
668 Unavailable
669 }
670}