#![allow(unreachable_patterns)]
use std::num::NonZeroU32;
use bitflags::bitflags;
use raw_window_handle::RawWindowHandle;
use crate::display::{Display, GetGlDisplay};
use crate::private::{gl_api_dispatch, Sealed};
#[cfg(x11_platform)]
use crate::platform::x11::{X11GlConfigExt, X11VisualInfo};
#[cfg(cgl_backend)]
use crate::api::cgl::config::Config as CglConfig;
#[cfg(egl_backend)]
use crate::api::egl::config::Config as EglConfig;
#[cfg(glx_backend)]
use crate::api::glx::config::Config as GlxConfig;
#[cfg(wgl_backend)]
use crate::api::wgl::config::Config as WglConfig;
pub trait GlConfig: Sealed {
fn color_buffer_type(&self) -> Option<ColorBufferType>;
fn float_pixels(&self) -> bool;
fn alpha_size(&self) -> u8;
fn depth_size(&self) -> u8;
fn stencil_size(&self) -> u8;
fn num_samples(&self) -> u8;
fn srgb_capable(&self) -> bool;
fn supports_transparency(&self) -> Option<bool>;
fn hardware_accelerated(&self) -> bool;
fn config_surface_types(&self) -> ConfigSurfaceTypes;
fn api(&self) -> Api;
}
pub trait GetGlConfig: Sealed {
type Target: GlConfig;
fn config(&self) -> Self::Target;
}
pub trait AsRawConfig {
fn raw_config(&self) -> RawConfig;
}
#[derive(Debug, Default, Clone)]
pub struct ConfigTemplateBuilder {
template: ConfigTemplate,
}
impl ConfigTemplateBuilder {
#[inline]
pub fn new() -> Self {
Default::default()
}
#[inline]
pub fn with_alpha_size(mut self, alpha_size: u8) -> Self {
self.template.alpha_size = alpha_size;
self
}
#[inline]
pub fn with_float_pixels(mut self, float_pixels: bool) -> Self {
self.template.float_pixels = float_pixels;
self
}
#[inline]
pub fn with_stencil_size(mut self, stencil_size: u8) -> Self {
self.template.stencil_size = stencil_size;
self
}
#[inline]
pub fn with_depth_size(mut self, depth_size: u8) -> Self {
self.template.depth_size = depth_size;
self
}
#[inline]
pub fn with_multisampling(mut self, num_samples: u8) -> Self {
debug_assert!(num_samples.is_power_of_two());
self.template.num_samples = Some(num_samples);
self
}
#[inline]
pub fn with_surface_type(mut self, config_surface_types: ConfigSurfaceTypes) -> Self {
self.template.config_surface_types = config_surface_types;
self
}
#[inline]
pub fn with_buffer_type(mut self, color_buffer_type: ColorBufferType) -> Self {
self.template.color_buffer_type = color_buffer_type;
self
}
#[inline]
pub fn with_api(mut self, api: Api) -> Self {
self.template.api = Some(api);
self
}
#[inline]
pub fn with_stereoscopy(mut self, stereoscopy: Option<bool>) -> Self {
self.template.stereoscopy = stereoscopy;
self
}
#[inline]
pub fn with_single_buffering(mut self, single_buffering: bool) -> Self {
self.template.single_buffering = single_buffering;
self
}
#[inline]
pub fn with_transparency(mut self, transparency: bool) -> Self {
self.template.transparency = transparency;
self
}
#[inline]
pub fn with_pbuffer_sizes(mut self, width: NonZeroU32, height: NonZeroU32) -> Self {
self.template.max_pbuffer_width = Some(width.into());
self.template.max_pbuffer_height = Some(height.into());
self
}
pub fn prefer_hardware_accelerated(mut self, hardware_accerelated: Option<bool>) -> Self {
self.template.hardware_accelerated = hardware_accerelated;
self
}
pub fn compatible_with_native_window(mut self, native_window: RawWindowHandle) -> Self {
self.template.native_window = Some(native_window);
self
}
#[inline]
pub fn with_swap_interval(
mut self,
min_swap_interval: Option<u16>,
max_swap_interval: Option<u16>,
) -> Self {
self.template.min_swap_interval = min_swap_interval;
self.template.max_swap_interval = max_swap_interval;
self
}
#[must_use]
pub fn build(self) -> ConfigTemplate {
self.template
}
}
#[derive(Debug, Clone)]
pub struct ConfigTemplate {
pub(crate) color_buffer_type: ColorBufferType,
pub(crate) alpha_size: u8,
pub(crate) depth_size: u8,
pub(crate) stencil_size: u8,
pub(crate) num_samples: Option<u8>,
pub(crate) min_swap_interval: Option<u16>,
pub(crate) max_swap_interval: Option<u16>,
pub(crate) config_surface_types: ConfigSurfaceTypes,
pub(crate) api: Option<Api>,
pub(crate) transparency: bool,
pub(crate) single_buffering: bool,
pub(crate) stereoscopy: Option<bool>,
pub(crate) float_pixels: bool,
pub(crate) max_pbuffer_width: Option<u32>,
pub(crate) hardware_accelerated: Option<bool>,
pub(crate) max_pbuffer_height: Option<u32>,
pub(crate) native_window: Option<RawWindowHandle>,
}
impl Default for ConfigTemplate {
fn default() -> Self {
ConfigTemplate {
color_buffer_type: ColorBufferType::Rgb { r_size: 8, g_size: 8, b_size: 8 },
alpha_size: 8,
depth_size: 24,
stencil_size: 8,
num_samples: None,
transparency: false,
stereoscopy: None,
min_swap_interval: None,
max_swap_interval: None,
single_buffering: false,
float_pixels: false,
config_surface_types: ConfigSurfaceTypes::WINDOW,
max_pbuffer_width: None,
max_pbuffer_height: None,
native_window: None,
hardware_accelerated: None,
api: None,
}
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ConfigSurfaceTypes: u8 {
const WINDOW = 0b00000001;
const PIXMAP = 0b00000010;
const PBUFFER = 0b00000100;
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Api : u8 {
const OPENGL = 0b00000001;
const GLES1 = 0b00000010;
const GLES2 = 0b00000100;
const GLES3 = 0b00001000;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorBufferType {
Rgb {
r_size: u8,
g_size: u8,
b_size: u8,
},
Luminance(u8),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Config {
#[cfg(egl_backend)]
Egl(EglConfig),
#[cfg(glx_backend)]
Glx(GlxConfig),
#[cfg(wgl_backend)]
Wgl(WglConfig),
#[cfg(cgl_backend)]
Cgl(CglConfig),
}
impl GlConfig for Config {
fn color_buffer_type(&self) -> Option<ColorBufferType> {
gl_api_dispatch!(self; Self(config) => config.color_buffer_type())
}
fn float_pixels(&self) -> bool {
gl_api_dispatch!(self; Self(config) => config.float_pixels())
}
fn alpha_size(&self) -> u8 {
gl_api_dispatch!(self; Self(config) => config.alpha_size())
}
fn depth_size(&self) -> u8 {
gl_api_dispatch!(self; Self(config) => config.depth_size())
}
fn stencil_size(&self) -> u8 {
gl_api_dispatch!(self; Self(config) => config.stencil_size())
}
fn num_samples(&self) -> u8 {
gl_api_dispatch!(self; Self(config) => config.num_samples())
}
fn srgb_capable(&self) -> bool {
gl_api_dispatch!(self; Self(config) => config.srgb_capable())
}
fn config_surface_types(&self) -> ConfigSurfaceTypes {
gl_api_dispatch!(self; Self(config) => config.config_surface_types())
}
fn hardware_accelerated(&self) -> bool {
gl_api_dispatch!(self; Self(config) => config.hardware_accelerated())
}
fn supports_transparency(&self) -> Option<bool> {
gl_api_dispatch!(self; Self(config) => config.supports_transparency())
}
fn api(&self) -> Api {
gl_api_dispatch!(self; Self(config) => config.api())
}
}
impl GetGlDisplay for Config {
type Target = Display;
fn display(&self) -> Self::Target {
gl_api_dispatch!(self; Self(config) => config.display(); as Display)
}
}
#[cfg(x11_platform)]
impl X11GlConfigExt for Config {
fn x11_visual(&self) -> Option<X11VisualInfo> {
gl_api_dispatch!(self; Self(config) => config.x11_visual())
}
}
impl Sealed for Config {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RawConfig {
#[cfg(egl_backend)]
Egl(*const std::ffi::c_void),
#[cfg(glx_backend)]
Glx(*const std::ffi::c_void),
#[cfg(wgl_backend)]
Wgl(i32),
#[cfg(cgl_backend)]
Cgl(*const std::ffi::c_void),
}
impl AsRawConfig for Config {
fn raw_config(&self) -> RawConfig {
gl_api_dispatch!(self; Self(config) => config.raw_config())
}
}