Add documentation for the egl buffer features

This commit is contained in:
Drakulix 2018-01-07 21:48:49 +01:00
parent efaadb8882
commit aaa68b1cce
12 changed files with 89 additions and 29 deletions

View File

@ -27,7 +27,6 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{Format, EGLDisplay, EGLWaylandExtensions};
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::wayland::compositor::roles::Role;
use smithay::wayland::shell::ShellState;
use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell;
use std::fs::{File, OpenOptions};
@ -35,7 +34,6 @@ use std::os::unix::io::RawFd;
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
use std::time::Duration;
use wayland_server::{StateToken};
#[derive(Debug)]
pub struct Card(File);
@ -125,7 +123,7 @@ fn main() {
init_shm_global(&mut event_loop, vec![], log.clone());
let (compositor_token, shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone());
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone());
/*
* Add a listening socket:
@ -141,7 +139,6 @@ fn main() {
&mut event_loop,
device_token,
DrmHandlerImpl {
shell_state_token,
compositor_token,
window_map: window_map.clone(),
drawer: renderer,
@ -158,7 +155,6 @@ fn main() {
}
pub struct DrmHandlerImpl {
shell_state_token: StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
window_map: Rc<RefCell<MyWindowMap>>,
drawer: GliumDrawer<DrmBackend<Card>>,

View File

@ -1,16 +1,14 @@
use glium;
use glium::{Frame, Surface, GlObject};
use glium::backend::Facade;
use glium::index::PrimitiveType;
use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d};
use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::error::Result as EGLResult;
use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions, BufferAccessError};
use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions};
use smithay::backend::graphics::glium::GliumGraphicsBackend;
use std::borrow::Borrow;
use std::ops::Deref;
use wayland_server::Display;
use wayland_server::protocol::wl_buffer::WlBuffer;
#[derive(Copy, Clone)]
struct Vertex {

View File

@ -19,7 +19,6 @@ extern crate ctrlc;
mod helpers;
use drm::Device as BasicDevice;
use drm::control::{Device as ControlDevice, ResourceInfo};
use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState};
use drm::control::encoder::Info as EncoderInfo;
@ -45,7 +44,6 @@ use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAct
use smithay::wayland::compositor::roles::Role;
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
use smithay::wayland::shell::ShellState;
use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell;
use std::collections::HashMap;
@ -56,7 +54,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::path::PathBuf;
use std::process::Command;
use std::os::unix::io::{AsRawFd, RawFd};
use xkbcommon::xkb::keysyms as xkb;
use wayland_server::{Display, StateToken, StateProxy};
use wayland_server::protocol::{wl_output, wl_pointer};
@ -199,7 +196,7 @@ fn main() {
*/
init_shm_global(&mut event_loop, vec![], log.clone());
let (compositor_token, shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
/*
* Initialize session on the current tty
@ -226,7 +223,6 @@ fn main() {
let bytes = include_bytes!("resources/cursor2.rgba");
let udev_token
= UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl {
shell_state_token,
compositor_token,
active_egl_context,
backends: HashMap::new(),
@ -307,10 +303,13 @@ fn main() {
let udev_event_source = udev_backend_bind(&mut event_loop, udev_token).unwrap();
while running.load(Ordering::SeqCst) {
event_loop.dispatch(Some(16));
if let Err(_) = event_loop.dispatch(Some(16)) {
running.store(false, Ordering::SeqCst);
} else {
display.flush_clients();
window_map.borrow_mut().refresh();
}
}
println!("Bye Bye");
@ -326,7 +325,6 @@ fn main() {
}
struct UdevHandlerImpl {
shell_state_token: StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
backends: HashMap<u64, Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>>,
@ -399,7 +397,6 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
self.backends.insert(device.device_id(), backends.clone());
Some(DrmHandlerImpl {
shell_state_token: self.shell_state_token.clone(),
compositor_token: self.compositor_token.clone(),
backends,
window_map: self.window_map.clone(),
@ -434,7 +431,6 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
}
pub struct DrmHandlerImpl {
shell_state_token: StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
compositor_token: CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
backends: Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>>>>,
window_map: Rc<RefCell<MyWindowMap>>,

View File

@ -14,6 +14,7 @@ use std::cell::Cell;
use std::rc::{Rc, Weak};
use wayland_server::Display;
/// Backend based on a `DrmDevice` and a given crtc
pub struct DrmBackend<A: Device + 'static> {
backend: Rc<DrmBackendInternal<A>>,
surface: EGLSurface<GbmSurface<framebuffer::Info>>,
@ -21,7 +22,6 @@ pub struct DrmBackend<A: Device + 'static> {
connectors: Vec<connector::Handle>,
}
/// Backend based on a `DrmDevice` and a given crtc
pub(crate) struct DrmBackendInternal<A: Device + 'static> {
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>,
cursor: Cell<BufferObject<()>>,

View File

@ -400,7 +400,9 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
}
}
/// Trait for types representing open devices
pub trait DevPath {
/// Returns the path of the open device if possible
fn dev_path(&self) -> Option<PathBuf>;
}
@ -556,7 +558,7 @@ where
#[cfg(feature = "backend_session")]
impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
fn pause<'a>(&mut self, state: &mut StateProxy<'a>) {
let device: &mut DrmDevice<A> = state.get_mut(self);
let device = state.get_mut(self);
device.active = false;
if let Err(err) = device.drop_master() {
error!(
@ -567,7 +569,7 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
}
fn activate<'a>(&mut self, state: &mut StateProxy<'a>) {
let mut device = state.get_mut(self);
let device = state.get_mut(self);
device.active = true;
if let Err(err) = device.set_master() {
crit!(

View File

@ -1,3 +1,5 @@
//! EGL context related structs
use super::{ffi, EGLSurface, PixelFormat};
use super::error::*;
use super::native;
@ -47,6 +49,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> DerefMut for EGLContext<B,
}
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
/// Create a new `EGLContext` from a given `NativeDisplay`
pub fn new<L>(
native: N,
attributes: GlAttributes,
@ -146,16 +149,16 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
Err(_) => ptr::null(),
}
});
let procAddress = constrain(|sym| {
let proc_address = constrain(|sym| {
let addr = CString::new(sym).unwrap();
let addr = addr.as_ptr();
ffi::egl::GetProcAddress(addr) as *const _
});
ffi::egl::load_with(&procAddress);
ffi::egl::BindWaylandDisplayWL::load_with(&procAddress);
ffi::egl::UnbindWaylandDisplayWL::load_with(&procAddress);
ffi::egl::QueryWaylandBufferWL::load_with(&procAddress);
ffi::gl::load_with(&procAddress);
ffi::egl::load_with(&proc_address);
ffi::egl::BindWaylandDisplayWL::load_with(&proc_address);
ffi::egl::UnbindWaylandDisplayWL::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

View File

@ -1,3 +1,5 @@
//! EGL error types
error_chain! {
errors {
#[doc = "The requested OpenGL version is not supported"]

View File

@ -1,4 +1,4 @@
//! Common traits and types for egl context creation and rendering
//! 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/

View File

@ -1,3 +1,5 @@
//! Type safe native types for safe context/surface creation
use super::ffi;
use super::error::*;
@ -18,9 +20,17 @@ use winit::os::unix::WindowExt;
#[cfg(feature = "backend_winit")]
use wayland_client::egl as wegl;
/// Trait for typed backend variants (X11/Wayland/GBM)
pub trait Backend {
/// Surface type created by this backend
type Surface: NativeSurface;
/// Return an `EGLDisplay` based on this backend
///
/// # Unsafety
///
/// The returned `EGLDisplay` needs to be a valid ptr for egl,
/// but there is no way to test that.
unsafe fn get_display<F: Fn(&str) -> bool>(
display: ffi::NativeDisplayType,
has_dp_extension: F,
@ -29,6 +39,7 @@ pub trait Backend {
}
#[cfg(feature = "backend_winit")]
/// Wayland backend type
pub enum Wayland {}
#[cfg(feature = "backend_winit")]
impl Backend for Wayland {
@ -65,8 +76,10 @@ impl Backend for Wayland {
}
#[cfg(feature = "backend_winit")]
/// Typed Xlib window for the `X11` backend
pub struct XlibWindow(u64);
#[cfg(feature = "backend_winit")]
/// X11 backend type
pub enum X11 {}
#[cfg(feature = "backend_winit")]
impl Backend for X11 {
@ -94,6 +107,7 @@ impl Backend for X11 {
}
}
#[cfg(feature = "backend_drm")]
/// Gbm backend type
pub struct Gbm<T: 'static> {
_userdata: PhantomData<T>,
}
@ -134,7 +148,9 @@ impl<T: 'static> Backend for Gbm<T> {
///
/// The returned `NativeDisplayType` must be valid for egl and there is no way to test that.
pub unsafe trait NativeDisplay<B: Backend> {
/// Arguments used to surface creation.
type Arguments;
/// Error type thrown by the surface creation in case of failure.
type Error: ::std::error::Error + Send + 'static;
/// Because one typ might implement multiple `Backend` this function must be called to check
/// if the expected `Backend` is used at runtime.

View File

@ -1,3 +1,5 @@
//! EGL surface related structs
use super::{EGLContext, SwapBuffersError};
use super::error::*;
use super::ffi;

View File

@ -1,3 +1,15 @@
//! Wayland specific EGL functionality - EGL based WlBuffers.
//!
//! The types of this module can be used to initialize hardware acceleration rendering
//! based on EGL for clients as it may enabled usage of `EGLImage` based `WlBuffer`s.
//!
//! To use it bind any backend implementing the `EGLWaylandExtensions` trait, that shall do the
//! rendering (so pick a fast one), to the `wayland_server::Display` of your compositor.
//! Note only one backend may be bould to any `Display` at any time.
//!
//! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer`
//! for rendering.
use backend::graphics::egl::{EGLContext, EglExtensionNotSupportedError, ffi, native};
use backend::graphics::egl::error::*;
use backend::graphics::egl::ffi::egl::types::EGLImage;
@ -113,17 +125,26 @@ impl ::std::error::Error for TextureCreationError {
}
}
/// Texture format types
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum Format {
/// RGB format
RGB = ffi::egl::TEXTURE_RGB as i32,
/// RGB + alpha channel format
RGBA = ffi::egl::TEXTURE_RGBA as i32,
/// External format
External = ffi::egl::TEXTURE_EXTERNAL_WL,
/// 2-plane Y and UV format
Y_UV = ffi::egl::TEXTURE_Y_UV_WL,
/// 3-plane Y, U and V format
Y_U_V = ffi::egl::TEXTURE_Y_U_V_WL,
/// 2-plane Y and XUXV format
Y_XUXV = ffi::egl::TEXTURE_Y_XUXV_WL,
}
impl Format {
/// Amount of planes this format uses
pub fn num_planes(&self) -> usize {
match *self {
Format::RGB | Format::RGBA | Format::External => 1,
@ -133,21 +154,34 @@ impl Format {
}
}
/// Images of the egl-based `WlBuffer`.
pub struct EGLImages {
display: Weak<ffi::egl::types::EGLDisplay>,
/// Width in pixels
pub width: u32,
/// Height in pixels
pub height: u32,
/// If the y-axis is inverted or not
pub y_inverted: bool,
/// Format of these images
pub format: Format,
images: Vec<EGLImage>,
buffer: WlBuffer,
}
impl EGLImages {
/// Amount of planes of these `EGLImages`
pub fn num_planes(&self) -> usize {
self.format.num_planes()
}
/// Bind plane to an OpenGL texture id
///
/// This does only temporarily modify the OpenGL state any changes are reverted before returning.
///
/// # Unsafety
///
/// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur.
pub unsafe fn bind_to_texture(&self, plane: usize, tex_id: c_uint) -> ::std::result::Result<(), TextureCreationError> {
if self.display.upgrade().is_some() {
let mut old_tex_id: i32 = 0;
@ -177,6 +211,8 @@ impl Drop for EGLImages {
}
}
/// Trait any backend type may implement that allows binding a `wayland_server::Display`
/// to create an `EGLDisplay` for egl-based `WlBuffer`s.
pub trait EGLWaylandExtensions {
/// Binds this EGL context to the given Wayland display.
///
@ -194,6 +230,9 @@ pub trait EGLWaylandExtensions {
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay>;
}
/// Type to recieve `EGLImages` for egl-based `WlBuffer`s.
///
/// Can be created by using `EGLWaylandExtensions::bind_wl_display`.
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
impl EGLDisplay {
@ -201,6 +240,11 @@ impl EGLDisplay {
EGLDisplay(Rc::downgrade(&context.display), display)
}
/// Try to recieve `EGLImages` from a given `WlBuffer`.
///
/// In case the buffer is not managed by egl (but e.g. the wayland::shm module)
/// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer
/// to render it another way.
pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> {
if let Some(display) = self.0.upgrade() {
let mut format: i32 = 0;

View File

@ -25,6 +25,7 @@ use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket,
use wayland_server::{EventLoopHandle, StateProxy, StateToken};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
/// Udev's `DrmDevice` type based on the underlying session
pub struct SessionFdDrmDevice(RawFd);
impl AsRawFd for SessionFdDrmDevice {