Skip to content

Commit

Permalink
anvil: allow for non-egl builds
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed Nov 28, 2018
1 parent 4f6475b commit 4a292f9
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 35 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ members = [ "anvil" ]

[dependencies]
wayland-server = "0.21.6"
wayland-sys = "0.21.3"
wayland-sys = { version = "0.21.6", optional = true }
nix = "0.11"
xkbcommon = "0.2.1"
tempfile = "2.1.5"
Expand All @@ -27,7 +27,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"
Expand All @@ -37,7 +37,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"]
Expand All @@ -49,4 +49,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 = []
5 changes: 3 additions & 2 deletions anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" ]
100 changes: 79 additions & 21 deletions anvil/src/glium_drawer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use slog::Logger;

use smithay::{
backend::{
egl::{BufferAccessError, EGLDisplay, EGLImages, Format},
egl::{BufferAccessError, EGLImages, Format},
graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend},
},
wayland::{
Expand All @@ -22,6 +22,8 @@ use smithay::{
},
wayland_server::{protocol::wl_buffer, Resource},
};
#[cfg(feature = "egl")]
use smithay::backend::egl::EGLDisplay;

use shaders;
use shell::{MyCompositorToken, MyWindowMap};
Expand All @@ -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,
}
Expand All @@ -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();

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -134,33 +181,43 @@ 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));
Err(())
}
}
}

#[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,
Expand Down Expand Up @@ -218,6 +275,7 @@ pub struct TextureMetadata {
pub fragment: usize,
pub y_inverted: bool,
pub dimensions: (u32, u32),
#[cfg(feature = "egl")]
images: Option<EGLImages>,
}

Expand Down
90 changes: 82 additions & 8 deletions anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use smithay::{
legacy::LegacyDrmDevice,
DevPath, Device, DeviceHandler, Surface,
},
egl::{EGLDisplay, EGLGraphicsBackend},
graphics::CursorBackend,
input::InputBackend,
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
Expand Down Expand Up @@ -56,6 +55,8 @@ use smithay::{
Display,
},
};
#[cfg(feature = "egl")]
use smithay::backend::egl::{EGLDisplay, EGLGraphicsBackend};

use glium_drawer::GliumDrawer;
use input_handler::AnvilInputHandler;
Expand All @@ -78,6 +79,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));
Expand Down Expand Up @@ -113,6 +115,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(),
Expand Down Expand Up @@ -217,6 +220,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<
Expand All @@ -238,6 +242,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>>>,
Expand Down Expand Up @@ -278,7 +283,55 @@ impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
);

backends.insert(crtc, renderer);
break;
break;
}
}
}
}

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;
}
}
}
Expand All @@ -301,15 +354,25 @@ 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,
Expand Down Expand Up @@ -351,12 +414,19 @@ 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
renderer
Expand All @@ -383,8 +453,12 @@ impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data>

// 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;

#[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);
Expand Down
5 changes: 4 additions & 1 deletion src/backend/drm/egl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 4a292f9

Please sign in to comment.