anvil: allow for non-egl builds
This commit is contained in:
parent
f2466c5c50
commit
f8a5e8bfde
|
@ -11,8 +11,8 @@ members = [ "anvil" ]
|
|||
|
||||
[dependencies]
|
||||
wayland-server = "0.21.6"
|
||||
wayland-sys = "0.21.3"
|
||||
wayland-commons = "0.21.1"
|
||||
wayland-sys = { version = "0.21.6", optional = true }
|
||||
nix = "0.11"
|
||||
xkbcommon = "0.2.1"
|
||||
tempfile = "2.1.5"
|
||||
|
@ -28,7 +28,7 @@ input = { version = "0.4.0", optional = true }
|
|||
udev = { version = "0.2.0", optional = true }
|
||||
dbus = { version = "0.6.1", optional = true }
|
||||
systemd = { version = "^0.2.0", optional = true }
|
||||
wayland-protocols = { version = "0.21.3", features = ["unstable_protocols", "native_server"] }
|
||||
wayland-protocols = { version = "0.21.3", features = ["unstable_protocols", "server"] }
|
||||
image = "0.17.0"
|
||||
error-chain = "0.11.0"
|
||||
lazy_static = "1.0.0"
|
||||
|
@ -38,7 +38,7 @@ gl_generator = { version = "0.9", optional = true }
|
|||
|
||||
[features]
|
||||
default = ["backend_winit", "backend_drm_legacy", "backend_drm_gbm", "backend_drm_egl", "backend_libinput", "backend_udev", "backend_session", "renderer_glium", "xwayland"]
|
||||
backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl"]
|
||||
backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl", "native_lib"]
|
||||
backend_drm = ["drm"]
|
||||
backend_drm_legacy = ["backend_drm"]
|
||||
backend_drm_gbm = ["backend_drm", "gbm"]
|
||||
|
@ -50,4 +50,5 @@ backend_udev = ["udev"]
|
|||
backend_session_logind = ["dbus", "systemd", "backend_session"]
|
||||
renderer_gl = ["gl_generator"]
|
||||
renderer_glium = ["renderer_gl", "glium"]
|
||||
native_lib = ["wayland-sys", "wayland-server/native_lib", "wayland-protocols/native_server"]
|
||||
xwayland = []
|
|
@ -23,7 +23,8 @@ features = [ "renderer_glium" ]
|
|||
gl_generator = "0.9"
|
||||
|
||||
[features]
|
||||
default = [ "winit", "udev" ]
|
||||
default = [ "winit", "egl", "udev" ]
|
||||
egl = [ "smithay/native_lib" ]
|
||||
winit = [ "smithay/backend_winit" ]
|
||||
udev = [ "smithay/backend_libinput", "smithay/backend_drm", "smithay/backend_udev", "smithay/backend_session" ]
|
||||
udev = [ "smithay/backend_libinput", "smithay/backend_drm_legacy", "smithay/backend_drm_gbm", "smithay/backend_drm_egl", "smithay/backend_udev", "smithay/backend_session" ]
|
||||
logind = [ "smithay/backend_session_logind" ]
|
||||
|
|
|
@ -11,9 +11,11 @@ use glium::{
|
|||
};
|
||||
use slog::Logger;
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
use smithay::backend::egl::EGLDisplay;
|
||||
use smithay::{
|
||||
backend::{
|
||||
egl::{BufferAccessError, EGLDisplay, EGLImages, Format},
|
||||
egl::{BufferAccessError, EGLImages, Format},
|
||||
graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend},
|
||||
},
|
||||
wayland::{
|
||||
|
@ -39,6 +41,7 @@ pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
|
|||
vertex_buffer: glium::VertexBuffer<Vertex>,
|
||||
index_buffer: glium::IndexBuffer<u16>,
|
||||
programs: [glium::Program; shaders::FRAGMENT_COUNT],
|
||||
#[cfg(feature = "egl")]
|
||||
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
||||
log: Logger,
|
||||
}
|
||||
|
@ -50,6 +53,7 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
|||
}
|
||||
|
||||
impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer<T> {
|
||||
#[cfg(feature = "egl")]
|
||||
pub fn init(backend: T, egl_display: Rc<RefCell<Option<EGLDisplay>>>, log: Logger) -> GliumDrawer<T> {
|
||||
let display = backend.into();
|
||||
|
||||
|
@ -91,9 +95,52 @@ impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer
|
|||
log,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "egl"))]
|
||||
pub fn init(backend: T, log: Logger) -> GliumDrawer<T> {
|
||||
let display = backend.into();
|
||||
|
||||
// building the vertex buffer, which contains all the vertices that we will draw
|
||||
let vertex_buffer = glium::VertexBuffer::new(
|
||||
&display,
|
||||
&[
|
||||
Vertex {
|
||||
position: [0.0, 0.0],
|
||||
tex_coords: [0.0, 0.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [0.0, 1.0],
|
||||
tex_coords: [0.0, 1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [1.0, 1.0],
|
||||
tex_coords: [1.0, 1.0],
|
||||
},
|
||||
Vertex {
|
||||
position: [1.0, 0.0],
|
||||
tex_coords: [1.0, 0.0],
|
||||
},
|
||||
],
|
||||
).unwrap();
|
||||
|
||||
// building the index buffer
|
||||
let index_buffer =
|
||||
glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();
|
||||
|
||||
let programs = opengl_programs!(&display);
|
||||
|
||||
GliumDrawer {
|
||||
display,
|
||||
vertex_buffer,
|
||||
index_buffer,
|
||||
programs,
|
||||
log,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||
#[cfg(feature = "egl")]
|
||||
pub fn texture_from_buffer(&self, buffer: Resource<wl_buffer::WlBuffer>) -> Result<TextureMetadata, ()> {
|
||||
// try to retrieve the egl contents of this buffer
|
||||
let images = if let Some(display) = &self.egl_display.borrow().as_ref() {
|
||||
|
@ -134,26 +181,7 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
|||
}
|
||||
Err(BufferAccessError::NotManaged(buffer)) => {
|
||||
// this is not an EGL buffer, try SHM
|
||||
match shm_buffer_contents(&buffer, |slice, data| {
|
||||
::shm_load::load_shm_buffer(data, slice)
|
||||
.map(|(image, kind)| (Texture2d::new(&self.display, image).unwrap(), kind, data))
|
||||
}) {
|
||||
Ok(Ok((texture, kind, data))) => Ok(TextureMetadata {
|
||||
texture,
|
||||
fragment: kind,
|
||||
y_inverted: false,
|
||||
dimensions: (data.width as u32, data.height as u32),
|
||||
images: None,
|
||||
}),
|
||||
Ok(Err(format)) => {
|
||||
warn!(self.log, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
|
||||
Err(())
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
self.texture_from_shm_buffer(buffer)
|
||||
}
|
||||
Err(err) => {
|
||||
error!(self.log, "EGL error"; "err" => format!("{:?}", err));
|
||||
|
@ -162,6 +190,35 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "egl"))]
|
||||
pub fn texture_from_buffer(&self, buffer: Resource<wl_buffer::WlBuffer>) -> Result<TextureMetadata, ()> {
|
||||
self.texture_from_shm_buffer(buffer)
|
||||
}
|
||||
|
||||
fn texture_from_shm_buffer(&self, buffer: Resource<wl_buffer::WlBuffer>) -> Result<TextureMetadata, ()> {
|
||||
match shm_buffer_contents(&buffer, |slice, data| {
|
||||
::shm_load::load_shm_buffer(data, slice)
|
||||
.map(|(image, kind)| (Texture2d::new(&self.display, image).unwrap(), kind, data))
|
||||
}) {
|
||||
Ok(Ok((texture, kind, data))) => Ok(TextureMetadata {
|
||||
texture,
|
||||
fragment: kind,
|
||||
y_inverted: false,
|
||||
dimensions: (data.width as u32, data.height as u32),
|
||||
#[cfg(feature = "egl")]
|
||||
images: None,
|
||||
}),
|
||||
Ok(Err(format)) => {
|
||||
warn!(self.log, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
|
||||
Err(())
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_texture(
|
||||
&self,
|
||||
target: &mut glium::Frame,
|
||||
|
@ -218,6 +275,7 @@ pub struct TextureMetadata {
|
|||
pub fragment: usize,
|
||||
pub y_inverted: bool,
|
||||
pub dimensions: (u32, u32),
|
||||
#[cfg(feature = "egl")]
|
||||
images: Option<EGLImages>,
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
|||
use slog::Logger;
|
||||
|
||||
#[cfg(feature = "udev")]
|
||||
use smithay::backend::session::{Session, auto::AutoSession};
|
||||
use smithay::backend::session::{auto::AutoSession, Session};
|
||||
use smithay::{
|
||||
backend::input::{
|
||||
self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent, PointerAxisEvent,
|
||||
|
|
|
@ -14,6 +14,8 @@ use std::{
|
|||
use glium::Surface as GliumSurface;
|
||||
use slog::Logger;
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
use smithay::backend::egl::{EGLDisplay, EGLGraphicsBackend};
|
||||
use smithay::{
|
||||
backend::{
|
||||
drm::{
|
||||
|
@ -23,7 +25,6 @@ use smithay::{
|
|||
legacy::LegacyDrmDevice,
|
||||
DevPath, Device, DeviceHandler, Surface,
|
||||
},
|
||||
egl::{EGLDisplay, EGLGraphicsBackend},
|
||||
graphics::CursorBackend,
|
||||
input::InputBackend,
|
||||
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
|
||||
|
@ -79,6 +80,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
|||
info!(log, "Listening on wayland socket"; "name" => name.clone());
|
||||
::std::env::set_var("WAYLAND_DISPLAY", name);
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
let active_egl_context = Rc::new(RefCell::new(None));
|
||||
|
||||
let display = Rc::new(RefCell::new(display));
|
||||
|
@ -114,6 +116,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
|||
&context,
|
||||
UdevHandlerImpl {
|
||||
compositor_token,
|
||||
#[cfg(feature = "egl")]
|
||||
active_egl_context,
|
||||
session: session.clone(),
|
||||
backends: HashMap::new(),
|
||||
|
@ -226,6 +229,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
|||
|
||||
struct UdevHandlerImpl<S: SessionNotifier, Data: 'static> {
|
||||
compositor_token: CompositorToken<SurfaceData, Roles>,
|
||||
#[cfg(feature = "egl")]
|
||||
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
|
||||
session: AutoSession,
|
||||
backends: HashMap<
|
||||
|
@ -247,6 +251,7 @@ struct UdevHandlerImpl<S: SessionNotifier, Data: 'static> {
|
|||
}
|
||||
|
||||
impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
|
||||
#[cfg(feature = "egl")]
|
||||
pub fn scan_connectors(
|
||||
device: &mut RenderDevice,
|
||||
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
||||
|
@ -295,6 +300,54 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
|
|||
|
||||
backends
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "egl"))]
|
||||
pub fn scan_connectors(
|
||||
device: &mut RenderDevice,
|
||||
logger: &::slog::Logger,
|
||||
) -> HashMap<crtc::Handle, GliumDrawer<RenderSurface>> {
|
||||
// Get a set of all modesetting resource handles (excluding planes):
|
||||
let res_handles = device.resource_handles().unwrap();
|
||||
|
||||
// Use first connected connector
|
||||
let connector_infos: Vec<ConnectorInfo> = res_handles
|
||||
.connectors()
|
||||
.iter()
|
||||
.map(|conn| device.resource_info::<ConnectorInfo>(*conn).unwrap())
|
||||
.filter(|conn| conn.connection_state() == ConnectorState::Connected)
|
||||
.inspect(|conn| info!(logger, "Connected: {:?}", conn.connector_type()))
|
||||
.collect();
|
||||
|
||||
let mut backends = HashMap::new();
|
||||
|
||||
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
|
||||
for connector_info in connector_infos {
|
||||
let encoder_infos = connector_info
|
||||
.encoders()
|
||||
.iter()
|
||||
.flat_map(|encoder_handle| device.resource_info::<EncoderInfo>(*encoder_handle))
|
||||
.collect::<Vec<EncoderInfo>>();
|
||||
for encoder_info in encoder_infos {
|
||||
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
||||
if !backends.contains_key(&crtc) {
|
||||
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
||||
// create a backend
|
||||
let renderer = GliumDrawer::init(
|
||||
device
|
||||
.create_surface(crtc, mode, vec![connector_info.handle()].into_iter())
|
||||
.unwrap(),
|
||||
logger.clone(),
|
||||
);
|
||||
|
||||
backends.insert(crtc, renderer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backends
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data> {
|
||||
|
@ -310,16 +363,27 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>
|
|||
.and_then(|gbm| EglDevice::new(gbm, self.logger.clone()).ok())
|
||||
{
|
||||
// init hardware acceleration on the primary gpu.
|
||||
if path.canonicalize().ok() == self.primary_gpu {
|
||||
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok();
|
||||
#[cfg(feature = "egl")]
|
||||
{
|
||||
if path.canonicalize().ok() == self.primary_gpu {
|
||||
*self.active_egl_context.borrow_mut() =
|
||||
device.bind_wl_display(&*self.display.borrow()).ok();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||
&mut device,
|
||||
self.active_egl_context.clone(),
|
||||
&self.logger,
|
||||
)));
|
||||
|
||||
#[cfg(not(feature = "egl"))]
|
||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||
&mut device,
|
||||
&self.logger,
|
||||
)));
|
||||
|
||||
device.set_handler(DrmHandlerImpl {
|
||||
compositor_token: self.compositor_token,
|
||||
backends: backends.clone(),
|
||||
|
@ -360,11 +424,15 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>
|
|||
let source = evt_source.clone_inner();
|
||||
let mut evented = source.borrow_mut();
|
||||
let mut backends = backends.borrow_mut();
|
||||
*backends = UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||
#[cfg(feature = "egl")]
|
||||
let new_backends = UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||
&mut (*evented).0,
|
||||
self.active_egl_context.clone(),
|
||||
&self.logger,
|
||||
);
|
||||
#[cfg(not(feature = "egl"))]
|
||||
let new_backends = UdevHandlerImpl::<S, Data>::scan_connectors(&mut (*evented).0, &self.logger);
|
||||
*backends = new_backends;
|
||||
|
||||
for renderer in backends.values() {
|
||||
// create cursor
|
||||
|
@ -391,9 +459,17 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>
|
|||
debug!(self.logger, "Surfaces dropped");
|
||||
|
||||
// don't use hardware acceleration anymore, if this was the primary gpu
|
||||
let device = Rc::try_unwrap(evt_source.remove().unwrap()).map_err(|_| "This should not happend").unwrap().into_inner().0;
|
||||
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||
*self.active_egl_context.borrow_mut() = None;
|
||||
let device = Rc::try_unwrap(evt_source.remove().unwrap())
|
||||
.map_err(|_| "This should not happend")
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.0;
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
{
|
||||
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||
*self.active_egl_context.borrow_mut() = None;
|
||||
}
|
||||
}
|
||||
|
||||
self.notifier.unregister(id);
|
||||
|
|
|
@ -9,7 +9,9 @@ use super::{Device, DeviceHandler, Surface};
|
|||
use backend::egl::context::GlAttributes;
|
||||
use backend::egl::error::Result as EGLResult;
|
||||
use backend::egl::native::{Backend, NativeDisplay, NativeSurface};
|
||||
use backend::egl::{EGLContext, EGLDisplay, EGLGraphicsBackend};
|
||||
use backend::egl::EGLContext;
|
||||
#[cfg(feature = "native_lib")]
|
||||
use backend::egl::{EGLDisplay, EGLGraphicsBackend};
|
||||
|
||||
pub mod error;
|
||||
use self::error::*;
|
||||
|
@ -178,6 +180,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "native_lib")]
|
||||
impl<B: Backend<Surface = <D as Device>::Surface> + 'static, D: Device + NativeDisplay<B> + 'static>
|
||||
EGLGraphicsBackend for EglDevice<B, D>
|
||||
where
|
||||
|
|
|
@ -29,6 +29,7 @@ use wayland_server::{
|
|||
protocol::wl_buffer::{self, WlBuffer},
|
||||
Display, Resource,
|
||||
};
|
||||
#[cfg(feature = "native_lib")]
|
||||
use wayland_sys::server::wl_display;
|
||||
|
||||
pub mod context;
|
||||
|
@ -303,6 +304,7 @@ 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.
|
||||
#[cfg(feature = "native_lib")]
|
||||
pub trait EGLGraphicsBackend {
|
||||
/// Binds this EGL context to the given Wayland display.
|
||||
///
|
||||
|
@ -323,6 +325,7 @@ pub trait EGLGraphicsBackend {
|
|||
/// Type to receive `EGLImages` for EGL-based `WlBuffer`s.
|
||||
///
|
||||
/// Can be created by using `EGLGraphicsBackend::bind_wl_display`.
|
||||
#[cfg(feature = "native_lib")]
|
||||
pub struct EGLDisplay {
|
||||
egl: Weak<ffi::egl::types::EGLDisplay>,
|
||||
wayland: *mut wl_display,
|
||||
|
@ -332,6 +335,7 @@ pub struct EGLDisplay {
|
|||
egl_to_texture_support: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "native_lib")]
|
||||
impl EGLDisplay {
|
||||
fn new<B: native::Backend, N: native::NativeDisplay<B>>(
|
||||
context: &EGLContext<B, N>,
|
||||
|
@ -469,6 +473,7 @@ impl EGLDisplay {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "native_lib")]
|
||||
impl Drop for EGLDisplay {
|
||||
fn drop(&mut self) {
|
||||
if let Some(display) = self.egl.upgrade() {
|
||||
|
@ -481,12 +486,14 @@ impl Drop for EGLDisplay {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "native_lib")]
|
||||
impl<E: EGLGraphicsBackend> EGLGraphicsBackend for Rc<E> {
|
||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||
(**self).bind_wl_display(display)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "native_lib")]
|
||||
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLGraphicsBackend for EGLContext<B, N> {
|
||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||
if !self.wl_drm_support {
|
||||
|
|
|
@ -14,6 +14,7 @@ extern crate tempfile;
|
|||
pub extern crate wayland_commons;
|
||||
pub extern crate wayland_protocols;
|
||||
pub extern crate wayland_server;
|
||||
#[cfg(feature = "native_lib")]
|
||||
extern crate wayland_sys;
|
||||
extern crate xkbcommon;
|
||||
|
||||
|
|
Loading…
Reference in New Issue