#![cfg_attr(
target_os = "windows",
doc = "\
[`RawContextExt`]: os/windows/trait.RawContextExt.html
"
)]
#![cfg_attr(
not(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "windows",
target_os = "openbsd",
)),
doc = "\
[`RawContextExt`]: os/index.html
"
)]
#![cfg_attr(
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
),
doc = "\
[`RawContextExt`]: os/unix/trait.RawContextExt.html
"
)]
#![cfg(any(
target_os = "linux",
target_os = "ios",
target_os = "windows",
target_os = "macos",
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "emscripten",
))]
#![deny(
warnings,
missing_debug_implementations,
//missing_docs,
)]
#![allow(intra_doc_link_resolution_failure)]
#[cfg(any(
target_os = "windows",
target_os = "linux",
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
#[macro_use]
extern crate lazy_static;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[macro_use]
extern crate objc;
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
#[macro_use]
extern crate log;
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
#[macro_use]
extern crate derivative;
pub mod platform;
mod api;
mod context;
mod platform_impl;
mod windowed;
pub use crate::context::*;
pub use crate::windowed::*;
pub use winit::*;
use winit::error::OsError;
use std::io;
#[derive(Debug, Clone)]
pub struct ContextBuilder<'a, T: ContextCurrentState> {
pub gl_attr: GlAttributes<&'a Context<T>>,
pub pf_reqs: PixelFormatRequirements,
}
impl<'a> ContextBuilder<'a, NotCurrent> {
pub fn new() -> Self {
ContextBuilder {
pf_reqs: std::default::Default::default(),
gl_attr: std::default::Default::default(),
}
}
}
impl<'a, T: ContextCurrentState> ContextBuilder<'a, T> {
#[inline]
pub fn with_gl(mut self, request: GlRequest) -> Self {
self.gl_attr.version = request;
self
}
#[inline]
pub fn with_gl_profile(mut self, profile: GlProfile) -> Self {
self.gl_attr.profile = Some(profile);
self
}
#[inline]
pub fn with_gl_debug_flag(mut self, flag: bool) -> Self {
self.gl_attr.debug = flag;
self
}
#[inline]
pub fn with_gl_robustness(mut self, robustness: Robustness) -> Self {
self.gl_attr.robustness = robustness;
self
}
#[inline]
pub fn with_vsync(mut self, vsync: bool) -> Self {
self.gl_attr.vsync = vsync;
self
}
#[inline]
pub fn with_shared_lists<T2: ContextCurrentState>(
self,
other: &'a Context<T2>,
) -> ContextBuilder<'a, T2> {
ContextBuilder {
gl_attr: self.gl_attr.set_sharing(Some(other)),
pf_reqs: self.pf_reqs,
}
}
#[inline]
pub fn with_multisampling(mut self, samples: u16) -> Self {
self.pf_reqs.multisampling = match samples {
0 => None,
_ => {
assert!(samples.is_power_of_two());
Some(samples)
}
};
self
}
#[inline]
pub fn with_depth_buffer(mut self, bits: u8) -> Self {
self.pf_reqs.depth_bits = Some(bits);
self
}
#[inline]
pub fn with_stencil_buffer(mut self, bits: u8) -> Self {
self.pf_reqs.stencil_bits = Some(bits);
self
}
#[inline]
pub fn with_pixel_format(mut self, color_bits: u8, alpha_bits: u8) -> Self {
self.pf_reqs.color_bits = Some(color_bits);
self.pf_reqs.alpha_bits = Some(alpha_bits);
self
}
#[inline]
pub fn with_stereoscopy(mut self) -> Self {
self.pf_reqs.stereoscopy = true;
self
}
#[inline]
pub fn with_srgb(mut self, srgb_enabled: bool) -> Self {
self.pf_reqs.srgb = srgb_enabled;
self
}
#[inline]
pub fn with_double_buffer(mut self, double_buffer: Option<bool>) -> Self {
self.pf_reqs.double_buffer = double_buffer;
self
}
#[inline]
pub fn with_hardware_acceleration(
mut self,
acceleration: Option<bool>,
) -> Self {
self.pf_reqs.hardware_accelerated = acceleration;
self
}
}
#[derive(Debug)]
pub enum CreationError {
OsError(String),
NotSupported(String),
NoBackendAvailable(Box<dyn std::error::Error + Send + Sync>),
RobustnessNotSupported,
OpenGlVersionNotSupported,
NoAvailablePixelFormat,
PlatformSpecific(String),
Window(OsError),
CreationErrors(Vec<Box<CreationError>>),
}
impl CreationError {
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
pub(crate) fn append(self, err: CreationError) -> Self {
match self {
CreationError::CreationErrors(mut errs) => {
errs.push(Box::new(err));
CreationError::CreationErrors(errs)
}
_ => CreationError::CreationErrors(vec![
Box::new(err),
Box::new(self),
]),
}
}
fn to_string(&self) -> &str {
match *self {
CreationError::OsError(ref text)
| CreationError::NotSupported(ref text) => &text,
CreationError::NoBackendAvailable(_) => "No backend is available",
CreationError::RobustnessNotSupported => {
"You requested robustness, but it is not supported."
}
CreationError::OpenGlVersionNotSupported => {
"The requested OpenGL version is not supported."
}
CreationError::NoAvailablePixelFormat => {
"Couldn't find any pixel format that matches the criteria."
}
CreationError::PlatformSpecific(ref text) => &text,
CreationError::Window(ref err) => {
std::error::Error::description(err)
}
CreationError::CreationErrors(_) => "Received multiple errors.",
}
}
}
impl std::fmt::Display for CreationError {
fn fmt(
&self,
formatter: &mut std::fmt::Formatter,
) -> Result<(), std::fmt::Error> {
formatter.write_str(self.to_string())?;
if let CreationError::CreationErrors(ref es) = *self {
use std::fmt::Debug;
write!(formatter, " Errors: `")?;
es.fmt(formatter)?;
write!(formatter, "`")?;
}
if let Some(err) = std::error::Error::source(self) {
write!(formatter, ": {}", err)?;
}
Ok(())
}
}
impl std::error::Error for CreationError {
fn description(&self) -> &str {
self.to_string()
}
fn cause(&self) -> Option<&dyn std::error::Error> {
match *self {
CreationError::NoBackendAvailable(ref err) => Some(&**err),
CreationError::Window(ref err) => Some(err),
_ => None,
}
}
}
impl From<OsError> for CreationError {
fn from(err: OsError) -> Self {
CreationError::Window(err)
}
}
#[derive(Debug)]
pub enum ContextError {
OsError(String),
IoError(io::Error),
ContextLost,
}
impl ContextError {
fn to_string(&self) -> &str {
use std::error::Error;
match *self {
ContextError::OsError(ref string) => string,
ContextError::IoError(ref err) => err.description(),
ContextError::ContextLost => "Context lost",
}
}
}
impl std::fmt::Display for ContextError {
fn fmt(
&self,
formatter: &mut std::fmt::Formatter,
) -> Result<(), std::fmt::Error> {
formatter.write_str(self.to_string())
}
}
impl std::error::Error for ContextError {
fn description(&self) -> &str {
self.to_string()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Api {
OpenGl,
OpenGlEs,
WebGl,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GlProfile {
Compatibility,
Core,
}
#[derive(Debug, Copy, Clone)]
pub enum GlRequest {
Latest,
Specific(Api, (u8, u8)),
GlThenGles {
opengl_version: (u8, u8),
opengles_version: (u8, u8),
},
}
impl GlRequest {
pub fn to_gl_version(&self) -> Option<(u8, u8)> {
match self {
&GlRequest::Specific(Api::OpenGl, opengl_version) => {
Some(opengl_version)
}
&GlRequest::GlThenGles { opengl_version, .. } => {
Some(opengl_version)
}
_ => None,
}
}
}
pub static GL_CORE: GlRequest = GlRequest::Specific(Api::OpenGl, (3, 2));
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Robustness {
NotRobust,
NoError,
RobustNoResetNotification,
TryRobustNoResetNotification,
RobustLoseContextOnReset,
TryRobustLoseContextOnReset,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ReleaseBehavior {
None,
Flush,
}
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct PixelFormat {
pub hardware_accelerated: bool,
pub color_bits: u8,
pub alpha_bits: u8,
pub depth_bits: u8,
pub stencil_bits: u8,
pub stereoscopy: bool,
pub double_buffer: bool,
pub multisampling: Option<u16>,
pub srgb: bool,
}
#[derive(Clone, Debug)]
pub struct PixelFormatRequirements {
pub hardware_accelerated: Option<bool>,
pub color_bits: Option<u8>,
pub float_color_buffer: bool,
pub alpha_bits: Option<u8>,
pub depth_bits: Option<u8>,
pub stencil_bits: Option<u8>,
pub double_buffer: Option<bool>,
pub multisampling: Option<u16>,
pub stereoscopy: bool,
pub srgb: bool,
pub release_behavior: ReleaseBehavior,
pub(crate) x11_visual_xid: Option<std::os::raw::c_ulong>,
}
impl Default for PixelFormatRequirements {
#[inline]
fn default() -> PixelFormatRequirements {
PixelFormatRequirements {
hardware_accelerated: Some(true),
color_bits: Some(24),
float_color_buffer: false,
alpha_bits: Some(8),
depth_bits: Some(24),
stencil_bits: Some(8),
double_buffer: None,
multisampling: None,
stereoscopy: false,
srgb: false,
release_behavior: ReleaseBehavior::Flush,
x11_visual_xid: None,
}
}
}
#[derive(Clone, Debug)]
pub struct GlAttributes<S> {
pub sharing: Option<S>,
pub version: GlRequest,
pub profile: Option<GlProfile>,
pub debug: bool,
pub robustness: Robustness,
pub vsync: bool,
}
impl<S> GlAttributes<S> {
#[inline]
pub fn map_sharing<F, T>(self, f: F) -> GlAttributes<T>
where
F: FnOnce(S) -> T,
{
GlAttributes {
sharing: self.sharing.map(f),
version: self.version,
profile: self.profile,
debug: self.debug,
robustness: self.robustness,
vsync: self.vsync,
}
}
#[inline]
fn set_sharing<T>(self, sharing: Option<T>) -> GlAttributes<T> {
GlAttributes {
sharing,
version: self.version,
profile: self.profile,
debug: self.debug,
robustness: self.robustness,
vsync: self.vsync,
}
}
}
impl<S> Default for GlAttributes<S> {
#[inline]
fn default() -> GlAttributes<S> {
GlAttributes {
sharing: None,
version: GlRequest::Latest,
profile: None,
debug: cfg!(debug_assertions),
robustness: Robustness::NotRobust,
vsync: false,
}
}
}