#[cfg(dmc_display_backend="x11")]
#[path="x11.rs"]
mod backend;
use std::path::Path;
use std::os::raw::{c_void, c_char};
use Decision;
use Extent2;
use Rgba32;
use Semver;
pub mod window {
use super::Extent2;
use super::Rgba32;
use super::backend;
use super::Error;
use super::Decision;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Mode {
#[allow(missing_docs)]
FixedSize(Extent2<u32>),
#[allow(missing_docs)]
DesktopSize,
#[allow(missing_docs)]
FullScreen,
FixedSizeFullScreen(Extent2<u32>),
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Settings {
pub mode: Mode,
pub opengl: bool,
pub resizable: bool,
pub allow_high_dpi: bool,
pub fully_opaque: bool,
}
impl Default for Mode {
fn default() -> Self {
Mode::FixedSize(Extent2::new(400, 300))
}
}
impl Default for Settings {
fn default() -> Self {
Self {
opengl: true,
resizable: true,
allow_high_dpi: true,
fully_opaque: true,
mode: Default::default(),
}
}
}
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Borders {
pub thickness: Decision<u16>,
pub color: Decision<Rgba32>,
}
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct TitleBarStyle {
pub minimize_button: bool,
pub maximize_button: bool,
pub close_button: bool,
}
impl Default for TitleBarStyle {
fn default() -> Self {
Self {
minimize_button: true,
maximize_button: true,
close_button: true,
}
}
}
pub struct Style {
pub title_bar: Option<TitleBarStyle>,
pub borders: Option<Borders>,
}
pub struct Icon;
impl<T: Into<Extent2<u32>>> From<T> for Mode {
fn from(size: T) -> Self {
Mode::FixedSize(size.into())
}
}
impl<T: Into<Extent2<u32>>> From<T> for Settings {
fn from(size: T) -> Self {
Self {
mode: Mode::from(size),
.. Default::default()
}
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum WindowOpResult {
#[allow(missing_docs)]
Success,
#[allow(missing_docs)]
Failed { reason: Option<&'static str> },
#[allow(missing_docs)]
Unsupported { required_optin: bool },
Unimplemented,
}
impl WindowOpResult {
pub fn ignore(self) {}
pub fn unwrap(self) {
self.into_result().unwrap()
}
pub fn into_result(self) -> Result<(),Self> {
match self {
WindowOpResult::Success => Ok(()),
_ => Err(self),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Capabilities {
pub hide: WindowOpResult,
pub show: WindowOpResult,
pub set_title: WindowOpResult,
pub set_icon: WindowOpResult,
pub set_style: WindowOpResult,
pub recenter: WindowOpResult,
pub set_opacity: WindowOpResult,
pub maximize: WindowOpResult,
pub minimize: WindowOpResult,
pub restore: WindowOpResult,
pub raise: WindowOpResult,
pub enter_fullscreen: WindowOpResult,
pub leave_fullscreen: WindowOpResult,
pub set_minimum_size: WindowOpResult,
pub set_maximum_size: WindowOpResult,
pub move_absolute: WindowOpResult,
pub move_relative_to_parent: WindowOpResult,
pub move_relative_to_self: WindowOpResult,
pub resize: WindowOpResult,
}
#[derive(Debug)]
pub struct Window<'dpy>(pub(super) backend::Window<'dpy>);
impl<'a,'b:'a,'dpy:'b> Window<'dpy> {
pub fn get_capabilities(&self) -> Capabilities {
self.0.get_capabilities()
}
pub fn show(&self) -> WindowOpResult { self.0.show() }
pub fn hide(&self) -> WindowOpResult { self.0.hide() }
pub fn set_title(&self, title: &str) -> WindowOpResult {
self.0.set_title(title)
}
#[allow(missing_docs)]
pub fn set_icon<I: Into<Option<Icon>>>(&self, icon: I) -> WindowOpResult {
self.0.set_icon(icon.into())
}
pub fn set_style(&self, style: &Style) -> WindowOpResult {
self.0.set_style(style)
}
pub fn recenter(&self) -> WindowOpResult {
self.0.recenter()
}
pub fn set_opacity(&self, opacity: f32) -> WindowOpResult {
self.0.set_opacity(opacity)
}
pub unsafe fn get_internal(&'b self) -> &'a backend::Window {
&self.0
}
pub unsafe fn get_internal_mut(&'dpy mut self) -> &'a mut backend::Window {
&mut self.0
}
pub fn create_child(&'b mut self, settings: &Settings) -> Result<Window<'a>,Error> {
self.0.create_child(settings).map(Window)
}
pub fn query_screenspace_size(&self) -> Extent2<u32> {
self.0.query_screenspace_size()
}
pub fn query_canvas_size(&self) -> Extent2<u32> {
self.0.query_canvas_size()
}
pub fn maximize(&self) -> WindowOpResult { self.0.maximize() }
pub fn minimize(&self) -> WindowOpResult { self.0.minimize() }
pub fn restore(&self) -> WindowOpResult { self.0.restore() }
pub fn raise(&self) -> WindowOpResult { self.0.raise() }
pub fn enter_fullscreen(&self) -> WindowOpResult { self.0.enter_fullscreen() }
pub fn leave_fullscreen(&self) -> WindowOpResult { self.0.leave_fullscreen() }
pub fn set_minimum_size(&self, size: Extent2<u32>) -> WindowOpResult {
self.0.set_minimum_size(size)
}
pub fn set_maximum_size(&self, size: Extent2<u32>) -> WindowOpResult {
self.0.set_maximum_size(size)
}
pub fn move_absolute(&self, pos: Extent2<u32>) -> WindowOpResult {
self.0.move_absolute(pos)
}
pub fn move_relative_to_self(&self, pos: Extent2<u32>) -> WindowOpResult {
self.0.move_relative_to_self(pos)
}
pub fn move_relative_to_parent(&self, pos: Extent2<u32>) -> WindowOpResult {
self.0.move_relative_to_parent(pos)
}
pub fn resize(&self, size: Extent2<u32>) -> WindowOpResult {
self.0.resize(size)
}
}
}
use self::window::{Window, Settings, Style, Icon};
#[derive(Debug, Clone)]
pub enum Error {
#[allow(missing_docs)]
DoesntSupportMultipleWindows,
#[allow(missing_docs)]
CouldntCreateWindow,
Backend(backend::Error)
}
#[derive(Debug)]
pub struct Display(backend::Display);
impl<'dpy> Display {
pub fn open() -> Result<Self, Error> {
backend::Display::open().map(Display)
}
#[cfg(dmc_display_backend="x11")]
pub fn open_x11_display_name(name: Option<&::std::ffi::CStr>) -> Result<Self, Error> {
backend::Display::open_x11_display_name(name).map(Display)
}
pub fn create_window(&'dpy self, settings: &Settings) -> Result<Window<'dpy>, Error> {
self.0.create_window(settings).map(Window)
}
pub fn create_window_and_show(&'dpy self, settings: &Settings) -> Result<Window<'dpy>, Error> {
let w = self.create_window(settings)?;
w.show().ignore();
Ok(w)
}
pub fn create_gl_context(&'dpy self, settings: &GLContextSettings) -> Result<GLContext<'dpy>,Error> {
self.0.create_gl_context(settings).map(GLContext)
}
pub fn create_software_gl_context(&'dpy self, settings: &GLContextSettings) -> Result<GLContext<'dpy>,Error> {
self.0.create_software_gl_context(settings).map(GLContext)
}
pub fn create_gl_context_from_lib<P: AsRef<Path>>(&'dpy self, _settings: &GLContextSettings, _path: P) -> Result<GLContext<'dpy>,Error> {
unimplemented!()
}
}
pub struct GLContext<'dpy>(backend::GLContext<'dpy>);
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum GLProfile {
Core,
Compatibility,
}
impl Default for GLProfile {
fn default() -> Self {
GLProfile::Compatibility
}
}
pub struct GLSwapChain<'win,'gl:'win,'dpy:'gl> {
window: &'win Window<'dpy>,
gl_context: &'gl GLContext<'dpy>,
}
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum GLVariant {
Desktop,
ES,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[allow(non_camel_case_types, missing_docs)]
#[repr(u16)]
pub enum GLVersion {
GL(Semver),
ES(Semver),
GL_4_5,
GL_4_4,
GL_4_3,
GL_4_2,
GL_4_1,
GL_4_0,
GL_3_3,
GL_3_2,
GL_3_1,
GL_3_0,
GL_2_1,
GL_2_0,
GL_1_5,
GL_1_4,
GL_1_3,
GL_1_2_1,
GL_1_2,
GL_1_1,
ES_3_2,
ES_3_1,
ES_3_0,
ES_2_0,
ES_1_1,
ES_1_0,
}
impl GLVersion {
#[allow(missing_docs)]
pub fn try_from_semver(v: &(GLVariant, Semver)) -> Option<Self> {
let &(variant, Semver {major, minor, patch}) = v;
match (variant, major, minor, patch) {
(GLVariant::Desktop, 4,5,0) => Some(GLVersion::GL_4_5 ),
(GLVariant::Desktop, 4,4,0) => Some(GLVersion::GL_4_4 ),
(GLVariant::Desktop, 4,3,0) => Some(GLVersion::GL_4_3 ),
(GLVariant::Desktop, 4,2,0) => Some(GLVersion::GL_4_2 ),
(GLVariant::Desktop, 4,1,0) => Some(GLVersion::GL_4_1 ),
(GLVariant::Desktop, 4,0,0) => Some(GLVersion::GL_4_0 ),
(GLVariant::Desktop, 3,3,0) => Some(GLVersion::GL_3_3 ),
(GLVariant::Desktop, 3,2,0) => Some(GLVersion::GL_3_2 ),
(GLVariant::Desktop, 3,1,0) => Some(GLVersion::GL_3_1 ),
(GLVariant::Desktop, 3,0,0) => Some(GLVersion::GL_3_0 ),
(GLVariant::Desktop, 2,1,0) => Some(GLVersion::GL_2_1 ),
(GLVariant::Desktop, 2,0,0) => Some(GLVersion::GL_2_0 ),
(GLVariant::Desktop, 1,5,0) => Some(GLVersion::GL_1_5 ),
(GLVariant::Desktop, 1,4,0) => Some(GLVersion::GL_1_4 ),
(GLVariant::Desktop, 1,3,0) => Some(GLVersion::GL_1_3 ),
(GLVariant::Desktop, 1,2,1) => Some(GLVersion::GL_1_2_1),
(GLVariant::Desktop, 1,2,0) => Some(GLVersion::GL_1_2 ),
(GLVariant::Desktop, 1,1,0) => Some(GLVersion::GL_1_1 ),
(GLVariant::ES , 3,2,0) => Some(GLVersion::ES_3_2 ),
(GLVariant::ES , 3,1,0) => Some(GLVersion::ES_3_1 ),
(GLVariant::ES , 3,0,0) => Some(GLVersion::ES_3_0 ),
(GLVariant::ES , 2,0,0) => Some(GLVersion::ES_2_0 ),
(GLVariant::ES , 1,1,0) => Some(GLVersion::ES_1_1 ),
(GLVariant::ES , 1,0,0) => Some(GLVersion::ES_1_0 ),
_ => None,
}
}
#[allow(missing_docs)]
pub fn to_semver(&self) -> (GLVariant, Semver) {
match *self {
GLVersion::GL(v) => (GLVariant::Desktop, v),
GLVersion::ES(v) => (GLVariant::ES , v),
GLVersion::GL_4_5 => (GLVariant::Desktop, Semver::new(4,5,0)),
GLVersion::GL_4_4 => (GLVariant::Desktop, Semver::new(4,4,0)),
GLVersion::GL_4_3 => (GLVariant::Desktop, Semver::new(4,3,0)),
GLVersion::GL_4_2 => (GLVariant::Desktop, Semver::new(4,2,0)),
GLVersion::GL_4_1 => (GLVariant::Desktop, Semver::new(4,1,0)),
GLVersion::GL_4_0 => (GLVariant::Desktop, Semver::new(4,0,0)),
GLVersion::GL_3_3 => (GLVariant::Desktop, Semver::new(3,3,0)),
GLVersion::GL_3_2 => (GLVariant::Desktop, Semver::new(3,2,0)),
GLVersion::GL_3_1 => (GLVariant::Desktop, Semver::new(3,1,0)),
GLVersion::GL_3_0 => (GLVariant::Desktop, Semver::new(3,0,0)),
GLVersion::GL_2_1 => (GLVariant::Desktop, Semver::new(2,1,0)),
GLVersion::GL_2_0 => (GLVariant::Desktop, Semver::new(2,0,0)),
GLVersion::GL_1_5 => (GLVariant::Desktop, Semver::new(1,5,0)),
GLVersion::GL_1_4 => (GLVariant::Desktop, Semver::new(1,4,0)),
GLVersion::GL_1_3 => (GLVariant::Desktop, Semver::new(1,3,0)),
GLVersion::GL_1_2_1 => (GLVariant::Desktop, Semver::new(1,2,1)),
GLVersion::GL_1_2 => (GLVariant::Desktop, Semver::new(1,2,0)),
GLVersion::GL_1_1 => (GLVariant::Desktop, Semver::new(1,1,0)),
GLVersion::ES_3_2 => (GLVariant::ES , Semver::new(3,2,0)),
GLVersion::ES_3_1 => (GLVariant::ES , Semver::new(3,1,0)),
GLVersion::ES_3_0 => (GLVariant::ES , Semver::new(3,0,0)),
GLVersion::ES_2_0 => (GLVariant::ES , Semver::new(2,0,0)),
GLVersion::ES_1_1 => (GLVariant::ES , Semver::new(1,1,0)),
GLVersion::ES_1_0 => (GLVariant::ES , Semver::new(1,0,0)),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum Requirement<'a, T: 'a> {
HighestAvailable,
LowestAvailable,
AtLeast(T),
AtMost(T),
Exactly(T),
TryInOrder(&'a [T]),
}
#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
pub struct GLMsaa {
buffer_count: u8,
sample_count: u8,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct GLContextSettings<'a> {
pub msaa: Requirement<'a, GLMsaa>,
pub version: Requirement<'a, GLVersion>,
pub debug : bool,
pub forward_compatible: bool, pub profile : Decision<GLProfile>,
pub depth_bits: u8,
pub stencil_bits: u8,
pub double_buffer: bool,
pub stereo: bool,
pub red_bits: u8,
pub green_bits: u8,
pub blue_bits: u8,
pub alpha_bits: u8,
pub accum_red_bits: u8,
pub accum_green_bits: u8,
pub accum_blue_bits: u8,
pub accum_alpha_bits: u8,
pub aux_buffers: u8,
}
impl<'a> Default for GLContextSettings<'a> {
fn default() -> Self {
Self {
msaa: Requirement::HighestAvailable,
version: Requirement::HighestAvailable,
.. Default::default()
}
}
}
impl<'a> GLContextSettings<'a> {
pub fn sanitize(&self) -> GLContextSettings<'static> {
unimplemented!()
}
}
impl<'win,'gl:'win,'dpy:'gl> GLContext<'dpy> {
pub fn make_current(&'gl self, window: &'win Window<'dpy>) -> GLSwapChain<'win,'gl,'dpy> {
self.0.make_current(&window.0);
let out = GLSwapChain { window, gl_context: self };
if out.set_interval(Default::default()).is_err() {
out.set_interval(GLSwapInterval::LimitFps(60)).unwrap();
}
out
}
pub unsafe fn get_proc_address(&self, name: *const c_char) -> Option<*const c_void> {
self.0.get_proc_address(name)
}
}
impl<'win,'gl:'win,'dpy:'gl> GLSwapChain<'win, 'gl, 'dpy> {
pub fn present(&self) {
self.window.0.gl_swap_buffers()
}
pub fn set_interval(&self, interval: GLSwapInterval) -> Result<(),Error> {
self.window.0.gl_set_swap_interval(interval)
}
pub fn force_make_current(&self) {
self.gl_context.0.make_current(&self.window.0);
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum GLSwapInterval {
VSync,
Immediate,
LimitFps(u32),
Interval(u32),
LateSwapTearing,
}
impl Default for GLSwapInterval {
fn default() -> Self {
GLSwapInterval::VSync
}
}