Add documentation for the egl buffer features
This commit is contained in:
parent
efaadb8882
commit
aaa68b1cce
|
@ -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>>,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,9 +303,12 @@ 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));
|
||||
display.flush_clients();
|
||||
window_map.borrow_mut().refresh();
|
||||
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>>,
|
||||
|
|
|
@ -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<()>>,
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! EGL error types
|
||||
|
||||
error_chain! {
|
||||
errors {
|
||||
#[doc = "The requested OpenGL version is not supported"]
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! EGL surface related structs
|
||||
|
||||
use super::{EGLContext, SwapBuffersError};
|
||||
use super::error::*;
|
||||
use super::ffi;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue