diff --git a/examples/threads.rs b/examples/threads.rs index a2cc89f0..e63b5218 100644 --- a/examples/threads.rs +++ b/examples/threads.rs @@ -7,8 +7,8 @@ use euclid::default::{Point2D, Rect, Size2D, Vector2D}; use gl::types::{GLenum, GLint, GLuint}; use std::sync::mpsc::{self, Receiver, Sender}; use std::thread; -use surfman::{declare_surfman, SurfaceAccess, SurfaceTexture, SurfaceType}; -use surfman::{Adapter, Connection, Context, ContextDescriptor, Device, GLApi, Surface}; +use surfman::{declare_surfman, ContextDescriptor, SurfaceAccess, SurfaceTexture, SurfaceType}; +use surfman::{Adapter, Connection, Context, Device, GLApi, Surface}; #[cfg(not(target_os = "android"))] use self::common::FilesystemResourceLoader; diff --git a/src/adapter.rs b/src/adapter.rs index 45aaf281..a12a251f 100644 --- a/src/adapter.rs +++ b/src/adapter.rs @@ -12,9 +12,9 @@ use crate::base::io_surface::adapter::AppleAdapter; use crate::free_unix::adapter::FreeUnixAdapter; #[cfg(any(android_platform, ohos_platform))] use crate::hardware_buffer::adapter::HardwareBufferAdapter; +use crate::macros::enum_conversion; #[cfg(all(windows_platform, not(feature = "sm-no-wgl")))] use crate::wgl::adapter::WglAdapter; -use crate::{macros::enum_conversion, Error}; /// A power usage preference for selecting an adapter. #[derive(Copy, Clone, Debug, Default)] @@ -69,17 +69,24 @@ pub enum Adapter { } #[cfg(all(windows_platform, feature = "sm-angle"))] -enum_conversion!(Adapter, Angle, AngleAdapter, angle); +enum_conversion!(Adapter, Angle, AngleAdapter, angle, IncompatibleAdapter); #[cfg(macos_platform)] -enum_conversion!(Adapter, Apple, AppleAdapter, apple); +enum_conversion!(Adapter, Apple, AppleAdapter, apple, IncompatibleAdapter); #[cfg(free_unix)] -enum_conversion!(Adapter, FreeUnix, FreeUnixAdapter, free_unix); +enum_conversion!( + Adapter, + FreeUnix, + FreeUnixAdapter, + free_unix, + IncompatibleAdapter +); #[cfg(any(android_platform, ohos_platform))] enum_conversion!( Adapter, HardwareBuffer, HardwareBufferAdapter, - hardware_buffer + hardware_buffer, + IncompatibleAdapter ); #[cfg(all(windows_platform, not(feature = "sm-no-wgl")))] -enum_conversion!(Adapter, Wgl, WglAdapter, wgl); +enum_conversion!(Adapter, Wgl, WglAdapter, wgl, IncompatibleAdapter); diff --git a/src/angle/context.rs b/src/angle/context.rs index 02f08d8a..ef063fc3 100644 --- a/src/angle/context.rs +++ b/src/angle/context.rs @@ -1,7 +1,7 @@ //! Wrapper for EGL contexts managed by ANGLE using Direct3D 11 as a backend on Windows. use super::surface::Surface; -pub use crate::base::egl::context::{ContextDescriptor, NativeContext}; +pub use crate::base::egl::context::NativeContext; use crate::base::egl::surface::ExternalEGLSurfaces; use crate::context::ContextID; use crate::egl; diff --git a/src/angle/device.rs b/src/angle/device.rs index 260df1ff..f6d3eb84 100644 --- a/src/angle/device.rs +++ b/src/angle/device.rs @@ -2,7 +2,7 @@ use super::adapter::AngleAdapter; use crate::angle::connection::Connection; -use crate::angle::context::{Context, ContextDescriptor, NativeContext}; +use crate::angle::context::{Context, NativeContext}; use crate::angle::surface::{ Surface, SurfaceDataGuard, SurfaceTexture, Synchronization, Win32Objects, }; @@ -20,8 +20,10 @@ use crate::egl::types::{ EGLAttrib, EGLConfig, EGLDeviceEXT, EGLDisplay, EGLNativeWindowType, EGLSurface, EGLint, }; use crate::surface::Framebuffer; +use crate::EglContextDescriptor; use crate::{ - egl, gl, Adapter, ContextAttributes, Error, GLApi, Gl, SurfaceAccess, SurfaceInfo, SurfaceType, + egl, gl, Adapter, ContextAttributes, ContextDescriptor, Error, GLApi, Gl, SurfaceAccess, + SurfaceInfo, SurfaceType, }; use euclid::default::Size2D; use glow::HasContext; @@ -244,7 +246,7 @@ impl Device { attributes: &ContextAttributes, ) -> Result { unsafe { - ContextDescriptor::new( + EglContextDescriptor::new( self.egl_display, attributes, &[ @@ -256,6 +258,7 @@ impl Device { egl::OPENGL_ES2_BIT as EGLint, ], ) + .map(Into::into) } } @@ -273,7 +276,7 @@ impl Device { let egl_context = unsafe { context::create_context( self.egl_display, - descriptor, + descriptor.egl()?, share_with.map_or(egl::NO_CONTEXT, |ctx| ctx.egl_context), self.gl_api(), )? @@ -370,7 +373,12 @@ impl Device { /// Returns the descriptor that this context was created with. pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { unsafe { - ContextDescriptor::from_egl_context(&context.gl, self.egl_display, context.egl_context) + EglContextDescriptor::from_egl_context( + &context.gl, + self.egl_display, + context.egl_context, + ) + .into() } } @@ -428,6 +436,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); unsafe { context_descriptor.attributes(self.egl_display) } } @@ -446,7 +457,7 @@ impl Device { #[inline] pub(crate) fn context_descriptor_to_egl_config( &self, - context_descriptor: &ContextDescriptor, + context_descriptor: &EglContextDescriptor, ) -> EGLConfig { unsafe { context::egl_config_from_id(self.egl_display, context_descriptor.egl_config_id) } } @@ -630,6 +641,7 @@ impl Device { texture: Option>, ) -> Result { let context_descriptor = self.context_descriptor(context); + let context_descriptor = context_descriptor.egl()?.clone(); let egl_config = self.context_descriptor_to_egl_config(&context_descriptor); unsafe { @@ -732,7 +744,7 @@ impl Device { context: &Context, egl_native_window: EGLNativeWindowType, ) -> Result { - let context_descriptor = self.context_descriptor(context); + let context_descriptor = self.context_descriptor(context).egl()?.clone(); let egl_config = self.context_descriptor_to_egl_config(&context_descriptor); unsafe { diff --git a/src/angle/surface.rs b/src/angle/surface.rs index f05658d3..8ebe7f83 100644 --- a/src/angle/surface.rs +++ b/src/angle/surface.rs @@ -1,12 +1,11 @@ //! Surface management for Direct3D 11 on Windows using the ANGLE library as a frontend. -use super::context::ContextDescriptor; use super::device::Device; use crate::base::egl::device::EGL_FUNCTIONS; use crate::context::ContextID; use crate::egl::types::EGLSurface; use crate::egl::{self}; -use crate::{Error, SurfaceID}; +use crate::{EglContextDescriptor, Error, SurfaceID}; use euclid::default::Size2D; use std::fmt::{self, Debug, Formatter}; @@ -37,7 +36,7 @@ pub struct Surface { pub(crate) egl_surface: EGLSurface, pub(crate) size: Size2D, pub(crate) context_id: ContextID, - pub(crate) context_descriptor: ContextDescriptor, + pub(crate) context_descriptor: EglContextDescriptor, pub(crate) win32_objects: Win32Objects, } diff --git a/src/base/egl/context.rs b/src/base/egl/context.rs index 36ecf7ce..571dd49b 100644 --- a/src/base/egl/context.rs +++ b/src/base/egl/context.rs @@ -47,7 +47,7 @@ pub struct NativeContext { /// /// These are local to a device. #[derive(Clone)] -pub struct ContextDescriptor { +pub struct EglContextDescriptor { pub(crate) egl_config_id: EGLint, pub(crate) gl_version: GLVersion, pub(crate) compatibility_profile: bool, @@ -112,7 +112,7 @@ impl Drop for EGLBackedContext { impl EGLBackedContext { pub(crate) unsafe fn new( egl_display: EGLDisplay, - descriptor: &ContextDescriptor, + descriptor: &EglContextDescriptor, share_with: Option<&EGLBackedContext>, gl_api: GLApi, ) -> Result { @@ -316,12 +316,12 @@ impl NativeContext { } } -impl ContextDescriptor { +impl EglContextDescriptor { pub(crate) unsafe fn new( egl_display: EGLDisplay, attributes: &ContextAttributes, extra_config_attributes: &[EGLint], - ) -> Result { + ) -> Result { let flags = attributes.flags; let alpha_size = if flags.contains(ContextAttributeFlags::ALPHA) { @@ -430,7 +430,7 @@ impl ContextDescriptor { let egl_config_id = get_config_attr(egl_display, egl_config, egl::CONFIG_ID as EGLint); let gl_version = attributes.version; - Ok(ContextDescriptor { + Ok(EglContextDescriptor { egl_config_id, gl_version, compatibility_profile, @@ -442,12 +442,12 @@ impl ContextDescriptor { gl: &Gl, egl_display: EGLDisplay, egl_context: EGLContext, - ) -> ContextDescriptor { + ) -> EglContextDescriptor { let egl_config_id = get_context_attr(egl_display, egl_context, egl::CONFIG_ID as EGLint); let gl_version = GLVersion::current(gl); let compatibility_profile = context::current_context_uses_compatibility_profile(gl); - ContextDescriptor { + EglContextDescriptor { egl_config_id, gl_version, compatibility_profile, @@ -508,7 +508,7 @@ impl ContextDescriptor { pub(crate) unsafe fn create_context( egl_display: EGLDisplay, - descriptor: &ContextDescriptor, + descriptor: &EglContextDescriptor, share_with: EGLContext, gl_api: GLApi, ) -> Result { diff --git a/src/cgl/context.rs b/src/cgl/context.rs index c734e463..2e043b66 100644 --- a/src/cgl/context.rs +++ b/src/cgl/context.rs @@ -51,11 +51,11 @@ impl Drop for Context { /// Options that control OpenGL rendering. /// /// This corresponds to a "pixel format" object in many APIs. These are thread-safe. -pub struct ContextDescriptor { +pub struct CglContextDescriptor { pub(crate) cgl_pixel_format: CGLPixelFormatObj, } -impl Drop for ContextDescriptor { +impl Drop for CglContextDescriptor { // These have been verified to be thread-safe. #[inline] fn drop(&mut self) { @@ -65,18 +65,18 @@ impl Drop for ContextDescriptor { } } -impl Clone for ContextDescriptor { +impl Clone for CglContextDescriptor { #[inline] - fn clone(&self) -> ContextDescriptor { + fn clone(&self) -> CglContextDescriptor { unsafe { - ContextDescriptor { + CglContextDescriptor { cgl_pixel_format: CGLRetainPixelFormat(self.cgl_pixel_format), } } } } -unsafe impl Send for ContextDescriptor {} +unsafe impl Send for CglContextDescriptor {} #[must_use] pub(crate) struct CurrentContextGuard { diff --git a/src/cgl/device.rs b/src/cgl/device.rs index 54e96ef3..dc78e0fa 100644 --- a/src/cgl/device.rs +++ b/src/cgl/device.rs @@ -1,6 +1,7 @@ //! A handle to the device. (This is a no-op, because handles are implicit in Apple's Core OpenGL.) use super::connection::Connection; +use super::context::CglContextDescriptor; use crate::base::io_surface::device::Device as SystemDevice; use crate::cgl::context::{CurrentContextGuard, NativeContext}; use crate::cgl::error::ToWindowingApiError; @@ -164,7 +165,7 @@ impl Device { return Err(Error::NoPixelFormatFound); } - Ok(ContextDescriptor { cgl_pixel_format }) + Ok(CglContextDescriptor { cgl_pixel_format }.into()) } } @@ -186,7 +187,7 @@ impl Device { // Create the CGL context. let mut cgl_context = ptr::null_mut(); let err = CGLCreateContext( - descriptor.cgl_pixel_format, + descriptor.cgl()?.cgl_pixel_format, share_with.map_or(ptr::null_mut(), |ctx| ctx.cgl_context), &mut cgl_context, ); @@ -257,7 +258,7 @@ impl Device { unsafe { let mut cgl_pixel_format = CGLGetPixelFormat(context.cgl_context); cgl_pixel_format = CGLRetainPixelFormat(cgl_pixel_format); - ContextDescriptor { cgl_pixel_format } + CglContextDescriptor { cgl_pixel_format }.into() } } @@ -395,6 +396,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .cgl() + .expect("Passed incompatible context descriptor"); unsafe { let alpha_size = get_pixel_format_attribute(context_descriptor, kCGLPFAAlphaSize); let depth_size = get_pixel_format_attribute(context_descriptor, kCGLPFADepthSize); @@ -423,7 +427,7 @@ impl Device { } unsafe fn get_pixel_format_attribute( - context_descriptor: &ContextDescriptor, + context_descriptor: &CglContextDescriptor, attribute: CGLPixelFormatAttribute, ) -> i32 { let mut value = 0; diff --git a/src/context_descriptor.rs b/src/context_descriptor.rs new file mode 100644 index 00000000..968645d1 --- /dev/null +++ b/src/context_descriptor.rs @@ -0,0 +1,52 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#[cfg(macos_platform)] +use crate::cgl::context::CglContextDescriptor; +use crate::macros::enum_conversion; +#[cfg(all(windows_platform, not(feature = "sm-no-wgl")))] +use crate::wgl::context::WglContextDescriptor; +#[cfg(any(android_platform, angle, free_unix, ohos_platform))] +use crate::EglContextDescriptor; + +/// Information needed to create a context. Some APIs call this a "config" or a "pixel format". +/// +/// These are local to a device. +#[derive(Clone)] +pub enum ContextDescriptor { + /// A [`ContextDescriptor`] for CGL platforms. + #[cfg(macos_platform)] + Cgl(CglContextDescriptor), + /// A [`ContextDescriptor`] for EGL platforms. + #[cfg(any(android_platform, angle, free_unix, ohos_platform))] + Egl(EglContextDescriptor), + /// A [`ContextDescriptor`] for WGL platforms. + #[cfg(all(windows_platform, not(feature = "sm-no-wgl")))] + Wgl(WglContextDescriptor), +} + +#[cfg(macos_platform)] +enum_conversion!( + ContextDescriptor, + Cgl, + CglContextDescriptor, + cgl, + IncompatibleContextDescriptor +); +#[cfg(any(android_platform, angle, free_unix, ohos_platform))] +enum_conversion!( + ContextDescriptor, + Egl, + EglContextDescriptor, + egl, + IncompatibleContextDescriptor +); +#[cfg(all(windows_platform, not(feature = "sm-no-wgl")))] +enum_conversion!( + ContextDescriptor, + Wgl, + WglContextDescriptor, + wgl, + IncompatibleContextDescriptor +); diff --git a/src/device.rs b/src/device.rs index abefb6b5..6bb1152c 100644 --- a/src/device.rs +++ b/src/device.rs @@ -2,7 +2,8 @@ use super::connection::Connection as ConnectionInterface; use crate::{ - Adapter, ContextAttributes, ContextID, Error, GLApi, SurfaceAccess, SurfaceInfo, SurfaceType, + Adapter, ContextAttributes, ContextDescriptor, ContextID, Error, GLApi, SurfaceAccess, + SurfaceInfo, SurfaceType, }; use euclid::default::Size2D; use glow::Texture; @@ -20,8 +21,6 @@ where type Connection; /// The context type associated with this device. type Context; - /// The context descriptor type associated with this device. - type ContextDescriptor; /// The surface type associated with this device. type Surface; /// The surface texture type associated with this device. @@ -46,7 +45,7 @@ where fn create_context_descriptor( &self, attributes: &ContextAttributes, - ) -> Result; + ) -> Result; /// Creates a new OpenGL context and makes it current. /// @@ -54,7 +53,7 @@ where /// commands will fail or have no effect. fn create_context( &self, - descriptor: &Self::ContextDescriptor, + descriptor: &ContextDescriptor, share_with: Option<&Self::Context>, ) -> Result; @@ -64,7 +63,7 @@ where fn destroy_context(&self, context: &mut Self::Context) -> Result<(), Error>; /// Returns the descriptor that this context was created with. - fn context_descriptor(&self, context: &Self::Context) -> Self::ContextDescriptor; + fn context_descriptor(&self, context: &Self::Context) -> ContextDescriptor; /// Makes the context the current OpenGL context for this thread. /// @@ -80,7 +79,7 @@ where /// Returns the attributes that the context descriptor was created with. fn context_descriptor_attributes( &self, - context_descriptor: &Self::ContextDescriptor, + context_descriptor: &ContextDescriptor, ) -> ContextAttributes; /// Fetches the address of an OpenGL function associated with this context. diff --git a/src/hardware_buffer/context.rs b/src/hardware_buffer/context.rs index f5d610e4..42804959 100644 --- a/src/hardware_buffer/context.rs +++ b/src/hardware_buffer/context.rs @@ -9,7 +9,7 @@ use crate::surface::Framebuffer; use crate::Gl; use std::thread; -pub use crate::base::egl::context::{ContextDescriptor, NativeContext}; +pub use crate::base::egl::context::NativeContext; /// Represents an OpenGL rendering context. /// diff --git a/src/hardware_buffer/device.rs b/src/hardware_buffer/device.rs index e2ec0726..0fe0a4bd 100644 --- a/src/hardware_buffer/device.rs +++ b/src/hardware_buffer/device.rs @@ -12,7 +12,7 @@ use crate::egl::types::{EGLConfig, EGLDisplay, EGLint}; use crate::hardware_buffer::surface::SurfaceObjects; use crate::surface::Framebuffer; use crate::Adapter; -use crate::{egl, ContextDescriptor, Surface}; +use crate::{egl, ContextDescriptor, EglContextDescriptor, Surface}; use crate::{Context, ContextAttributes, Error, GLApi, Gl, SurfaceInfo}; use euclid::default::Size2D; use glow::HasContext; @@ -107,7 +107,7 @@ impl Device { attributes: &ContextAttributes, ) -> Result { unsafe { - ContextDescriptor::new( + EglContextDescriptor::new( self.egl_display, attributes, &[ @@ -119,6 +119,7 @@ impl Device { egl::OPENGL_ES2_BIT as EGLint, ], ) + .map(Into::into) } } @@ -140,7 +141,7 @@ impl Device { let gl_api = self.gl_api(); let egl_context = context::create_context( egl_display, - descriptor, + descriptor.egl()?, share_with.map_or(egl::NO_CONTEXT, |ctx| ctx.egl_context), gl_api, )?; @@ -244,7 +245,12 @@ impl Device { /// Returns the descriptor that this context was created with. pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { unsafe { - ContextDescriptor::from_egl_context(&context.gl, self.egl_display, context.egl_context) + EglContextDescriptor::from_egl_context( + &context.gl, + self.egl_display, + context.egl_context, + ) + .into() } } @@ -375,6 +381,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); unsafe { context_descriptor.attributes(self.egl_display) } } diff --git a/src/hardware_buffer/surface/mod.rs b/src/hardware_buffer/surface/mod.rs index 322a7266..2c153725 100644 --- a/src/hardware_buffer/surface/mod.rs +++ b/src/hardware_buffer/surface/mod.rs @@ -11,8 +11,6 @@ use std::fmt::{self, Debug, Formatter}; use std::marker::PhantomData; use std::thread; -pub use crate::base::egl::context::ContextDescriptor; - #[cfg(android_platform)] mod android_surface; diff --git a/src/lib.rs b/src/lib.rs index 489460c9..b8ece8de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ pub mod cgl; pub mod chains; pub mod connection; mod context; +mod context_descriptor; pub mod device; pub mod error; #[cfg(free_unix)] @@ -60,12 +61,13 @@ pub use wayland as default; pub use wgl as default; pub use crate::context::{ContextAttributeFlags, ContextAttributes, ContextID}; +pub use crate::context_descriptor::ContextDescriptor; pub use crate::error::{Error, WindowingApiError}; pub use crate::info::{GLApi, GLVersion}; pub use crate::surface::{SurfaceAccess, SurfaceID, SurfaceInfo, SurfaceType, SystemSurfaceInfo}; pub use adapter::{Adapter, AdapterPreferences, PowerPreference, RenderingPreference}; pub use default::connection::Connection; -pub use default::context::{Context, ContextDescriptor}; +pub use default::context::Context; pub use default::device::Device; pub use default::surface::{Surface, SurfaceTexture}; pub(crate) use glow::{self as gl, Context as Gl}; @@ -81,6 +83,9 @@ pub use base::io_surface::device::Device as SystemDevice; #[cfg(target_os = "macos")] pub use base::io_surface::surface::Surface as SystemSurface; +#[cfg(any(android_platform, angle, free_unix, ohos_platform))] +pub use crate::base::egl::context::EglContextDescriptor; + #[cfg(any( target_os = "android", target_env = "ohos", diff --git a/src/macros.rs b/src/macros.rs index 56898e39..946b526d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,7 +35,7 @@ macro_rules! implement_interfaces { () => { mod implementation { use super::connection::Connection; - use super::context::{Context, ContextDescriptor}; + use super::context::Context; use super::device::Device; use super::surface::{Surface, SurfaceTexture}; use euclid::default::Size2D; @@ -46,7 +46,10 @@ macro_rules! implement_interfaces { use $crate::device::Device as DeviceInterface; use $crate::info::GLApi; use $crate::Error; - use $crate::{ContextAttributes, ContextID, SurfaceAccess, SurfaceInfo, SurfaceType}; + use $crate::{ + ContextAttributes, ContextDescriptor, ContextID, SurfaceAccess, SurfaceInfo, + SurfaceType, + }; impl ConnectionInterface for Connection { type Device = Device; @@ -85,7 +88,6 @@ macro_rules! implement_interfaces { impl DeviceInterface for Device { type Connection = Connection; type Context = Context; - type ContextDescriptor = ContextDescriptor; type Surface = Surface; type SurfaceTexture = SurfaceTexture; @@ -112,14 +114,14 @@ macro_rules! implement_interfaces { fn create_context_descriptor( &self, attributes: &ContextAttributes, - ) -> Result { + ) -> Result { Device::create_context_descriptor(self, attributes) } #[inline] fn create_context( &self, - descriptor: &Self::ContextDescriptor, + descriptor: &ContextDescriptor, share_with: Option<&Self::Context>, ) -> Result { Device::create_context(self, descriptor, share_with) @@ -131,7 +133,7 @@ macro_rules! implement_interfaces { } #[inline] - fn context_descriptor(&self, context: &Self::Context) -> Self::ContextDescriptor { + fn context_descriptor(&self, context: &Self::Context) -> ContextDescriptor { Device::context_descriptor(self, context) } @@ -148,7 +150,7 @@ macro_rules! implement_interfaces { #[inline] fn context_descriptor_attributes( &self, - context_descriptor: &Self::ContextDescriptor, + context_descriptor: &ContextDescriptor, ) -> ContextAttributes { Device::context_descriptor_attributes(self, context_descriptor) } @@ -289,7 +291,7 @@ macro_rules! implement_interfaces { /// A macro that takes care of producing the boilerplate for conversion to and /// from an inner type within an enum. macro_rules! enum_conversion { - ($enum:ty, $variant:ident, $type:ty, $name:ident) => { + ($enum:ty, $variant:ident, $type:ty, $name:ident, $error:ident) => { impl From<$type> for $enum { fn from(connection: $type) -> Self { Self::$variant(connection) @@ -298,11 +300,11 @@ macro_rules! enum_conversion { impl $enum { #[doc = concat!("Try to convert this generic [`", stringify!($enum), "`] into a [`", stringify!($type), "`].")] - pub fn $name(&self) -> Result<&$type, Error> { + pub fn $name(&self) -> Result<&$type, crate::Error> { #[allow(unreachable_patterns)] match self { Self::$variant(ref connection) => Ok(connection), - _ => Err(Error::Failed), + _ => Err(crate::Error::$error), } } } diff --git a/src/mesa_surfaceless/context.rs b/src/mesa_surfaceless/context.rs index 1d097363..486b1b7a 100644 --- a/src/mesa_surfaceless/context.rs +++ b/src/mesa_surfaceless/context.rs @@ -1,7 +1,7 @@ //! OpenGL rendering contexts on surfaceless Mesa. use crate::base::egl::context::EGLBackedContext; -pub use crate::base::egl::context::{ContextDescriptor, NativeContext}; +pub use crate::base::egl::context::NativeContext; use crate::Gl; /// Represents an OpenGL rendering context. diff --git a/src/mesa_surfaceless/device.rs b/src/mesa_surfaceless/device.rs index d48da1bb..10589d55 100644 --- a/src/mesa_surfaceless/device.rs +++ b/src/mesa_surfaceless/device.rs @@ -7,10 +7,10 @@ use crate::base::egl::surface::EGLBackedSurface; use crate::context::ContextID; use crate::egl::types::EGLint; use crate::free_unix::adapter::FreeUnixAdapter; -use crate::gl; -use crate::mesa_surfaceless::context::{Context, ContextDescriptor, NativeContext}; +use crate::mesa_surfaceless::context::{Context, NativeContext}; use crate::mesa_surfaceless::surface::{Surface, SurfaceTexture}; -use crate::{egl, Adapter}; +use crate::{egl, Adapter, EglContextDescriptor}; +use crate::{gl, ContextDescriptor}; use crate::{ContextAttributes, Gl, SurfaceInfo}; use crate::{Error, GLApi, SurfaceAccess, SurfaceType}; use euclid::default::Size2D; @@ -90,7 +90,7 @@ impl Device { self.adapter.set_environment_variables(); unsafe { - ContextDescriptor::new( + EglContextDescriptor::new( self.native_connection.egl_display, attributes, &[ @@ -102,6 +102,7 @@ impl Device { egl::RGB_BUFFER as EGLint, ], ) + .map(Into::into) } } @@ -118,7 +119,7 @@ impl Device { unsafe { let context = EGLBackedContext::new( self.native_connection.egl_display, - descriptor, + descriptor.egl()?, share_with.map(|ctx| &ctx.0), self.gl_api(), )?; @@ -170,11 +171,12 @@ impl Device { #[inline] pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { unsafe { - ContextDescriptor::from_egl_context( + EglContextDescriptor::from_egl_context( &context.1, self.native_connection.egl_display, context.0.egl_context, ) + .into() } } @@ -211,6 +213,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); unsafe { context_descriptor.attributes(self.native_connection.egl_display) } } diff --git a/src/multi/context.rs b/src/multi/context.rs index cee88d95..27caf376 100644 --- a/src/multi/context.rs +++ b/src/multi/context.rs @@ -5,7 +5,7 @@ use euclid::default::Size2D; use super::device::Device; use super::surface::Surface; use crate::device::Device as DeviceInterface; -use crate::{ContextAttributes, ContextID, Error, SurfaceInfo}; +use crate::{ContextAttributes, ContextDescriptor, ContextID, Error, SurfaceInfo}; use std::os::raw::c_void; @@ -36,21 +36,6 @@ where Alternate(Alt::Context), } -/// Information needed to create a context. Some APIs call this a "config" or a "pixel format". -/// -/// These are local to a device. -#[derive(Clone)] -pub enum ContextDescriptor -where - Def: DeviceInterface, - Alt: DeviceInterface, -{ - /// The default context descriptor type. - Default(Def::ContextDescriptor), - /// The alternate context descriptor type. - Alternate(Alt::ContextDescriptor), -} - impl Device where Def: DeviceInterface, @@ -62,14 +47,10 @@ where pub fn create_context_descriptor( &self, attributes: &ContextAttributes, - ) -> Result, Error> { + ) -> Result { match *self { - Device::Default(ref device) => device - .create_context_descriptor(attributes) - .map(ContextDescriptor::Default), - Device::Alternate(ref device) => device - .create_context_descriptor(attributes) - .map(ContextDescriptor::Alternate), + Device::Default(ref device) => device.create_context_descriptor(attributes), + Device::Alternate(ref device) => device.create_context_descriptor(attributes), } } @@ -79,11 +60,11 @@ where /// commands will fail or have no effect. pub fn create_context( &self, - descriptor: &ContextDescriptor, + descriptor: &ContextDescriptor, share_with: Option<&Context>, ) -> Result, Error> { - match (self, descriptor) { - (Device::Default(device), ContextDescriptor::Default(descriptor)) => { + match self { + Device::Default(device) => { let shared = match share_with { Some(Context::Default(other)) => Some(other), Some(_) => { @@ -95,7 +76,7 @@ where .create_context(descriptor, shared) .map(Context::Default) } - (Device::Alternate(device), ContextDescriptor::Alternate(descriptor)) => { + Device::Alternate(device) => { let shared = match share_with { Some(Context::Alternate(other)) => Some(other), Some(_) => { @@ -107,7 +88,6 @@ where .create_context(descriptor, shared) .map(Context::Alternate) } - _ => Err(Error::IncompatibleContextDescriptor), } } @@ -127,13 +107,13 @@ where } /// Returns the descriptor that this context was created with. - pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { + pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { match (self, context) { (Device::Default(device), Context::Default(context)) => { - ContextDescriptor::Default(device.context_descriptor(context)) + device.context_descriptor(context) } (Device::Alternate(device), Context::Alternate(context)) => { - ContextDescriptor::Alternate(device.context_descriptor(context)) + device.context_descriptor(context) } _ => panic!("Incompatible context!"), } @@ -255,16 +235,11 @@ where /// Returns the attributes that the context descriptor was created with. pub fn context_descriptor_attributes( &self, - context_descriptor: &ContextDescriptor, + context_descriptor: &ContextDescriptor, ) -> ContextAttributes { - match (self, context_descriptor) { - (Device::Default(device), ContextDescriptor::Default(context_descriptor)) => { - device.context_descriptor_attributes(context_descriptor) - } - (Device::Alternate(device), ContextDescriptor::Alternate(context_descriptor)) => { - device.context_descriptor_attributes(context_descriptor) - } - _ => panic!("Incompatible context!"), + match self { + Device::Default(device) => device.context_descriptor_attributes(context_descriptor), + Device::Alternate(device) => device.context_descriptor_attributes(context_descriptor), } } diff --git a/src/multi/device.rs b/src/multi/device.rs index 520eb098..bae4438a 100644 --- a/src/multi/device.rs +++ b/src/multi/device.rs @@ -1,12 +1,14 @@ //! A device abstraction that allows the choice of backends dynamically. use super::connection::Connection; -use super::context::{Context, ContextDescriptor}; +use super::context::Context; use super::surface::{Surface, SurfaceTexture}; use crate::connection::Connection as ConnectionInterface; use crate::context::ContextAttributes; use crate::device::Device as DeviceInterface; -use crate::{Adapter, ContextID, Error, GLApi, SurfaceAccess, SurfaceInfo, SurfaceType}; +use crate::{ + Adapter, ContextDescriptor, ContextID, Error, GLApi, SurfaceAccess, SurfaceInfo, SurfaceType, +}; use euclid::default::Size2D; use glow::Texture; @@ -67,7 +69,6 @@ where { type Connection = Connection; type Context = Context; - type ContextDescriptor = ContextDescriptor; type Surface = Surface; type SurfaceTexture = SurfaceTexture; @@ -94,14 +95,14 @@ where fn create_context_descriptor( &self, attributes: &ContextAttributes, - ) -> Result { + ) -> Result { Device::create_context_descriptor(self, attributes) } #[inline] fn create_context( &self, - descriptor: &ContextDescriptor, + descriptor: &ContextDescriptor, share_with: Option<&Context>, ) -> Result, Error> { Device::create_context(self, descriptor, share_with) @@ -113,7 +114,7 @@ where } #[inline] - fn context_descriptor(&self, context: &Context) -> Self::ContextDescriptor { + fn context_descriptor(&self, context: &Context) -> ContextDescriptor { Device::context_descriptor(self, context) } @@ -130,7 +131,7 @@ where #[inline] fn context_descriptor_attributes( &self, - context_descriptor: &ContextDescriptor, + context_descriptor: &ContextDescriptor, ) -> ContextAttributes { Device::context_descriptor_attributes(self, context_descriptor) } diff --git a/src/tests.rs b/src/tests.rs index 8a8d9942..d3cab55e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -7,13 +7,14 @@ #![allow(missing_docs)] use super::connection::Connection; -use super::context::{Context, ContextDescriptor, NativeContext}; +use super::context::{Context, NativeContext}; use super::device::Device; use super::surface::Surface; -use crate::{gl, AdapterPreferences, PowerPreference}; -use crate::{Adapter, RenderingPreference}; -use crate::{ContextAttributeFlags, ContextAttributes, Error, GLApi, GLVersion, Gl, SurfaceAccess}; -use crate::{SurfaceType, WindowingApiError}; +use crate::{ + gl, Adapter, AdapterPreferences, ContextAttributeFlags, ContextAttributes, ContextDescriptor, + Error, GLApi, GLVersion, Gl, PowerPreference, RenderingPreference, SurfaceAccess, SurfaceType, + WindowingApiError, +}; use euclid::default::Size2D; use glow::{Framebuffer, HasContext, PixelPackData, Texture}; diff --git a/src/unix.rs b/src/unix.rs index 78ac23de..10b79015 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -19,7 +19,6 @@ pub mod connection { pub mod context { use crate::mesa_surfaceless::device::Device as SWDevice; use crate::multi::context::Context as MultiContext; - use crate::multi::context::ContextDescriptor as MultiContextDescriptor; use crate::multi::device::Device as MultiDevice; use crate::wayland::device::Device as WaylandDevice; use crate::x11::device::Device as X11Device; @@ -43,11 +42,6 @@ pub mod context { /// /// A context must be explicitly destroyed with `destroy_context()`, or a panic will occur. pub type Context = MultiContext; - - /// Information needed to create a context. Some APIs call this a "config" or a "pixel format". - /// - /// These are local to a device. - pub type ContextDescriptor = MultiContextDescriptor; } /// Thread-local handles to devices. diff --git a/src/wayland/context.rs b/src/wayland/context.rs index 622a04c1..05fa92e8 100644 --- a/src/wayland/context.rs +++ b/src/wayland/context.rs @@ -1,7 +1,7 @@ //! OpenGL rendering contexts on Wayland. use crate::base::egl::context::EGLBackedContext; -pub use crate::base::egl::context::{ContextDescriptor, NativeContext}; +pub use crate::base::egl::context::NativeContext; use crate::Gl; /// Represents an OpenGL rendering context. diff --git a/src/wayland/device.rs b/src/wayland/device.rs index f4b730a6..4f6c7b03 100644 --- a/src/wayland/device.rs +++ b/src/wayland/device.rs @@ -1,18 +1,18 @@ //! A wrapper around Wayland `EGLDisplay`s. use super::connection::{Connection, NativeConnectionWrapper}; -use super::context::{Context, ContextDescriptor, NativeContext}; +use super::context::{Context, NativeContext}; use super::surface::{Surface, SurfaceDataGuard, SurfaceTexture}; use crate::base::egl::context::{self, CurrentContextGuard, EGLBackedContext}; use crate::base::egl::surface::EGLBackedSurface; use crate::context::ContextID; use crate::egl::types::EGLint; use crate::free_unix::adapter::FreeUnixAdapter; -use crate::gl; use crate::surface::Framebuffer; -use crate::{egl, Adapter}; -use crate::{ContextAttributes, Gl, SurfaceInfo}; -use crate::{Error, GLApi, SurfaceAccess, SurfaceType}; +use crate::{ + egl, gl, Adapter, ContextAttributes, ContextDescriptor, EglContextDescriptor, Error, GLApi, Gl, + SurfaceAccess, SurfaceInfo, SurfaceType, +}; use euclid::default::Size2D; use glow::Texture; use raw_window_handle::RawWindowHandle; @@ -97,7 +97,7 @@ impl Device { self.adapter.set_environment_variables(); unsafe { - ContextDescriptor::new( + EglContextDescriptor::new( self.native_connection.egl_display, attributes, &[ @@ -107,6 +107,7 @@ impl Device { egl::OPENGL_BIT as EGLint, ], ) + .map(Into::into) } } @@ -123,7 +124,7 @@ impl Device { unsafe { let context = EGLBackedContext::new( self.native_connection.egl_display, - descriptor, + descriptor.egl()?, share_with.map(|ctx| &ctx.0), self.gl_api(), )?; @@ -175,11 +176,12 @@ impl Device { #[inline] pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { unsafe { - ContextDescriptor::from_egl_context( + EglContextDescriptor::from_egl_context( &context.1, self.native_connection.egl_display, context.0.egl_context, ) + .into() } } @@ -216,6 +218,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); unsafe { context_descriptor.attributes(self.native_connection.egl_display) } } @@ -371,6 +376,9 @@ impl Device { assert!(!egl_window.is_null()); let context_descriptor = self.context_descriptor(context); + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); let egl_config = context::egl_config_from_id( self.native_connection.egl_display, context_descriptor.egl_config_id, diff --git a/src/wgl/context.rs b/src/wgl/context.rs index b50996e2..e85bf85f 100644 --- a/src/wgl/context.rs +++ b/src/wgl/context.rs @@ -87,7 +87,7 @@ pub(crate) struct WGLDXInteropExtensionFunctions { /// /// These are local to a device. #[derive(Clone)] -pub struct ContextDescriptor { +pub struct WglContextDescriptor { pub(crate) pixel_format: c_int, pub(crate) gl_version: GLVersion, pub(crate) compatibility_profile: bool, diff --git a/src/wgl/device.rs b/src/wgl/device.rs index 1f2e558c..b8d327b2 100644 --- a/src/wgl/device.rs +++ b/src/wgl/device.rs @@ -9,13 +9,15 @@ use crate::surface::Framebuffer; use crate::wgl::adapter::WglAdapter; use crate::wgl::connection::Connection; use crate::wgl::context::{ - Context, ContextDescriptor, ContextStatus, CurrentContextGuard, FramebufferGuard, - NativeContext, OPENGL_LIBRARY, WGL_EXTENSION_FUNCTIONS, + Context, ContextStatus, CurrentContextGuard, FramebufferGuard, NativeContext, + WglContextDescriptor, OPENGL_LIBRARY, WGL_EXTENSION_FUNCTIONS, }; use crate::wgl::surface::{Surface, SurfaceDataGuard, SurfaceTexture, Win32Objects}; -use crate::{gl, gl_utils, GLApi, Gl, SurfaceAccess, SurfaceType}; -use crate::{Adapter, AdapterPreferences, PowerPreference}; -use crate::{ContextAttributeFlags, ContextAttributes, Error, GLVersion, SurfaceInfo}; +use crate::{ + gl, gl_utils, Adapter, AdapterPreferences, ContextAttributeFlags, ContextAttributes, + ContextDescriptor, Error, GLApi, GLVersion, Gl, PowerPreference, SurfaceAccess, SurfaceInfo, + SurfaceType, +}; use euclid::default::Size2D; use glow::HasContext; use libc::c_uint; @@ -308,11 +310,12 @@ impl Device { return Err(Error::NoPixelFormatFound); } - Ok(ContextDescriptor { + Ok(WglContextDescriptor { pixel_format, gl_version: attributes.version, compatibility_profile, - }) + } + .into()) } } @@ -332,6 +335,7 @@ impl Device { }; let mut next_context_id = CREATE_CONTEXT_MUTEX.lock().unwrap(); + let descriptor = descriptor.wgl()?; unsafe { let (glrc, gl); @@ -463,11 +467,12 @@ impl Device { let gl_version = GLVersion::current(&context.gl); let compatibility_profile = current_context_uses_compatibility_profile(&context.gl); - ContextDescriptor { + WglContextDescriptor { pixel_format, gl_version, compatibility_profile, } + .into() } } @@ -487,6 +492,9 @@ impl Device { .GetPixelFormatAttribivARB; let dc_guard = self.hidden_window.get_dc(); + let context_descriptor = context_descriptor + .wgl() + .expect("Passed incompatible context descriptor"); unsafe { let attrib_name_i_list = [ diff --git a/src/x11/context.rs b/src/x11/context.rs index 5facd79d..e4d540aa 100644 --- a/src/x11/context.rs +++ b/src/x11/context.rs @@ -1,7 +1,7 @@ //! OpenGL rendering contexts on X11 via EGL. use crate::base::egl::context::EGLBackedContext; -pub use crate::base::egl::context::{ContextDescriptor, NativeContext}; +pub use crate::base::egl::context::NativeContext; use crate::Gl; /// Represents an OpenGL rendering context. diff --git a/src/x11/device.rs b/src/x11/device.rs index 7d7485e7..98296350 100644 --- a/src/x11/device.rs +++ b/src/x11/device.rs @@ -1,7 +1,7 @@ //! A wrapper around X11 `EGLDisplay`s. use super::connection::{Connection, NativeConnectionWrapper}; -use super::context::{Context, ContextDescriptor, NativeContext}; +use super::context::{Context, NativeContext}; use super::surface::Surface; use crate::base::egl::{ context::{self, CurrentContextGuard, EGLBackedContext}, @@ -10,10 +10,11 @@ use crate::base::egl::{ use crate::context::ContextID; use crate::egl::types::EGLint; use crate::free_unix::adapter::FreeUnixAdapter; -use crate::gl; use crate::x11::surface::{SurfaceDataGuard, SurfaceTexture}; -use crate::Adapter; -use crate::{egl, ContextAttributes, Error, GLApi, Gl, SurfaceAccess, SurfaceInfo, SurfaceType}; +use crate::{ + egl, gl, Adapter, ContextAttributes, ContextDescriptor, EglContextDescriptor, Error, GLApi, Gl, + SurfaceAccess, SurfaceInfo, SurfaceType, +}; use euclid::default::Size2D; use glow::Texture; use raw_window_handle::RawWindowHandle; @@ -93,7 +94,7 @@ impl Device { self.adapter.set_environment_variables(); unsafe { - ContextDescriptor::new( + EglContextDescriptor::new( self.native_connection.egl_display, attributes, &[ @@ -103,6 +104,7 @@ impl Device { egl::OPENGL_BIT as EGLint, ], ) + .map(Into::into) } } @@ -119,7 +121,7 @@ impl Device { unsafe { let context = EGLBackedContext::new( self.native_connection.egl_display, - descriptor, + descriptor.egl()?, share_with.map(|ctx| &ctx.0), self.gl_api(), )?; @@ -171,11 +173,12 @@ impl Device { #[inline] pub fn context_descriptor(&self, context: &Context) -> ContextDescriptor { unsafe { - ContextDescriptor::from_egl_context( + EglContextDescriptor::from_egl_context( &context.1, self.native_connection.egl_display, context.0.egl_context, ) + .into() } } @@ -212,6 +215,9 @@ impl Device { &self, context_descriptor: &ContextDescriptor, ) -> ContextAttributes { + let context_descriptor = context_descriptor + .egl() + .expect("Passed incompatible context descriptor"); unsafe { context_descriptor.attributes(self.native_connection.egl_display) } }