Move egl module
- Remove gbm code - rename EGLWaylandExtensions to EGLGraphicsBackend - remove OpenGL specific code where possible
This commit is contained in:
parent
96a57fcc5d
commit
c9e67cdfef
|
@ -1,16 +1,9 @@
|
||||||
//! EGL context related structs
|
//! EGL context related structs
|
||||||
|
|
||||||
use super::{error::*, ffi, native, EGLSurface, PixelFormat};
|
use super::{error::*, ffi, native, EGLSurface};
|
||||||
#[cfg(feature = "backend_drm")]
|
use backend::graphics::gl::PixelFormat;
|
||||||
use drm::control::Device as ControlDevice;
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
use drm::Device as BasicDevice;
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
use gbm::Device as GbmDevice;
|
|
||||||
use nix::libc::{c_int, c_void};
|
use nix::libc::{c_int, c_void};
|
||||||
use slog;
|
use slog;
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
@ -29,7 +22,6 @@ pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
||||||
pub(crate) surface_attributes: Vec<c_int>,
|
pub(crate) surface_attributes: Vec<c_int>,
|
||||||
pixel_format: PixelFormat,
|
pixel_format: PixelFormat,
|
||||||
pub(crate) wl_drm_support: bool,
|
pub(crate) wl_drm_support: bool,
|
||||||
pub(crate) egl_to_texture_support: bool,
|
|
||||||
logger: slog::Logger,
|
logger: slog::Logger,
|
||||||
_backend: PhantomData<B>,
|
_backend: PhantomData<B>,
|
||||||
}
|
}
|
||||||
|
@ -67,7 +59,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
surface_attributes,
|
surface_attributes,
|
||||||
pixel_format,
|
pixel_format,
|
||||||
wl_drm_support,
|
wl_drm_support,
|
||||||
egl_to_texture_support,
|
|
||||||
) = unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
) = unsafe { EGLContext::<B, N>::new_internal(ptr, attributes, reqs, log.clone()) }?;
|
||||||
|
|
||||||
Ok(EGLContext {
|
Ok(EGLContext {
|
||||||
|
@ -78,7 +69,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
surface_attributes,
|
surface_attributes,
|
||||||
pixel_format,
|
pixel_format,
|
||||||
wl_drm_support,
|
wl_drm_support,
|
||||||
egl_to_texture_support,
|
|
||||||
logger: log,
|
logger: log,
|
||||||
_backend: PhantomData,
|
_backend: PhantomData,
|
||||||
})
|
})
|
||||||
|
@ -96,7 +86,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
Vec<c_int>,
|
Vec<c_int>,
|
||||||
PixelFormat,
|
PixelFormat,
|
||||||
bool,
|
bool,
|
||||||
bool,
|
|
||||||
)> {
|
)> {
|
||||||
// If no version is given, try OpenGLES 3.0, if available,
|
// If no version is given, try OpenGLES 3.0, if available,
|
||||||
// fallback to 2.0 otherwise
|
// fallback to 2.0 otherwise
|
||||||
|
@ -129,13 +118,14 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn constrain<F>(f: F) -> F
|
||||||
|
where
|
||||||
|
F: for<'a> Fn(&'a str) -> *const ::std::os::raw::c_void,
|
||||||
|
{
|
||||||
|
f
|
||||||
|
};
|
||||||
|
|
||||||
ffi::egl::LOAD.call_once(|| {
|
ffi::egl::LOAD.call_once(|| {
|
||||||
fn constrain<F>(f: F) -> F
|
|
||||||
where
|
|
||||||
F: for<'a> Fn(&'a str) -> *const ::std::os::raw::c_void,
|
|
||||||
{
|
|
||||||
f
|
|
||||||
};
|
|
||||||
ffi::egl::load_with(|sym| {
|
ffi::egl::load_with(|sym| {
|
||||||
let name = CString::new(sym).unwrap();
|
let name = CString::new(sym).unwrap();
|
||||||
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
||||||
|
@ -153,7 +143,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
ffi::egl::BindWaylandDisplayWL::load_with(&proc_address);
|
ffi::egl::BindWaylandDisplayWL::load_with(&proc_address);
|
||||||
ffi::egl::UnbindWaylandDisplayWL::load_with(&proc_address);
|
ffi::egl::UnbindWaylandDisplayWL::load_with(&proc_address);
|
||||||
ffi::egl::QueryWaylandBufferWL::load_with(&proc_address);
|
ffi::egl::QueryWaylandBufferWL::load_with(&proc_address);
|
||||||
ffi::gl::load_with(&proc_address);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// the first step is to query the list of extensions without any display, if supported
|
// the first step is to query the list of extensions without any display, if supported
|
||||||
|
@ -435,17 +424,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
// make current and get list of gl extensions
|
// make current and get list of gl extensions
|
||||||
ffi::egl::MakeCurrent(display as *const _, ptr::null(), ptr::null(), context as *const _);
|
ffi::egl::MakeCurrent(display as *const _, ptr::null(), ptr::null(), context as *const _);
|
||||||
|
|
||||||
// the list of gl extensions supported by the context
|
|
||||||
let gl_extensions = {
|
|
||||||
let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _)
|
|
||||||
.to_bytes()
|
|
||||||
.to_vec();
|
|
||||||
let list = String::from_utf8(data).unwrap();
|
|
||||||
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
|
|
||||||
};
|
|
||||||
|
|
||||||
info!(log, "GL Extensions: {:?}", gl_extensions);
|
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
Rc::new(context as *const _),
|
Rc::new(context as *const _),
|
||||||
Rc::new(display as *const _),
|
Rc::new(display as *const _),
|
||||||
|
@ -453,25 +431,22 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
surface_attributes,
|
surface_attributes,
|
||||||
desc,
|
desc,
|
||||||
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"),
|
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"),
|
||||||
gl_extensions
|
|
||||||
.iter()
|
|
||||||
.any(|s| *s == "GL_OES_EGL_image" || *s == "GL_OES_EGL_image_base"),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a surface for rendering
|
/// Creates a surface for rendering
|
||||||
pub fn create_surface(&self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
pub fn create_surface(&mut self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
||||||
trace!(self.logger, "Creating EGL window surface.");
|
trace!(self.logger, "Creating EGL window surface.");
|
||||||
let res = EGLSurface::new(
|
let surface = self.native
|
||||||
self,
|
|
||||||
self.native
|
|
||||||
.create_surface(args)
|
.create_surface(args)
|
||||||
.chain_err(|| ErrorKind::SurfaceCreationFailed)?,
|
.chain_err(|| ErrorKind::SurfaceCreationFailed)?;
|
||||||
);
|
EGLSurface::new(
|
||||||
if res.is_ok() {
|
self,
|
||||||
|
surface,
|
||||||
|
).map(|x| {
|
||||||
debug!(self.logger, "EGL surface successfully created");
|
debug!(self.logger, "EGL surface successfully created");
|
||||||
}
|
x
|
||||||
res
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the address of an OpenGL function.
|
/// Returns the address of an OpenGL function.
|
||||||
|
@ -508,18 +483,6 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> Drop for EGLContext<B, N>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
impl<T: 'static, A: AsRawFd + 'static> AsRawFd for EGLContext<native::Gbm<T>, GbmDevice<A>> {
|
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
|
||||||
self.native.as_raw_fd()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
impl<T: 'static, A: BasicDevice + 'static> BasicDevice for EGLContext<native::Gbm<T>, GbmDevice<A>> {}
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
impl<T: 'static, A: ControlDevice + 'static> ControlDevice for EGLContext<native::Gbm<T>, GbmDevice<A>> {}
|
|
||||||
|
|
||||||
/// Attributes to use when creating an OpenGL context.
|
/// Attributes to use when creating an OpenGL context.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct GlAttributes {
|
pub struct GlAttributes {
|
|
@ -13,11 +13,6 @@ pub type NativeDisplayType = *const c_void;
|
||||||
pub type NativePixmapType = *const c_void;
|
pub type NativePixmapType = *const c_void;
|
||||||
pub type NativeWindowType = *const c_void;
|
pub type NativeWindowType = *const c_void;
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy))]
|
|
||||||
pub mod gl {
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy))]
|
#[cfg_attr(feature = "cargo-clippy", allow(clippy))]
|
||||||
pub mod egl {
|
pub mod egl {
|
||||||
use super::*;
|
use super::*;
|
|
@ -1,3 +1,10 @@
|
||||||
|
//! Common traits and types for egl rendering
|
||||||
|
//!
|
||||||
|
//! Large parts of this module are taken from
|
||||||
|
//! https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/src/api/egl/
|
||||||
|
//!
|
||||||
|
//! It therefore falls under glutin's Apache 2.0 license
|
||||||
|
//! (see https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/LICENSE)
|
||||||
//! Wayland specific EGL functionality - EGL based `WlBuffer`s.
|
//! Wayland specific EGL functionality - EGL based `WlBuffer`s.
|
||||||
//!
|
//!
|
||||||
//! The types of this module can be used to initialize hardware acceleration rendering
|
//! The types of this module can be used to initialize hardware acceleration rendering
|
||||||
|
@ -10,13 +17,11 @@
|
||||||
//! You may then use the resulting `EGLDisplay` to receive `EGLImages` of an EGL-based `WlBuffer`
|
//! You may then use the resulting `EGLDisplay` to receive `EGLImages` of an EGL-based `WlBuffer`
|
||||||
//! for rendering.
|
//! for rendering.
|
||||||
|
|
||||||
use backend::graphics::egl::{
|
#[cfg(feature = "renderer_gl")]
|
||||||
error::*,
|
use backend::graphics::gl::ffi as gl_ffi;
|
||||||
ffi::{self, egl::types::EGLImage},
|
|
||||||
native, EGLContext, EglExtensionNotSupportedError,
|
|
||||||
};
|
|
||||||
use nix::libc::c_uint;
|
use nix::libc::c_uint;
|
||||||
use std::{
|
use std::{
|
||||||
|
ffi::CStr,
|
||||||
fmt,
|
fmt,
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
};
|
};
|
||||||
|
@ -26,6 +31,49 @@ use wayland_server::{
|
||||||
};
|
};
|
||||||
use wayland_sys::server::wl_display;
|
use wayland_sys::server::wl_display;
|
||||||
|
|
||||||
|
pub mod context;
|
||||||
|
pub use self::context::EGLContext;
|
||||||
|
pub mod error;
|
||||||
|
use self::error::*;
|
||||||
|
|
||||||
|
#[allow(
|
||||||
|
non_camel_case_types,
|
||||||
|
dead_code,
|
||||||
|
unused_mut,
|
||||||
|
non_upper_case_globals
|
||||||
|
)]
|
||||||
|
pub mod ffi;
|
||||||
|
use self::ffi::egl::types::EGLImage;
|
||||||
|
|
||||||
|
pub mod native;
|
||||||
|
pub mod surface;
|
||||||
|
pub use self::surface::EGLSurface;
|
||||||
|
|
||||||
|
/// Error that can happen on optional EGL features
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct EglExtensionNotSupportedError(&'static [&'static str]);
|
||||||
|
|
||||||
|
impl fmt::Display for EglExtensionNotSupportedError {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
|
write!(
|
||||||
|
formatter,
|
||||||
|
"None of the following EGL extensions is supported by the underlying EGL implementation,
|
||||||
|
at least one is required: {:?}",
|
||||||
|
self.0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::error::Error for EglExtensionNotSupportedError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"The required EGL extension is not supported by the underlying EGL implementation"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&::std::error::Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can occur when accessing an EGL buffer
|
/// Error that can occur when accessing an EGL buffer
|
||||||
pub enum BufferAccessError {
|
pub enum BufferAccessError {
|
||||||
/// The corresponding Context is not alive anymore
|
/// The corresponding Context is not alive anymore
|
||||||
|
@ -104,6 +152,8 @@ pub enum TextureCreationError {
|
||||||
/// application on sleep and wakes it up later. However any OpenGL implementation
|
/// application on sleep and wakes it up later. However any OpenGL implementation
|
||||||
/// can theoretically lose the context at any time.
|
/// can theoretically lose the context at any time.
|
||||||
ContextLost,
|
ContextLost,
|
||||||
|
/// Required OpenGL Extension for texture creation is missing
|
||||||
|
GLExtensionNotSupported(&'static str),
|
||||||
/// Failed to bind the `EGLImage` to the given texture
|
/// Failed to bind the `EGLImage` to the given texture
|
||||||
///
|
///
|
||||||
/// The given argument is the GL error code
|
/// The given argument is the GL error code
|
||||||
|
@ -116,6 +166,9 @@ impl fmt::Display for TextureCreationError {
|
||||||
match *self {
|
match *self {
|
||||||
TextureCreationError::ContextLost => write!(formatter, "{}", self.description()),
|
TextureCreationError::ContextLost => write!(formatter, "{}", self.description()),
|
||||||
TextureCreationError::PlaneIndexOutOfBounds => write!(formatter, "{}", self.description()),
|
TextureCreationError::PlaneIndexOutOfBounds => write!(formatter, "{}", self.description()),
|
||||||
|
TextureCreationError::GLExtensionNotSupported(ext) => {
|
||||||
|
write!(formatter, "{}: {:}", self.description(), ext)
|
||||||
|
}
|
||||||
TextureCreationError::TextureBindingFailed(code) => {
|
TextureCreationError::TextureBindingFailed(code) => {
|
||||||
write!(formatter, "{}. Gl error code: {:?}", self.description(), code)
|
write!(formatter, "{}. Gl error code: {:?}", self.description(), code)
|
||||||
}
|
}
|
||||||
|
@ -128,6 +181,7 @@ impl ::std::error::Error for TextureCreationError {
|
||||||
match *self {
|
match *self {
|
||||||
TextureCreationError::ContextLost => "The context has been lost, it needs to be recreated",
|
TextureCreationError::ContextLost => "The context has been lost, it needs to be recreated",
|
||||||
TextureCreationError::PlaneIndexOutOfBounds => "This buffer is not managed by EGL",
|
TextureCreationError::PlaneIndexOutOfBounds => "This buffer is not managed by EGL",
|
||||||
|
TextureCreationError::GLExtensionNotSupported(_) => "Required OpenGL Extension for texture creation is missing",
|
||||||
TextureCreationError::TextureBindingFailed(_) => "Failed to create EGLImages from the buffer",
|
TextureCreationError::TextureBindingFailed(_) => "Failed to create EGLImages from the buffer",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,6 +234,10 @@ pub struct EGLImages {
|
||||||
pub format: Format,
|
pub format: Format,
|
||||||
images: Vec<EGLImage>,
|
images: Vec<EGLImage>,
|
||||||
buffer: Resource<WlBuffer>,
|
buffer: Resource<WlBuffer>,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
gl: gl_ffi::Gles2,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
egl_to_texture_support: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EGLImages {
|
impl EGLImages {
|
||||||
|
@ -195,17 +253,22 @@ impl EGLImages {
|
||||||
/// # Unsafety
|
/// # Unsafety
|
||||||
///
|
///
|
||||||
/// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur.
|
/// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur.
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
pub unsafe fn bind_to_texture(
|
pub unsafe fn bind_to_texture(
|
||||||
&self,
|
&self,
|
||||||
plane: usize,
|
plane: usize,
|
||||||
tex_id: c_uint,
|
tex_id: c_uint,
|
||||||
) -> ::std::result::Result<(), TextureCreationError> {
|
) -> ::std::result::Result<(), TextureCreationError> {
|
||||||
if self.display.upgrade().is_some() {
|
if self.display.upgrade().is_some() {
|
||||||
|
if !self.egl_to_texture_support {
|
||||||
|
return Err(TextureCreationError::GLExtensionNotSupported("GL_OES_EGL_image"));
|
||||||
|
}
|
||||||
|
|
||||||
let mut old_tex_id: i32 = 0;
|
let mut old_tex_id: i32 = 0;
|
||||||
ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_tex_id);
|
self.gl.GetIntegerv(gl_ffi::TEXTURE_BINDING_2D, &mut old_tex_id);
|
||||||
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id);
|
self.gl.BindTexture(gl_ffi::TEXTURE_2D, tex_id);
|
||||||
ffi::gl::EGLImageTargetTexture2DOES(
|
self.gl.EGLImageTargetTexture2DOES(
|
||||||
ffi::gl::TEXTURE_2D,
|
gl_ffi::TEXTURE_2D,
|
||||||
*self
|
*self
|
||||||
.images
|
.images
|
||||||
.get(plane)
|
.get(plane)
|
||||||
|
@ -215,7 +278,7 @@ impl EGLImages {
|
||||||
ffi::egl::SUCCESS => Ok(()),
|
ffi::egl::SUCCESS => Ok(()),
|
||||||
err => Err(TextureCreationError::TextureBindingFailed(err)),
|
err => Err(TextureCreationError::TextureBindingFailed(err)),
|
||||||
};
|
};
|
||||||
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, old_tex_id as u32);
|
self.gl.BindTexture(gl_ffi::TEXTURE_2D, old_tex_id as u32);
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
Err(TextureCreationError::ContextLost)
|
Err(TextureCreationError::ContextLost)
|
||||||
|
@ -238,7 +301,7 @@ impl Drop for EGLImages {
|
||||||
|
|
||||||
/// Trait any backend type may implement that allows binding a `wayland_server::Display`
|
/// Trait any backend type may implement that allows binding a `wayland_server::Display`
|
||||||
/// to create an `EGLDisplay` for EGL-based `WlBuffer`s.
|
/// to create an `EGLDisplay` for EGL-based `WlBuffer`s.
|
||||||
pub trait EGLWaylandExtensions {
|
pub trait EGLGraphicsBackend {
|
||||||
/// Binds this EGL context to the given Wayland display.
|
/// Binds this EGL context to the given Wayland display.
|
||||||
///
|
///
|
||||||
/// This will allow clients to utilize EGL to create hardware-accelerated
|
/// This will allow clients to utilize EGL to create hardware-accelerated
|
||||||
|
@ -257,15 +320,38 @@ pub trait EGLWaylandExtensions {
|
||||||
|
|
||||||
/// Type to receive `EGLImages` for EGL-based `WlBuffer`s.
|
/// Type to receive `EGLImages` for EGL-based `WlBuffer`s.
|
||||||
///
|
///
|
||||||
/// Can be created by using `EGLWaylandExtensions::bind_wl_display`.
|
/// Can be created by using `EGLGraphicsBackend::bind_wl_display`.
|
||||||
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
|
pub struct EGLDisplay {
|
||||||
|
egl: Weak<ffi::egl::types::EGLDisplay>,
|
||||||
|
wayland: *mut wl_display,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
gl: gl_ffi::Gles2,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
egl_to_texture_support: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl EGLDisplay {
|
impl EGLDisplay {
|
||||||
fn new<B: native::Backend, N: native::NativeDisplay<B>>(
|
fn new<B: native::Backend, N: native::NativeDisplay<B>>(
|
||||||
context: &EGLContext<B, N>,
|
context: &EGLContext<B, N>,
|
||||||
display: *mut wl_display,
|
display: *mut wl_display,
|
||||||
) -> EGLDisplay {
|
) -> EGLDisplay {
|
||||||
EGLDisplay(Rc::downgrade(&context.display), display)
|
let gl = gl_ffi::Gles2::load_with(|s| unsafe { context.get_proc_address(s) as *const _ });
|
||||||
|
|
||||||
|
EGLDisplay {
|
||||||
|
egl: Rc::downgrade(&context.display),
|
||||||
|
wayland: display,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
egl_to_texture_support: {
|
||||||
|
// the list of gl extensions supported by the context
|
||||||
|
let data = unsafe { CStr::from_ptr(gl.GetString(gl_ffi::EXTENSIONS) as *const _ )}
|
||||||
|
.to_bytes()
|
||||||
|
.to_vec();
|
||||||
|
let list = String::from_utf8(data).unwrap();
|
||||||
|
list.split(' ').any(|s| s == "GL_OES_EGL_image" || s == "GL_OES_EGL_image_base")
|
||||||
|
},
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
gl,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to receive `EGLImages` from a given `WlBuffer`.
|
/// Try to receive `EGLImages` from a given `WlBuffer`.
|
||||||
|
@ -277,7 +363,7 @@ impl EGLDisplay {
|
||||||
&self,
|
&self,
|
||||||
buffer: Resource<WlBuffer>,
|
buffer: Resource<WlBuffer>,
|
||||||
) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
||||||
if let Some(display) = self.0.upgrade() {
|
if let Some(display) = self.egl.upgrade() {
|
||||||
let mut format: i32 = 0;
|
let mut format: i32 = 0;
|
||||||
if unsafe {
|
if unsafe {
|
||||||
ffi::egl::QueryWaylandBufferWL(
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
@ -368,6 +454,10 @@ impl EGLDisplay {
|
||||||
format,
|
format,
|
||||||
images,
|
images,
|
||||||
buffer,
|
buffer,
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
gl: self.gl.clone(),
|
||||||
|
#[cfg(feature = "renderer_gl")]
|
||||||
|
egl_to_texture_support: self.egl_to_texture_support,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(BufferAccessError::ContextLost)
|
Err(BufferAccessError::ContextLost)
|
||||||
|
@ -377,32 +467,29 @@ impl EGLDisplay {
|
||||||
|
|
||||||
impl Drop for EGLDisplay {
|
impl Drop for EGLDisplay {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(display) = self.0.upgrade() {
|
if let Some(display) = self.egl.upgrade() {
|
||||||
if !self.1.is_null() {
|
if !self.wayland.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::egl::UnbindWaylandDisplayWL(*display, self.1 as *mut _);
|
ffi::egl::UnbindWaylandDisplayWL(*display, self.wayland as *mut _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E> {
|
impl<E: EGLGraphicsBackend> EGLGraphicsBackend for Rc<E> {
|
||||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||||
(**self).bind_wl_display(display)
|
(**self).bind_wl_display(display)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLWaylandExtensions for EGLContext<B, N> {
|
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLGraphicsBackend for EGLContext<B, N> {
|
||||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||||
if !self.wl_drm_support {
|
if !self.wl_drm_support {
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&[
|
bail!(ErrorKind::EglExtensionNotSupported(&[
|
||||||
"EGL_WL_bind_wayland_display"
|
"EGL_WL_bind_wayland_display"
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
if !self.egl_to_texture_support {
|
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));
|
|
||||||
}
|
|
||||||
let res = unsafe { ffi::egl::BindWaylandDisplayWL(*self.display, display.c_ptr() as *mut _) };
|
let res = unsafe { ffi::egl::BindWaylandDisplayWL(*self.display, display.c_ptr() as *mut _) };
|
||||||
if res == 0 {
|
if res == 0 {
|
||||||
bail!(ErrorKind::OtherEGLDisplayAlreadyBound);
|
bail!(ErrorKind::OtherEGLDisplayAlreadyBound);
|
|
@ -1,16 +1,11 @@
|
||||||
//! Type safe native types for safe context/surface creation
|
//! Type safe native types for safe context/surface creation
|
||||||
|
|
||||||
use super::{error::*, ffi};
|
use super::{error::*, ffi};
|
||||||
#[cfg(feature = "backend_drm")]
|
use backend::graphics::SwapBuffersError;
|
||||||
use backend::drm::error::{Error as DrmError, ErrorKind as DrmErrorKind, Result as DrmResult};
|
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_winit")]
|
||||||
use gbm::{AsRaw, BufferObjectFlags, Device as GbmDevice, Format as GbmFormat, Surface as GbmSurface};
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
use std::os::unix::io::AsRawFd;
|
|
||||||
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
use wayland_client::egl as wegl;
|
use wayland_client::egl as wegl;
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
|
@ -95,38 +90,6 @@ impl Backend for X11 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
/// Gbm backend type
|
|
||||||
pub struct Gbm<T: 'static> {
|
|
||||||
_userdata: PhantomData<T>,
|
|
||||||
}
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
impl<T: 'static> Backend for Gbm<T> {
|
|
||||||
type Surface = GbmSurface<T>;
|
|
||||||
|
|
||||||
unsafe fn get_display<F>(
|
|
||||||
display: ffi::NativeDisplayType,
|
|
||||||
has_dp_extension: F,
|
|
||||||
log: ::slog::Logger,
|
|
||||||
) -> ffi::egl::types::EGLDisplay
|
|
||||||
where
|
|
||||||
F: Fn(&str) -> bool,
|
|
||||||
{
|
|
||||||
if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
|
|
||||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
|
||||||
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
|
||||||
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
|
||||||
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
|
||||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
|
||||||
} else {
|
|
||||||
trace!(log, "Default EGL Display Initialization via GetDisplay");
|
|
||||||
ffi::egl::GetDisplay(display as *mut _)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for types returning Surfaces which can be used to initialize `EGLSurface`s
|
/// Trait for types returning Surfaces which can be used to initialize `EGLSurface`s
|
||||||
///
|
///
|
||||||
|
@ -144,7 +107,7 @@ pub unsafe trait NativeDisplay<B: Backend> {
|
||||||
/// Return a raw pointer EGL will accept for context creation.
|
/// Return a raw pointer EGL will accept for context creation.
|
||||||
fn ptr(&self) -> Result<ffi::NativeDisplayType>;
|
fn ptr(&self) -> Result<ffi::NativeDisplayType>;
|
||||||
/// Create a surface
|
/// Create a surface
|
||||||
fn create_surface(&self, args: Self::Arguments) -> ::std::result::Result<B::Surface, Self::Error>;
|
fn create_surface(&mut self, args: Self::Arguments) -> ::std::result::Result<B::Surface, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
|
@ -162,7 +125,7 @@ unsafe impl NativeDisplay<X11> for WinitWindow {
|
||||||
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
|
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_surface(&self, _args: ()) -> Result<XlibWindow> {
|
fn create_surface(&mut self, _args: ()) -> Result<XlibWindow> {
|
||||||
self.get_xlib_window()
|
self.get_xlib_window()
|
||||||
.map(XlibWindow)
|
.map(XlibWindow)
|
||||||
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
|
.ok_or(ErrorKind::NonMatchingBackend("X11").into())
|
||||||
|
@ -184,7 +147,7 @@ unsafe impl NativeDisplay<Wayland> for WinitWindow {
|
||||||
.ok_or(ErrorKind::NonMatchingBackend("Wayland").into())
|
.ok_or(ErrorKind::NonMatchingBackend("Wayland").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_surface(&self, _args: ()) -> Result<wegl::WlEglSurface> {
|
fn create_surface(&mut self, _args: ()) -> Result<wegl::WlEglSurface> {
|
||||||
if let Some(surface) = self.get_wayland_surface() {
|
if let Some(surface) = self.get_wayland_surface() {
|
||||||
let size = self.get_inner_size().unwrap();
|
let size = self.get_inner_size().unwrap();
|
||||||
Ok(unsafe {
|
Ok(unsafe {
|
||||||
|
@ -196,41 +159,7 @@ unsafe impl NativeDisplay<Wayland> for WinitWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
/// Trait for types returning valid surface pointers for initializing egl
|
||||||
/// Arguments necessary to construct a `GbmSurface`
|
|
||||||
pub struct GbmSurfaceArguments {
|
|
||||||
/// Size of the surface
|
|
||||||
pub size: (u32, u32),
|
|
||||||
/// Pixel format of the surface
|
|
||||||
pub format: GbmFormat,
|
|
||||||
/// Flags for surface creation
|
|
||||||
pub flags: BufferObjectFlags,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevice<A> {
|
|
||||||
type Arguments = GbmSurfaceArguments;
|
|
||||||
type Error = DrmError;
|
|
||||||
|
|
||||||
fn is_backend(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
|
|
||||||
Ok(self.as_raw() as *const _)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_surface(&self, args: GbmSurfaceArguments) -> DrmResult<GbmSurface<T>> {
|
|
||||||
use backend::drm::error::ResultExt as DrmResultExt;
|
|
||||||
|
|
||||||
DrmResultExt::chain_err(
|
|
||||||
GbmDevice::create_surface(self, args.size.0, args.size.1, args.format, args.flags),
|
|
||||||
|| DrmErrorKind::GbmInitFailed,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for types returning valid surface pointers for initializing EGL
|
|
||||||
///
|
///
|
||||||
/// ## Unsafety
|
/// ## Unsafety
|
||||||
///
|
///
|
||||||
|
@ -238,6 +167,14 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
|
||||||
pub unsafe trait NativeSurface {
|
pub unsafe trait NativeSurface {
|
||||||
/// Return a raw pointer egl will accept for surface creation.
|
/// Return a raw pointer egl will accept for surface creation.
|
||||||
fn ptr(&self) -> ffi::NativeWindowType;
|
fn ptr(&self) -> ffi::NativeWindowType;
|
||||||
|
/// Adds additional semantics when calling EGLSurface::swap_buffers
|
||||||
|
///
|
||||||
|
/// Only implement if required by the backend, flip must be called during this call.
|
||||||
|
fn swap_buffers<F>(&self, flip: F) -> ::std::result::Result<(), SwapBuffersError>
|
||||||
|
where F: FnOnce() -> ::std::result::Result<(), SwapBuffersError>
|
||||||
|
{
|
||||||
|
flip()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
|
@ -253,10 +190,3 @@ unsafe impl NativeSurface for wegl::WlEglSurface {
|
||||||
self.ptr() as *const _
|
self.ptr() as *const _
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
|
||||||
unsafe impl<T: 'static> NativeSurface for GbmSurface<T> {
|
|
||||||
fn ptr(&self) -> ffi::NativeWindowType {
|
|
||||||
self.as_raw() as *const _
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! EGL surface related structs
|
//! EGL surface related structs
|
||||||
|
|
||||||
use super::{error::*, ffi, native, EGLContext, SwapBuffersError};
|
use super::{error::*, ffi, native, EGLContext};
|
||||||
|
use backend::graphics::SwapBuffersError;
|
||||||
use std::{
|
use std::{
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
rc::{Rc, Weak},
|
rc::{Rc, Weak},
|
||||||
|
@ -55,20 +56,22 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
||||||
|
|
||||||
/// Swaps buffers at the end of a frame.
|
/// Swaps buffers at the end of a frame.
|
||||||
pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||||
if let Some(display) = self.display.upgrade() {
|
self.native.swap_buffers(|| {
|
||||||
let ret = unsafe { ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _) };
|
if let Some(display) = self.display.upgrade() {
|
||||||
|
let ret = unsafe { ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _) };
|
||||||
|
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
match unsafe { ffi::egl::GetError() } as u32 {
|
match unsafe { ffi::egl::GetError() } as u32 {
|
||||||
ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost),
|
ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost),
|
||||||
err => Err(SwapBuffersError::Unknown(err)),
|
err => Err(SwapBuffersError::Unknown(err)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Err(SwapBuffersError::ContextLost)
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
Err(SwapBuffersError::ContextLost)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes the OpenGL context the current context in the current thread.
|
/// Makes the OpenGL context the current context in the current thread.
|
|
@ -1,155 +0,0 @@
|
||||||
//! Common traits and types for EGL rendering
|
|
||||||
|
|
||||||
// Large parts of this module are taken from
|
|
||||||
// https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/src/api/egl/
|
|
||||||
//
|
|
||||||
// It therefore falls under glutin's Apache 2.0 license
|
|
||||||
// (see https://github.com/tomaka/glutin/tree/044e651edf67a2029eecc650dd42546af1501414/LICENSE)
|
|
||||||
|
|
||||||
use super::GraphicsBackend;
|
|
||||||
use nix::libc::c_void;
|
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub mod context;
|
|
||||||
pub use self::context::EGLContext;
|
|
||||||
pub mod error;
|
|
||||||
#[allow(
|
|
||||||
non_camel_case_types,
|
|
||||||
dead_code,
|
|
||||||
unused_mut,
|
|
||||||
non_upper_case_globals
|
|
||||||
)]
|
|
||||||
pub mod ffi;
|
|
||||||
pub mod native;
|
|
||||||
pub mod surface;
|
|
||||||
pub use self::surface::EGLSurface;
|
|
||||||
pub mod wayland;
|
|
||||||
pub use self::wayland::{BufferAccessError, EGLImages, EGLWaylandExtensions};
|
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum SwapBuffersError {
|
|
||||||
/// The OpenGL context has been lost and needs to be recreated.
|
|
||||||
///
|
|
||||||
/// All the objects associated to it (textures, buffers, programs, etc.)
|
|
||||||
/// need to be recreated from scratch.
|
|
||||||
///
|
|
||||||
/// Operations will have no effect. Functions that read textures, buffers, etc.
|
|
||||||
/// from OpenGL will return uninitialized data instead.
|
|
||||||
///
|
|
||||||
/// A context loss usually happens on mobile devices when the user puts the
|
|
||||||
/// application to sleep and wakes it up later. However any OpenGL implementation
|
|
||||||
/// can theoretically lose the context at any time.
|
|
||||||
ContextLost,
|
|
||||||
/// The buffers have already been swapped.
|
|
||||||
///
|
|
||||||
/// This error can be returned when `swap_buffers` has been called multiple times
|
|
||||||
/// without any modification in between.
|
|
||||||
AlreadySwapped,
|
|
||||||
/// Unknown GL error
|
|
||||||
Unknown(u32),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for SwapBuffersError {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
|
||||||
use std::error::Error;
|
|
||||||
write!(formatter, "{}", self.description())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::error::Error for SwapBuffersError {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
match *self {
|
|
||||||
SwapBuffersError::ContextLost => "The context has been lost, it needs to be recreated",
|
|
||||||
SwapBuffersError::AlreadySwapped => {
|
|
||||||
"Buffers are already swapped, swap_buffers was called too many times"
|
|
||||||
}
|
|
||||||
SwapBuffersError::Unknown(_) => "Unknown Open GL error occurred",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cause(&self) -> Option<&::std::error::Error> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error that can happen on optional EGL features
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct EglExtensionNotSupportedError(&'static [&'static str]);
|
|
||||||
|
|
||||||
impl fmt::Display for EglExtensionNotSupportedError {
|
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
|
||||||
write!(
|
|
||||||
formatter,
|
|
||||||
"None of the following EGL extensions is supported by the underlying EGL implementation,
|
|
||||||
at least one is required: {:?}",
|
|
||||||
self.0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::error::Error for EglExtensionNotSupportedError {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
"The required EGL extension is not supported by the underlying EGL implementation"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cause(&self) -> Option<&::std::error::Error> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes the pixel format of the main framebuffer
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct PixelFormat {
|
|
||||||
/// is the format hardware accelerated
|
|
||||||
pub hardware_accelerated: bool,
|
|
||||||
/// number of bits used for colors
|
|
||||||
pub color_bits: u8,
|
|
||||||
/// number of bits used for alpha channel
|
|
||||||
pub alpha_bits: u8,
|
|
||||||
/// number of bits used for depth channel
|
|
||||||
pub depth_bits: u8,
|
|
||||||
/// number of bits used for stencil buffer
|
|
||||||
pub stencil_bits: u8,
|
|
||||||
/// is stereoscopy enabled
|
|
||||||
pub stereoscopy: bool,
|
|
||||||
/// is double buffering enabled
|
|
||||||
pub double_buffer: bool,
|
|
||||||
/// number of samples used for multisampling if enabled
|
|
||||||
pub multisampling: Option<u16>,
|
|
||||||
/// is srgb enabled
|
|
||||||
pub srgb: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait that describes objects that have an OpenGL context
|
|
||||||
/// and can be used to render upon
|
|
||||||
pub trait EGLGraphicsBackend: GraphicsBackend {
|
|
||||||
/// Swaps buffers at the end of a frame.
|
|
||||||
fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError>;
|
|
||||||
|
|
||||||
/// Returns the address of an OpenGL function.
|
|
||||||
///
|
|
||||||
/// Supposes that the context has been made current before this function is called.
|
|
||||||
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void;
|
|
||||||
|
|
||||||
/// Returns the dimensions of the window, or screen, etc in points.
|
|
||||||
///
|
|
||||||
/// That are the scaled pixels of the underlying graphics backend.
|
|
||||||
/// For nested compositors this will respect the scaling of the root compositor.
|
|
||||||
/// For drawing directly onto hardware this unit will be equal to actual pixels.
|
|
||||||
fn get_framebuffer_dimensions(&self) -> (u32, u32);
|
|
||||||
|
|
||||||
/// Returns `true` if the OpenGL context is the current one in the thread.
|
|
||||||
fn is_current(&self) -> bool;
|
|
||||||
|
|
||||||
/// Makes the OpenGL context the current context in the current thread.
|
|
||||||
///
|
|
||||||
/// # Unsafety
|
|
||||||
///
|
|
||||||
/// This function is marked unsafe, because the context cannot be made current
|
|
||||||
/// on multiple threads.
|
|
||||||
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError>;
|
|
||||||
|
|
||||||
/// Returns the pixel format of the main framebuffer of the context.
|
|
||||||
fn get_pixel_format(&self) -> PixelFormat;
|
|
||||||
}
|
|
Loading…
Reference in New Issue