Use new rustfmt-preview

This commit is contained in:
Drakulix 2018-01-07 22:30:38 +01:00
parent 25c1e30fb3
commit 66c011c942
23 changed files with 757 additions and 534 deletions

View File

@ -73,7 +73,6 @@ script:
vagga cargo-$TRAVIS_RUST_VERSION doc --no-deps vagga cargo-$TRAVIS_RUST_VERSION doc --no-deps
;; ;;
"cargo-fmt") "cargo-fmt")
vagga cargo-$TRAVIS_RUST_VERSION install -f rustfmt-nightly &&
vagga cargo-$TRAVIS_RUST_VERSION fmt -- --write-mode=diff vagga cargo-$TRAVIS_RUST_VERSION fmt -- --write-mode=diff
;; ;;
"cargo-clippy") "cargo-clippy")

View File

@ -40,9 +40,7 @@ fn main() {
(3, 2), (3, 2),
Profile::Compatibility, Profile::Compatibility,
Fallbacks::None, Fallbacks::None,
[ ["GL_OES_EGL_image"],
"GL_OES_EGL_image",
],
).write_bindings(gl_generator::GlobalGenerator, &mut file) ).write_bindings(gl_generator::GlobalGenerator, &mut file)
.unwrap(); .unwrap();
} }

View File

@ -20,18 +20,18 @@ use drm::control::crtc;
use drm::control::encoder::Info as EncoderInfo; use drm::control::encoder::Info as EncoderInfo;
use drm::result::Error as DrmError; use drm::result::Error as DrmError;
use glium::{Blend, Surface}; use glium::{Blend, Surface};
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData, Buffer}; use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
use slog::{Drain, Logger}; use slog::{Drain, Logger};
use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler}; use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{Format, EGLDisplay, EGLWaylandExtensions}; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format};
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::wayland::compositor::roles::Role; use smithay::wayland::compositor::roles::Role;
use smithay::wayland::shm::init_shm_global; use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell; use std::cell::RefCell;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::os::unix::io::RawFd;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
@ -64,8 +64,10 @@ fn main() {
let mut options = OpenOptions::new(); let mut options = OpenOptions::new();
options.read(true); options.read(true);
options.write(true); options.write(true);
let mut device = let mut device = DrmDevice::new(
DrmDevice::new(Card(options.clone().open("/dev/dri/card0").unwrap()), log.clone()).unwrap(); Card(options.clone().open("/dev/dri/card0").unwrap()),
log.clone(),
).unwrap();
// Get a set of all modesetting resource handles (excluding planes): // Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap(); let res_handles = device.resource_handles().unwrap();
@ -74,9 +76,7 @@ fn main() {
let connector_info = res_handles let connector_info = res_handles
.connectors() .connectors()
.iter() .iter()
.map(|conn| { .map(|conn| ConnectorInfo::load_from_device(&device, *conn).unwrap())
ConnectorInfo::load_from_device(&device, *conn).unwrap()
})
.find(|conn| conn.connection_state() == ConnectorState::Connected) .find(|conn| conn.connection_state() == ConnectorState::Connected)
.unwrap(); .unwrap();
@ -96,9 +96,11 @@ fn main() {
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.) 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.)
// Initialize the hardware backend // Initialize the hardware backend
let renderer = GliumDrawer::from(device let renderer = GliumDrawer::from(
.create_backend(crtc, mode, vec![connector_info.handle()]) device
.unwrap()); .create_backend(crtc, mode, vec![connector_info.handle()])
.unwrap(),
);
{ {
/* /*
* Initialize glium * Initialize glium
@ -114,7 +116,7 @@ fn main() {
Some(egl_display) Some(egl_display)
} else { } else {
None None
} },
)); ));
/* /*
@ -123,7 +125,8 @@ fn main() {
init_shm_global(&mut event_loop, vec![], log.clone()); 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: * Add a listening socket:
@ -162,7 +165,9 @@ pub struct DrmHandlerImpl {
} }
impl DrmHandler<Card> for DrmHandlerImpl { impl DrmHandler<Card> for DrmHandlerImpl {
fn ready(&mut self, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle, _frame: u32, _duration: Duration) { fn ready(
&mut self, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle, _frame: u32, _duration: Duration
) {
let mut frame = self.drawer.draw(); let mut frame = self.drawer.draw();
frame.clear_color(0.8, 0.8, 0.9, 1.0); frame.clear_color(0.8, 0.8, 0.9, 1.0);
// redraw the frame, in a simple but inneficient way // redraw the frame, in a simple but inneficient way
@ -185,19 +190,21 @@ impl DrmHandler<Card> for DrmHandlerImpl {
Some(Buffer::Egl { ref images }) => { Some(Buffer::Egl { ref images }) => {
match images.format { match images.format {
Format::RGB | Format::RGBA => { Format::RGB | Format::RGBA => {
attributes.user_data.texture = self.drawer.texture_from_egl(&images); attributes.user_data.texture =
}, self.drawer.texture_from_egl(&images);
}
_ => { _ => {
// we don't handle the more complex formats here. // we don't handle the more complex formats here.
attributes.user_data.texture = None; attributes.user_data.texture = None;
remove = true; remove = true;
}, }
}; };
}, }
Some(Buffer::Shm { ref data, ref size }) => { Some(Buffer::Shm { ref data, ref size }) => {
attributes.user_data.texture = Some(self.drawer.texture_from_mem(data, *size)); attributes.user_data.texture =
}, Some(self.drawer.texture_from_mem(data, *size));
_ => {}, }
_ => {}
} }
if remove { if remove {
attributes.user_data.buffer = None; attributes.user_data.buffer = None;
@ -239,8 +246,7 @@ impl DrmHandler<Card> for DrmHandlerImpl {
frame.finish().unwrap(); frame.finish().unwrap();
} }
fn error(&mut self, _device: &mut DrmDevice<Card>, fn error(&mut self, _device: &mut DrmDevice<Card>, error: DrmError) {
error: DrmError) {
panic!("{:?}", error); panic!("{:?}", error);
} }
} }

View File

@ -1,10 +1,10 @@
use glium; use glium;
use glium::{Frame, Surface, GlObject}; use glium::{Frame, GlObject, Surface};
use glium::index::PrimitiveType; use glium::index::PrimitiveType;
use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d}; use glium::texture::{MipmapsOption, Texture2d, UncompressedFloatFormat};
use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::error::Result as EGLResult; use smithay::backend::graphics::egl::error::Result as EGLResult;
use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions}; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format};
use smithay::backend::graphics::glium::GliumGraphicsBackend; use smithay::backend::graphics::glium::GliumGraphicsBackend;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::ops::Deref; use std::ops::Deref;
@ -120,9 +120,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
Texture2d::new(&self.display, image).unwrap() Texture2d::new(&self.display, image).unwrap()
} }
pub fn texture_from_egl(&self, images: &EGLImages) pub fn texture_from_egl(&self, images: &EGLImages) -> Option<Texture2d> {
-> Option<Texture2d>
{
let format = match images.format { let format = match images.format {
Format::RGB => UncompressedFloatFormat::U8U8U8, Format::RGB => UncompressedFloatFormat::U8U8U8,
Format::RGBA => UncompressedFloatFormat::U8U8U8U8, Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
@ -136,15 +134,19 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
images.width, images.width,
images.height, images.height,
).unwrap(); ).unwrap();
unsafe { images.bind_to_texture(0, opengl_texture.get_id()).expect("Failed to bind to texture"); } unsafe {
images
.bind_to_texture(0, opengl_texture.get_id())
.expect("Failed to bind to texture");
}
Some(opengl_texture) Some(opengl_texture)
} }
pub fn render_texture(&self, target: &mut glium::Frame, texture: &Texture2d, pub fn render_texture(
y_inverted: bool, surface_dimensions: (u32, u32), &self, target: &mut glium::Frame, texture: &Texture2d, y_inverted: bool,
surface_location: (i32, i32), screen_size: (u32, u32), surface_dimensions: (u32, u32), surface_location: (i32, i32), screen_size: (u32, u32),
blending: glium::Blend) blending: glium::Blend,
{ ) {
let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32); let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32); let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32);
@ -175,10 +177,10 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
&glium::DrawParameters { &glium::DrawParameters {
blend: blending, blend: blending,
..Default::default() ..Default::default()
} },
) )
.unwrap(); .unwrap();
} }
#[inline] #[inline]
pub fn draw(&self) -> Frame { pub fn draw(&self) -> Frame {

View File

@ -1,7 +1,7 @@
use super::WindowMap; use super::WindowMap;
use smithay::backend::graphics::egl::wayland::{Format, BufferAccessError};
use glium::texture::Texture2d; use glium::texture::Texture2d;
use rand; use rand;
use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format};
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages}; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes, use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
SurfaceUserImplementation}; SurfaceUserImplementation};
@ -25,7 +25,8 @@ pub enum Buffer {
Shm { data: Vec<u8>, size: (u32, u32) }, Shm { data: Vec<u8>, size: (u32, u32) },
} }
pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>> { pub fn surface_implementation(
) -> SurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>> {
SurfaceUserImplementation { SurfaceUserImplementation {
commit: |_, display, surface, token| { commit: |_, display, surface, token| {
// we retrieve the contents of the associated buffer and copy it // we retrieve the contents of the associated buffer and copy it
@ -34,25 +35,24 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
Some(Some((buffer, (_x, _y)))) => { Some(Some((buffer, (_x, _y)))) => {
// we ignore hotspot coordinates in this simple example // we ignore hotspot coordinates in this simple example
match if let Some(display) = display.borrow().as_ref() { match if let Some(display) = display.borrow().as_ref() {
display.egl_buffer_contents(buffer) display.egl_buffer_contents(buffer)
} else { } else {
Err(BufferAccessError::NotManaged(buffer)) Err(BufferAccessError::NotManaged(buffer))
} } {
{
Ok(images) => { Ok(images) => {
match images.format { match images.format {
Format::RGB => {}, Format::RGB => {}
Format::RGBA => {}, Format::RGBA => {}
_ => { _ => {
// we don't handle the more complex formats here. // we don't handle the more complex formats here.
attributes.user_data.buffer = None; attributes.user_data.buffer = None;
attributes.user_data.texture = None; attributes.user_data.texture = None;
return; return;
}, }
}; };
attributes.user_data.texture = None; attributes.user_data.texture = None;
attributes.user_data.buffer = Some(Buffer::Egl { images }); attributes.user_data.buffer = Some(Buffer::Egl { images });
}, }
Err(BufferAccessError::NotManaged(buffer)) => { Err(BufferAccessError::NotManaged(buffer)) => {
shm_buffer_contents(&buffer, |slice, data| { shm_buffer_contents(&buffer, |slice, data| {
let offset = data.offset as usize; let offset = data.offset as usize;
@ -68,7 +68,7 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) }); attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) });
}).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!"); }).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!");
buffer.release(); buffer.release();
}, }
Err(err) => panic!("EGL error: {}", err), Err(err) => panic!("EGL error: {}", err),
} }
} }
@ -92,7 +92,8 @@ pub struct ShellIData<F> {
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, (), F>>>, pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, (), F>>>,
} }
pub fn shell_implementation<F>() -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ShellIData<F>, ()> pub fn shell_implementation<F>(
) -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ShellIData<F>, ()>
where where
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>, F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
{ {
@ -113,22 +114,18 @@ where
serial: 42, serial: 42,
} }
}, },
new_popup: |_, _, _| { new_popup: |_, _, _| PopupConfigure {
PopupConfigure { size: (10, 10),
size: (10, 10), position: (10, 10),
position: (10, 10), serial: 42,
serial: 42,
}
}, },
move_: |_, _, _, _, _| {}, move_: |_, _, _, _, _| {},
resize: |_, _, _, _, _, _| {}, resize: |_, _, _, _, _, _| {},
grab: |_, _, _, _, _| {}, grab: |_, _, _, _, _| {},
change_display_state: |_, _, _, _, _, _, _| { change_display_state: |_, _, _, _, _, _, _| ToplevelConfigure {
ToplevelConfigure { size: None,
size: None, states: vec![],
states: vec![], serial: 42,
serial: 42,
}
}, },
show_window_menu: |_, _, _, _, _, _, _| {}, show_window_menu: |_, _, _, _, _, _, _| {},
} }
@ -155,12 +152,12 @@ pub type MyWindowMap = WindowMap<
>; >;
pub fn init_shell( pub fn init_shell(
evl: &mut EventLoop, log: ::slog::Logger, data: Rc<RefCell<Option<EGLDisplay>>>) evl: &mut EventLoop, log: ::slog::Logger, data: Rc<RefCell<Option<EGLDisplay>>>
-> ( ) -> (
CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>, CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>, StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
Rc<RefCell<MyWindowMap>>, Rc<RefCell<MyWindowMap>>,
) { ) {
let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone()); let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone());
let window_map = Rc::new(RefCell::new(WindowMap::<_, _, _, (), _>::new( let window_map = Rc::new(RefCell::new(WindowMap::<_, _, _, (), _>::new(

View File

@ -19,8 +19,9 @@ where
SD: 'static, SD: 'static,
{ {
// Find the topmost surface under this point if any and the location of this point in the surface // Find the topmost surface under this point if any and the location of this point in the surface
fn matching<F>(&self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F) fn matching<F>(
-> Option<(wl_surface::WlSurface, (f64, f64))> &self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F
) -> Option<(wl_surface::WlSurface, (f64, f64))>
where where
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>, F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
{ {
@ -33,27 +34,29 @@ where
let _ = ctoken.with_surface_tree_downward( let _ = ctoken.with_surface_tree_downward(
wl_surface, wl_surface,
self.location, self.location,
|wl_surface, attributes, role, &(mut x, mut y)| if let Some((w, h)) = get_size(attributes) { |wl_surface, attributes, role, &(mut x, mut y)| {
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) { if let Some((w, h)) = get_size(attributes) {
x += subdata.x; if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
y += subdata.y; x += subdata.x;
} y += subdata.y;
let my_rect = Rectangle { }
x, let my_rect = Rectangle {
y, x,
width: w, y,
height: h, width: w,
}; height: h,
if my_rect.contains((point.0 as i32, point.1 as i32)) { };
found = wl_surface.clone().map(|s| { if my_rect.contains((point.0 as i32, point.1 as i32)) {
(s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64)) found = wl_surface
}); .clone()
TraversalAction::Break .map(|s| (s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64)));
TraversalAction::Break
} else {
TraversalAction::DoChildren((x, y))
}
} else { } else {
TraversalAction::DoChildren((x, y)) TraversalAction::SkipChildren
} }
} else {
TraversalAction::SkipChildren
}, },
); );
} }
@ -151,8 +154,9 @@ where
None None
} }
pub fn get_surface_and_bring_to_top(&mut self, point: (f64, f64)) pub fn get_surface_and_bring_to_top(
-> Option<(wl_surface::WlSurface, (f64, f64))> { &mut self, point: (f64, f64)
) -> Option<(wl_surface::WlSurface, (f64, f64))> {
let mut found = None; let mut found = None;
for (i, w) in self.windows.iter().enumerate() { for (i, w) in self.windows.iter().enumerate() {
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) { if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {

View File

@ -1,14 +1,14 @@
extern crate drm; extern crate drm;
#[macro_use] #[macro_use]
extern crate glium; extern crate glium;
extern crate rand;
extern crate input as libinput;
extern crate image; extern crate image;
extern crate udev; extern crate input as libinput;
extern crate rand;
#[macro_use(define_roles)] #[macro_use(define_roles)]
extern crate smithay; extern crate smithay;
extern crate xkbcommon; extern crate udev;
extern crate wayland_server; extern crate wayland_server;
extern crate xkbcommon;
#[macro_use] #[macro_use]
extern crate slog; extern crate slog;
@ -21,25 +21,26 @@ mod helpers;
use drm::control::{Device as ControlDevice, ResourceInfo}; use drm::control::{Device as ControlDevice, ResourceInfo};
use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState}; use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState};
use drm::control::encoder::Info as EncoderInfo;
use drm::control::crtc; use drm::control::crtc;
use drm::control::encoder::Info as EncoderInfo;
use drm::result::Error as DrmError; use drm::result::Error as DrmError;
use glium::{Blend, Surface}; use glium::{Blend, Surface};
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
use image::{ImageBuffer, Rgba}; use image::{ImageBuffer, Rgba};
use libinput::{Libinput, Device as LibinputDevice, event}; use libinput::{event, Device as LibinputDevice, Libinput};
use libinput::event::keyboard::KeyboardEventTrait; use libinput::event::keyboard::KeyboardEventTrait;
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData, Buffer};
use slog::{Drain, Logger}; use slog::{Drain, Logger};
use smithay::backend::drm::{DrmBackend, DrmDevice, DrmHandler, DevPath}; use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler};
use smithay::backend::graphics::GraphicsBackend; use smithay::backend::graphics::GraphicsBackend;
use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay, Format}; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format};
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerButtonEvent, use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
PointerAxisEvent, KeyState}; PointerAxisEvent, PointerButtonEvent};
use smithay::backend::libinput::{LibinputInputBackend, libinput_bind, PointerAxisEvent as LibinputPointerAxisEvent, LibinputSessionInterface}; use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface,
use smithay::backend::udev::{UdevBackend, UdevHandler, udev_backend_bind, primary_gpu, SessionFdDrmDevice}; PointerAxisEvent as LibinputPointerAxisEvent};
use smithay::backend::session::{Session, SessionNotifier}; use smithay::backend::session::{Session, SessionNotifier};
use smithay::backend::session::direct::{direct_session_bind, DirectSession}; use smithay::backend::session::direct::{direct_session_bind, DirectSession};
use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, UdevBackend, UdevHandler};
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
use smithay::wayland::compositor::roles::Role; use smithay::wayland::compositor::roles::Role;
use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::wayland::output::{Mode, Output, PhysicalProperties};
@ -48,15 +49,15 @@ use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Error as IoError; use std::io::Error as IoError;
use std::path::PathBuf;
use std::process::Command;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration; use std::time::Duration;
use std::path::PathBuf; use wayland_server::{Display, StateProxy, StateToken};
use std::process::Command;
use xkbcommon::xkb::keysyms as xkb;
use wayland_server::{Display, StateToken, StateProxy};
use wayland_server::protocol::{wl_output, wl_pointer}; use wayland_server::protocol::{wl_output, wl_pointer};
use xkbcommon::xkb::keysyms as xkb;
struct LibinputInputHandler { struct LibinputInputHandler {
log: Logger, log: Logger,
@ -92,17 +93,18 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state)); debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
let serial = self.next_serial(); let serial = self.next_serial();
self.keyboard.input(keycode, state, serial, |modifiers, keysym| { self.keyboard
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace { .input(keycode, state, serial, |modifiers, keysym| {
self.running.store(false, Ordering::SeqCst); if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
false self.running.store(false, Ordering::SeqCst);
} else if modifiers.logo && keysym == xkb::KEY_Return && state == KeyState::Pressed { false
let _ = Command::new("weston-terminal").spawn(); } else if modifiers.logo && keysym == xkb::KEY_Return && state == KeyState::Pressed {
false let _ = Command::new("weston-terminal").spawn();
} else { false
true } else {
} true
}); }
});
} }
fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) { fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) {
let (x, y) = (evt.dx(), evt.dy()); let (x, y) = (evt.dx(), evt.dy());
@ -110,7 +112,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
let mut location = self.pointer_location.borrow_mut(); let mut location = self.pointer_location.borrow_mut();
location.0 += x; location.0 += x;
location.1 += y; location.1 += y;
let under = self.window_map.borrow().get_surface_under((location.0, location.1)); let under = self.window_map
.borrow()
.get_surface_under((location.0, location.1));
self.pointer.motion( self.pointer.motion(
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)), under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
serial, serial,
@ -118,7 +122,10 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
); );
} }
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) { fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) {
let (x, y) = (evt.absolute_x_transformed(self.screen_size.0), evt.absolute_y_transformed(self.screen_size.1)); let (x, y) = (
evt.absolute_x_transformed(self.screen_size.0),
evt.absolute_y_transformed(self.screen_size.1),
);
*self.pointer_location.borrow_mut() = (x, y); *self.pointer_location.borrow_mut() = (x, y);
let serial = self.next_serial(); let serial = self.next_serial();
let under = self.window_map.borrow().get_surface_under((x, y)); let under = self.window_map.borrow().get_surface_under((x, y));
@ -177,7 +184,9 @@ fn main() {
// A logger facility, here we use the terminal for this example // A logger facility, here we use the terminal for this example
let log = Logger::root( let log = Logger::root(
slog_term::FullFormat::new(slog_term::PlainSyncDecorator::new(std::io::stdout())).build().fuse(), slog_term::FullFormat::new(slog_term::PlainSyncDecorator::new(std::io::stdout()))
.build()
.fuse(),
o!(), o!(),
); );
@ -196,7 +205,8 @@ fn main() {
*/ */
init_shm_global(&mut event_loop, vec![], log.clone()); 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 * Initialize session on the current tty
@ -221,8 +231,11 @@ fn main() {
let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default(); let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
let bytes = include_bytes!("resources/cursor2.rgba"); let bytes = include_bytes!("resources/cursor2.rgba");
let udev_token let udev_token = UdevBackend::new(
= UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl { &mut event_loop,
&context,
session.clone(),
UdevHandlerImpl {
compositor_token, compositor_token,
active_egl_context, active_egl_context,
backends: HashMap::new(), backends: HashMap::new(),
@ -232,7 +245,9 @@ fn main() {
pointer_location: pointer_location.clone(), pointer_location: pointer_location.clone(),
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(), pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
logger: log.clone(), logger: log.clone(),
}, log.clone()).unwrap(); },
log.clone(),
).unwrap();
let udev_session_id = notifier.register(udev_token.clone()); let udev_session_id = notifier.register(udev_token.clone());
@ -283,7 +298,9 @@ fn main() {
/* /*
* Initialize libinput backend * Initialize libinput backend
*/ */
let mut libinput_context = Libinput::new_from_udev::<LibinputSessionInterface<Rc<RefCell<DirectSession>>>>(session.into(), &context); let mut libinput_context = Libinput::new_from_udev::<
LibinputSessionInterface<Rc<RefCell<DirectSession>>>,
>(session.into(), &context);
let libinput_session_id = notifier.register(libinput_context.clone()); let libinput_session_id = notifier.register(libinput_context.clone());
libinput_context.udev_assign_seat(&seat).unwrap(); libinput_context.udev_assign_seat(&seat).unwrap();
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone()); let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
@ -337,7 +354,9 @@ struct UdevHandlerImpl {
} }
impl UdevHandlerImpl { impl UdevHandlerImpl {
pub fn scan_connectors(&self, device: &mut DrmDevice<SessionFdDrmDevice>) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> { pub fn scan_connectors(
&self, device: &mut DrmDevice<SessionFdDrmDevice>
) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> {
// Get a set of all modesetting resource handles (excluding planes): // Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap(); let res_handles = device.resource_handles().unwrap();
@ -345,9 +364,7 @@ impl UdevHandlerImpl {
let connector_infos: Vec<ConnectorInfo> = res_handles let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors() .connectors()
.iter() .iter()
.map(|conn| { .map(|conn| ConnectorInfo::load_from_device(device, *conn).unwrap())
ConnectorInfo::load_from_device(device, *conn).unwrap()
})
.filter(|conn| conn.connection_state() == ConnectorState::Connected) .filter(|conn| conn.connection_state() == ConnectorState::Connected)
.inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type())) .inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type()))
.collect(); .collect();
@ -356,16 +373,26 @@ impl UdevHandlerImpl {
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete // very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
for connector_info in connector_infos { for connector_info in connector_infos {
let encoder_infos = connector_info.encoders().iter().flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle)).collect::<Vec<EncoderInfo>>(); let encoder_infos = connector_info
.encoders()
.iter()
.flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle))
.collect::<Vec<EncoderInfo>>();
for encoder_info in encoder_infos { for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) { for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
if !backends.contains_key(&crtc) { 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.) 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 // create a backend
let renderer = GliumDrawer::from(device.create_backend(crtc, mode, vec![connector_info.handle()]).unwrap()); let renderer = GliumDrawer::from(
device
.create_backend(crtc, mode, vec![connector_info.handle()])
.unwrap(),
);
// create cursor // create cursor
renderer.set_cursor_representation(&self.pointer_image, (2, 2)).unwrap(); renderer
.set_cursor_representation(&self.pointer_image, (2, 2))
.unwrap();
// render first frame // render first frame
{ {
@ -386,8 +413,9 @@ impl UdevHandlerImpl {
} }
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl { impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
fn device_added<'a, S: Into<StateProxy<'a>>>(&mut self, _state: S, device: &mut DrmDevice<SessionFdDrmDevice>) -> Option<DrmHandlerImpl> fn device_added<'a, S: Into<StateProxy<'a>>>(
{ &mut self, _state: S, device: &mut DrmDevice<SessionFdDrmDevice>
) -> Option<DrmHandlerImpl> {
// init hardware acceleration on the primary gpu. // init hardware acceleration on the primary gpu.
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu { if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display).ok(); *self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display).ok();
@ -405,14 +433,18 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
}) })
} }
fn device_changed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>) { fn device_changed<'a, S: Into<StateProxy<'a>>>(
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
) {
//quick and dirt, just re-init all backends //quick and dirt, just re-init all backends
let mut state = state.into(); let mut state = state.into();
let backends = self.backends.get(&state.get(device).device_id()).unwrap(); let backends = self.backends.get(&state.get(device).device_id()).unwrap();
*backends.borrow_mut() = self.scan_connectors(state.get_mut(device)); *backends.borrow_mut() = self.scan_connectors(state.get_mut(device));
} }
fn device_removed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>) { fn device_removed<'a, S: Into<StateProxy<'a>>>(
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
) {
let state = state.into(); let state = state.into();
let device = state.get(device); let device = state.get(device);
@ -439,7 +471,10 @@ pub struct DrmHandlerImpl {
} }
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl { impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
fn ready(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, crtc: crtc::Handle, _frame: u32, _duration: Duration) { fn ready(
&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, crtc: crtc::Handle, _frame: u32,
_duration: Duration,
) {
if let Some(drawer) = self.backends.borrow().get(&crtc) { if let Some(drawer) = self.backends.borrow().get(&crtc) {
{ {
let (x, y) = *self.pointer_location.borrow(); let (x, y) = *self.pointer_location.borrow();
@ -450,73 +485,77 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
// redraw the frame, in a simple but inneficient way // redraw the frame, in a simple but inneficient way
{ {
let screen_dimensions = drawer.get_framebuffer_dimensions(); let screen_dimensions = drawer.get_framebuffer_dimensions();
self.window_map self.window_map.borrow().with_windows_from_bottom_to_top(
.borrow() |toplevel_surface, initial_place| {
.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { if let Some(wl_surface) = toplevel_surface.get_surface() {
if let Some(wl_surface) = toplevel_surface.get_surface() { // this surface is a root of a subsurface tree that needs to be drawn
// this surface is a root of a subsurface tree that needs to be drawn self.compositor_token
self.compositor_token .with_surface_tree_upward(
.with_surface_tree_upward( wl_surface,
wl_surface, initial_place,
initial_place, |_surface, attributes, role, &(mut x, mut y)| {
|_surface, attributes, role, &(mut x, mut y)| { // there is actually something to draw !
// there is actually something to draw ! if attributes.user_data.texture.is_none() {
if attributes.user_data.texture.is_none() { let mut remove = false;
let mut remove = false; match attributes.user_data.buffer {
match attributes.user_data.buffer { Some(Buffer::Egl { ref images }) => {
Some(Buffer::Egl { ref images }) => { match images.format {
match images.format { Format::RGB | Format::RGBA => {
Format::RGB | Format::RGBA => { attributes.user_data.texture =
attributes.user_data.texture = drawer.texture_from_egl(&images); drawer.texture_from_egl(&images);
}, }
_ => { _ => {
// we don't handle the more complex formats here. // we don't handle the more complex formats here.
attributes.user_data.texture = None; attributes.user_data.texture = None;
remove = true; remove = true;
}, }
}; };
}, }
Some(Buffer::Shm { ref data, ref size }) => { Some(Buffer::Shm { ref data, ref size }) => {
attributes.user_data.texture = Some(drawer.texture_from_mem(data, *size)); attributes.user_data.texture =
}, Some(drawer.texture_from_mem(data, *size));
_ => {}, }
_ => {}
}
if remove {
attributes.user_data.buffer = None;
}
} }
if remove {
attributes.user_data.buffer = None;
}
}
if let Some(ref texture) = attributes.user_data.texture { if let Some(ref texture) = attributes.user_data.texture {
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) { if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.x; x += subdata.x;
y += subdata.y; y += subdata.y;
}
info!(self.logger, "Render window");
drawer.render_texture(
&mut frame,
texture,
match *attributes.user_data.buffer.as_ref().unwrap() {
Buffer::Egl { ref images } => images.y_inverted,
Buffer::Shm { .. } => false,
},
match *attributes.user_data.buffer.as_ref().unwrap() {
Buffer::Egl { ref images } => {
(images.width, images.height)
}
Buffer::Shm { ref size, .. } => *size,
},
(x, y),
screen_dimensions,
Blend::alpha_blending(),
);
TraversalAction::DoChildren((x, y))
} else {
// we are not display, so our children are neither
TraversalAction::SkipChildren
} }
info!(self.logger, "Render window"); },
drawer.render_texture( )
&mut frame, .unwrap();
texture, }
match *attributes.user_data.buffer.as_ref().unwrap() { },
Buffer::Egl { ref images } => images.y_inverted, );
Buffer::Shm { .. } => false,
},
match *attributes.user_data.buffer.as_ref().unwrap() {
Buffer::Egl { ref images } => (images.width, images.height),
Buffer::Shm { ref size, .. } => *size,
},
(x, y),
screen_dimensions,
Blend::alpha_blending(),
);
TraversalAction::DoChildren((x, y))
} else {
// we are not display, so our children are neither
TraversalAction::SkipChildren
}
},
)
.unwrap();
}
});
} }
if let Err(err) = frame.finish() { if let Err(err) = frame.finish() {
error!(self.logger, "Error during rendering: {:?}", err); error!(self.logger, "Error during rendering: {:?}", err);
@ -524,8 +563,7 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
} }
} }
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) {
error: DrmError) {
error!(self.logger, "{:?}", error); error!(self.logger, "{:?}", error);
} }
} }

View File

@ -12,7 +12,7 @@ extern crate wayland_server;
mod helpers; mod helpers;
use glium::Surface; use glium::Surface;
use helpers::{init_shell, GliumDrawer, MyWindowMap, Buffer}; use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap};
use slog::{Drain, Logger}; use slog::{Drain, Logger};
use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
@ -143,7 +143,7 @@ fn main() {
Some(egl_display) Some(egl_display)
} else { } else {
None None
} },
)); ));
let (w, h) = renderer.get_framebuffer_dimensions(); let (w, h) = renderer.get_framebuffer_dimensions();
@ -155,7 +155,8 @@ fn main() {
init_shm_global(&mut event_loop, vec![], log.clone()); 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); let (compositor_token, _shell_state_token, window_map) =
init_shell(&mut event_loop, log.clone(), egl_display);
let (seat_token, _) = Seat::new(&mut event_loop, "winit".into(), log.clone()); let (seat_token, _) = Seat::new(&mut event_loop, "winit".into(), log.clone());
@ -240,19 +241,21 @@ fn main() {
Some(Buffer::Egl { ref images }) => { Some(Buffer::Egl { ref images }) => {
match images.format { match images.format {
Format::RGB | Format::RGBA => { Format::RGB | Format::RGBA => {
attributes.user_data.texture = drawer.texture_from_egl(&images); attributes.user_data.texture =
}, drawer.texture_from_egl(&images);
}
_ => { _ => {
// we don't handle the more complex formats here. // we don't handle the more complex formats here.
attributes.user_data.texture = None; attributes.user_data.texture = None;
remove = true; remove = true;
}, }
}; };
}, }
Some(Buffer::Shm { ref data, ref size }) => { Some(Buffer::Shm { ref data, ref size }) => {
attributes.user_data.texture = Some(drawer.texture_from_mem(data, *size)); attributes.user_data.texture =
}, Some(drawer.texture_from_mem(data, *size));
_ => {}, }
_ => {}
} }
if remove { if remove {
attributes.user_data.buffer = None; attributes.user_data.buffer = None;
@ -280,14 +283,16 @@ fn main() {
glium::Blend { glium::Blend {
color: glium::BlendingFunction::Addition { color: glium::BlendingFunction::Addition {
source: glium::LinearBlendingFactor::One, source: glium::LinearBlendingFactor::One,
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha, destination:
glium::LinearBlendingFactor::OneMinusSourceAlpha,
}, },
alpha: glium::BlendingFunction::Addition { alpha: glium::BlendingFunction::Addition {
source: glium::LinearBlendingFactor::One, source: glium::LinearBlendingFactor::One,
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha, destination:
glium::LinearBlendingFactor::OneMinusSourceAlpha,
}, },
..Default::default() ..Default::default()
} },
); );
TraversalAction::DoChildren((x, y)) TraversalAction::DoChildren((x, y))
} else { } else {

View File

@ -1,13 +1,14 @@
use super::error::*;
use super::DevPath; use super::DevPath;
use super::error::*;
use backend::graphics::GraphicsBackend; use backend::graphics::GraphicsBackend;
use backend::graphics::egl::{EGLGraphicsBackend, EGLContext, EGLSurface, PixelFormat, SwapBuffersError}; use backend::graphics::egl::{EGLContext, EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError};
use backend::graphics::egl::error::Result as EGLResult; use backend::graphics::egl::error::Result as EGLResult;
use backend::graphics::egl::native::{Gbm, GbmSurfaceArguments}; use backend::graphics::egl::native::{Gbm, GbmSurfaceArguments};
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay}; use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
use drm::control::{Device, ResourceInfo}; use drm::control::{Device, ResourceInfo};
use drm::control::{connector, crtc, encoder, framebuffer, Mode}; use drm::control::{connector, crtc, encoder, framebuffer, Mode};
use gbm::{Device as GbmDevice, BufferObject, BufferObjectFlags, Format as GbmFormat, Surface as GbmSurface, SurfaceBufferHandle}; use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice, Format as GbmFormat, Surface as GbmSurface,
SurfaceBufferHandle};
use image::{ImageBuffer, Rgba}; use image::{ImageBuffer, Rgba};
use nix::libc::c_void; use nix::libc::c_void;
use std::cell::Cell; use std::cell::Cell;
@ -34,11 +35,8 @@ pub(crate) struct DrmBackendInternal<A: Device + 'static> {
impl<A: Device + 'static> DrmBackend<A> { impl<A: Device + 'static> DrmBackend<A> {
pub(crate) fn new( pub(crate) fn new(
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>, context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>, crtc: crtc::Handle, mode: Mode,
crtc: crtc::Handle, connectors: Vec<connector::Handle>, log: ::slog::Logger,
mode: Mode,
connectors: Vec<connector::Handle>,
log: ::slog::Logger,
) -> Result<Self> { ) -> Result<Self> {
// logger already initialized by the DrmDevice // logger already initialized by the DrmDevice
info!(log, "Initializing DrmBackend"); info!(log, "Initializing DrmBackend");
@ -46,36 +44,40 @@ impl<A: Device + 'static> DrmBackend<A> {
let (w, h) = mode.size(); let (w, h) = mode.size();
debug!(log, "Creating Surface"); debug!(log, "Creating Surface");
let surface = context.create_surface( let surface = context
GbmSurfaceArguments { .create_surface(GbmSurfaceArguments {
size: (w as u32, h as u32), size: (w as u32, h as u32),
format: GbmFormat::XRGB8888, format: GbmFormat::XRGB8888,
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING, flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
} })
).chain_err(|| ErrorKind::GbmInitFailed)?; .chain_err(|| ErrorKind::GbmInitFailed)?;
// make it active for the first `crtc::set` // make it active for the first `crtc::set`
// (which is needed before the first page_flip) // (which is needed before the first page_flip)
unsafe { unsafe {
surface surface
.make_current() .make_current()
.chain_err(|| ErrorKind::FailedToSwap)? .chain_err(|| ErrorKind::FailedToSwap)?
}; };
surface surface
.swap_buffers() .swap_buffers()
.chain_err(|| ErrorKind::FailedToSwap)?; .chain_err(|| ErrorKind::FailedToSwap)?;
// init the first screen // init the first screen
// (must be done before calling page_flip for the first time) // (must be done before calling page_flip for the first time)
let mut front_bo = surface let mut front_bo = surface
.lock_front_buffer() .lock_front_buffer()
.chain_err(|| ErrorKind::FailedToSwap)?; .chain_err(|| ErrorKind::FailedToSwap)?;
debug!(log, "FrontBuffer color format: {:?}", front_bo.format()); debug!(log, "FrontBuffer color format: {:?}", front_bo.format());
// we need a framebuffer for the front buffer // we need a framebuffer for the front buffer
let fb = framebuffer::create(&*context, &*front_bo) let fb = framebuffer::create(&*context, &*front_bo).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error creating framebuffer on {:?}", context.dev_path())))?; ErrorKind::DrmDev(format!(
"Error creating framebuffer on {:?}",
context.dev_path()
))
})?;
debug!(log, "Initialize screen"); debug!(log, "Initialize screen");
crtc::set( crtc::set(
@ -85,14 +87,23 @@ impl<A: Device + 'static> DrmBackend<A> {
&connectors, &connectors,
(0, 0), (0, 0),
Some(mode), Some(mode),
).chain_err(|| ErrorKind::DrmDev(format!("Error setting crtc {:?} on {:?}", crtc, context.dev_path())))?; ).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error setting crtc {:?} on {:?}",
crtc,
context.dev_path()
))
})?;
front_bo.set_userdata(fb).unwrap(); front_bo.set_userdata(fb).unwrap();
let cursor = Cell::new(context.create_buffer_object( let cursor = Cell::new(context
1, 1, .create_buffer_object(
GbmFormat::ARGB8888, 1,
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE, 1,
).chain_err(|| ErrorKind::GbmInitFailed)?); GbmFormat::ARGB8888,
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
)
.chain_err(|| ErrorKind::GbmInitFailed)?);
Ok(DrmBackend { Ok(DrmBackend {
backend: Rc::new(DrmBackendInternal { backend: Rc::new(DrmBackendInternal {
@ -110,8 +121,7 @@ impl<A: Device + 'static> DrmBackend<A> {
}) })
} }
pub(crate) fn weak(&self) -> Weak<DrmBackendInternal<A>> pub(crate) fn weak(&self) -> Weak<DrmBackendInternal<A>> {
{
Rc::downgrade(&self.backend) Rc::downgrade(&self.backend)
} }
@ -121,8 +131,12 @@ impl<A: Device + 'static> DrmBackend<A> {
/// ///
/// Errors if the new connector does not support the currently set `Mode` /// Errors if the new connector does not support the currently set `Mode`
pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> { pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> {
let info = connector::Info::load_from_device(&*self.backend.context, connector) let info = connector::Info::load_from_device(&*self.backend.context, connector).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.backend.context.dev_path())))?; ErrorKind::DrmDev(format!(
"Error loading connector info on {:?}",
self.backend.context.dev_path()
))
})?;
// check if the connector can handle the current mode // check if the connector can handle the current mode
if info.modes().contains(&self.mode) { if info.modes().contains(&self.mode) {
@ -130,15 +144,22 @@ impl<A: Device + 'static> DrmBackend<A> {
let encoders = info.encoders() let encoders = info.encoders()
.iter() .iter()
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(&*self.backend.context, *encoder) encoder::Info::load_from_device(&*self.backend.context, *encoder).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.backend.context.dev_path()))) ErrorKind::DrmDev(format!(
"Error loading encoder info on {:?}",
self.backend.context.dev_path()
))
})
}) })
.collect::<Result<Vec<encoder::Info>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc // and if any encoder supports the selected crtc
let resource_handles = self.backend.context let resource_handles = self.backend.context.resource_handles().chain_err(|| {
.resource_handles() ErrorKind::DrmDev(format!(
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.backend.context.dev_path())))?; "Error loading resources on {:?}",
self.backend.context.dev_path()
))
})?;
if !encoders if !encoders
.iter() .iter()
.map(|encoder| encoder.possible_crtcs()) .map(|encoder| encoder.possible_crtcs())
@ -193,7 +214,12 @@ impl<A: Device + 'static> DrmBackend<A> {
// check the connectors // check the connectors
for connector in &self.connectors { for connector in &self.connectors {
if !connector::Info::load_from_device(&*self.backend.context, *connector) if !connector::Info::load_from_device(&*self.backend.context, *connector)
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.backend.context.dev_path())))? .chain_err(|| {
ErrorKind::DrmDev(format!(
"Error loading connector info on {:?}",
self.backend.context.dev_path()
))
})?
.modes() .modes()
.contains(&mode) .contains(&mode)
{ {
@ -206,32 +232,39 @@ impl<A: Device + 'static> DrmBackend<A> {
// Recreate the surface and the related resources to match the new // Recreate the surface and the related resources to match the new
// resolution. // resolution.
debug!(self.backend.logger, "Reinitializing surface for new mode: {}:{}", w, h); debug!(
let surface = self.backend.context.create_surface( self.backend.logger,
GbmSurfaceArguments { "Reinitializing surface for new mode: {}:{}", w, h
);
let surface = self.backend
.context
.create_surface(GbmSurfaceArguments {
size: (w as u32, h as u32), size: (w as u32, h as u32),
format: GbmFormat::XRGB8888, format: GbmFormat::XRGB8888,
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING, flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
} })
).chain_err(|| ErrorKind::GbmInitFailed)?; .chain_err(|| ErrorKind::GbmInitFailed)?;
// make it active for the first `crtc::set` // make it active for the first `crtc::set`
// (which is needed before the first page_flip) // (which is needed before the first page_flip)
unsafe { unsafe {
surface surface
.make_current() .make_current()
.chain_err(|| ErrorKind::FailedToSwap)? .chain_err(|| ErrorKind::FailedToSwap)?
}; };
surface surface
.swap_buffers() .swap_buffers()
.chain_err(|| ErrorKind::FailedToSwap)?; .chain_err(|| ErrorKind::FailedToSwap)?;
// Clean up next_buffer // Clean up next_buffer
{ {
if let Some(mut old_bo) = self.backend.next_buffer.take() { if let Some(mut old_bo) = self.backend.next_buffer.take() {
if let Ok(Some(fb)) = old_bo.take_userdata() { if let Ok(Some(fb)) = old_bo.take_userdata() {
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) { if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
warn!(self.backend.logger, "Error releasing old back_buffer framebuffer: {:?}", err); warn!(
self.backend.logger,
"Error releasing old back_buffer framebuffer: {:?}", err
);
} }
} }
} }
@ -244,7 +277,11 @@ impl<A: Device + 'static> DrmBackend<A> {
.lock_front_buffer() .lock_front_buffer()
.chain_err(|| ErrorKind::FailedToSwap)?; .chain_err(|| ErrorKind::FailedToSwap)?;
debug!(self.backend.logger, "FrontBuffer color format: {:?}", front_bo.format()); debug!(
self.backend.logger,
"FrontBuffer color format: {:?}",
front_bo.format()
);
// we also need a new framebuffer for the front buffer // we also need a new framebuffer for the front buffer
let dev_path = self.backend.context.dev_path(); let dev_path = self.backend.context.dev_path();
@ -261,13 +298,22 @@ impl<A: Device + 'static> DrmBackend<A> {
&self.connectors, &self.connectors,
(0, 0), (0, 0),
Some(mode), Some(mode),
).chain_err(|| ErrorKind::DrmDev(format!("Error setting crtc {:?} on {:?}", self.backend.crtc, self.backend.context.dev_path())))?; ).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error setting crtc {:?} on {:?}",
self.backend.crtc,
self.backend.context.dev_path()
))
})?;
front_bo front_bo
}); });
if let Ok(Some(fb)) = old_front_bo.take_userdata() { if let Ok(Some(fb)) = old_front_bo.take_userdata() {
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) { if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
warn!(self.backend.logger, "Error releasing old front_buffer framebuffer: {:?}", err); warn!(
self.backend.logger,
"Error releasing old front_buffer framebuffer: {:?}", err
);
} }
} }
@ -294,7 +340,9 @@ impl<A: Device + 'static> DrmBackendInternal<A> {
} }
} }
pub(crate) fn page_flip(&self, fb: Option<&framebuffer::Info>) -> ::std::result::Result<(), SwapBuffersError> { pub(crate) fn page_flip(
&self, fb: Option<&framebuffer::Info>
) -> ::std::result::Result<(), SwapBuffersError> {
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
let fb = *fb.unwrap_or(&self.current_frame_buffer.get()); let fb = *fb.unwrap_or(&self.current_frame_buffer.get());
@ -354,7 +402,12 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
&*self.backend.context, &*self.backend.context,
self.backend.crtc, self.backend.crtc,
(x as i32, y as i32), (x as i32, y as i32),
).chain_err(|| ErrorKind::DrmDev(format!("Error moving cursor on {:?}", self.backend.context.dev_path()))) ).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error moving cursor on {:?}",
self.backend.context.dev_path()
))
})
} }
fn set_cursor_representation( fn set_cursor_representation(
@ -364,20 +417,19 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
debug!(self.backend.logger, "Importing cursor"); debug!(self.backend.logger, "Importing cursor");
// import the cursor into a buffer we can render // import the cursor into a buffer we can render
let mut cursor = self let mut cursor = self.backend
.backend .context
.context .create_buffer_object(
.create_buffer_object( w,
w, h,
h, GbmFormat::ARGB8888,
GbmFormat::ARGB8888, BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE, )
) .chain_err(|| ErrorKind::GbmInitFailed)?;
.chain_err(|| ErrorKind::GbmInitFailed)?;
cursor cursor
.write(&**buffer) .write(&**buffer)
.chain_err(|| ErrorKind::GbmInitFailed)? .chain_err(|| ErrorKind::GbmInitFailed)?
.chain_err(|| ErrorKind::GbmInitFailed)?; .chain_err(|| ErrorKind::GbmInitFailed)?;
trace!(self.backend.logger, "Setting the new imported cursor"); trace!(self.backend.logger, "Setting the new imported cursor");
@ -389,9 +441,12 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
(hotspot.0 as i32, hotspot.1 as i32), (hotspot.0 as i32, hotspot.1 as i32),
).is_err() ).is_err()
{ {
crtc::set_cursor(&*self.backend.context, self.backend.crtc, &cursor).chain_err( crtc::set_cursor(&*self.backend.context, self.backend.crtc, &cursor).chain_err(|| {
|| ErrorKind::DrmDev(format!("Failed to set cursor on {:?}", self.backend.context.dev_path())), ErrorKind::DrmDev(format!(
)?; "Failed to set cursor on {:?}",
self.backend.context.dev_path()
))
})?;
} }
// and store it // and store it
@ -409,7 +464,10 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
res res
} { } {
// We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done // We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
warn!(self.backend.logger, "Tried to swap a DrmBackend with a queued flip"); warn!(
self.backend.logger,
"Tried to swap a DrmBackend with a queued flip"
);
return Err(SwapBuffersError::AlreadySwapped); return Err(SwapBuffersError::AlreadySwapped);
} }
@ -421,17 +479,20 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
// neither weston, wlc or wlroots bother with that as well. // neither weston, wlc or wlroots bother with that as well.
// so we just assume we got at least two buffers to do flipping. // so we just assume we got at least two buffers to do flipping.
let mut next_bo = self.surface let mut next_bo = self.surface
.lock_front_buffer() .lock_front_buffer()
.expect("Surface only has one front buffer. Not supported by smithay"); .expect("Surface only has one front buffer. Not supported by smithay");
// create a framebuffer if the front buffer does not have one already // create a framebuffer if the front buffer does not have one already
// (they are reused by gbm) // (they are reused by gbm)
let maybe_fb = next_bo.userdata().map_err(|_| SwapBuffersError::ContextLost)?.cloned(); let maybe_fb = next_bo
.userdata()
.map_err(|_| SwapBuffersError::ContextLost)?
.cloned();
let fb = if let Some(info) = maybe_fb { let fb = if let Some(info) = maybe_fb {
info info
} else { } else {
let fb = framebuffer::create(&*self.backend.context, &*next_bo) let fb = framebuffer::create(&*self.backend.context, &*next_bo)
.map_err(|_| SwapBuffersError::ContextLost)?; .map_err(|_| SwapBuffersError::ContextLost)?;
next_bo.set_userdata(fb).unwrap(); next_bo.set_userdata(fb).unwrap();
fb fb
}; };

View File

@ -212,29 +212,29 @@
use backend::graphics::egl::context::{EGLContext, GlAttributes}; use backend::graphics::egl::context::{EGLContext, GlAttributes};
use backend::graphics::egl::error::Result as EGLResult; use backend::graphics::egl::error::Result as EGLResult;
use backend::graphics::egl::native::Gbm; use backend::graphics::egl::native::Gbm;
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay}; use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use backend::session::SessionObserver; use backend::session::SessionObserver;
use drm::Device as BasicDevice; use drm::Device as BasicDevice;
use drm::control::{connector, crtc, encoder, Mode, ResourceInfo}; use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};
use drm::control::Device as ControlDevice; use drm::control::Device as ControlDevice;
use drm::result::Error as DrmError;
use drm::control::framebuffer; use drm::control::framebuffer;
use drm::result::Error as DrmError;
use gbm::Device as GbmDevice; use gbm::Device as GbmDevice;
use nix; use nix;
use nix::sys::stat::{dev_t, fstat};
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io::Result as IoResult; use std::io::Result as IoResult;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::path::PathBuf;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::sync::{Once, ONCE_INIT}; use std::sync::{Once, ONCE_INIT};
use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use nix::sys::stat::{dev_t, fstat};
use wayland_server::{EventLoopHandle, StateToken};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use wayland_server::{Display, StateProxy}; use wayland_server::{Display, StateProxy};
use wayland_server::{EventLoopHandle, StateToken};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
mod backend; mod backend;
pub mod error; pub mod error;
@ -299,7 +299,9 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
); );
}); });
let device_id = fstat(dev.as_raw_fd()).chain_err(|| ErrorKind::UnableToGetDeviceId)?.st_rdev; let device_id = fstat(dev.as_raw_fd())
.chain_err(|| ErrorKind::UnableToGetDeviceId)?
.st_rdev;
let mut drm = DrmDevice { let mut drm = DrmDevice {
// Open the gbm device from the drm device and create a context based on that // Open the gbm device from the drm device and create a context based on that
@ -326,17 +328,30 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
// we want to mode-set, so we better be the master // we want to mode-set, so we better be the master
drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?; drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?;
let res_handles = drm.resource_handles() let res_handles = drm.resource_handles().chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", drm.dev_path())))?; ErrorKind::DrmDev(format!(
"Error loading drm resources on {:?}",
drm.dev_path()
))
})?;
for &con in res_handles.connectors() { for &con in res_handles.connectors() {
let con_info = connector::Info::load_from_device(&drm, con) let con_info = connector::Info::load_from_device(&drm, con).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", drm.dev_path())))?; ErrorKind::DrmDev(format!(
"Error loading connector info on {:?}",
drm.dev_path()
))
})?;
if let Some(enc) = con_info.current_encoder() { if let Some(enc) = con_info.current_encoder() {
let enc_info = encoder::Info::load_from_device(&drm, enc) let enc_info = encoder::Info::load_from_device(&drm, enc).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", drm.dev_path())))?; ErrorKind::DrmDev(format!(
"Error loading encoder info on {:?}",
drm.dev_path()
))
})?;
if let Some(crtc) = enc_info.current_crtc() { if let Some(crtc) = enc_info.current_crtc() {
let info = crtc::Info::load_from_device(&drm, crtc) let info = crtc::Info::load_from_device(&drm, crtc).chain_err(|| {
.chain_err(|| ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", drm.dev_path())))?; ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", drm.dev_path()))
})?;
drm.old_state drm.old_state
.entry(crtc) .entry(crtc)
.or_insert((info, Vec::new())) .or_insert((info, Vec::new()))
@ -358,7 +373,7 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
&mut self, crtc: crtc::Handle, mode: Mode, connectors: I &mut self, crtc: crtc::Handle, mode: Mode, connectors: I
) -> Result<DrmBackend<A>> ) -> Result<DrmBackend<A>>
where where
I: Into<Vec<connector::Handle>> I: Into<Vec<connector::Handle>>,
{ {
if self.backends.contains_key(&crtc) { if self.backends.contains_key(&crtc) {
bail!(ErrorKind::CrtcAlreadyInUse(crtc)); bail!(ErrorKind::CrtcAlreadyInUse(crtc));
@ -373,10 +388,12 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
// check if we have an encoder for every connector and the mode mode // check if we have an encoder for every connector and the mode mode
for connector in &connectors { for connector in &connectors {
let con_info = connector::Info::load_from_device(self, *connector) let con_info = connector::Info::load_from_device(self, *connector).chain_err(|| {
.chain_err(|| { ErrorKind::DrmDev(format!(
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path())) "Error loading connector info on {:?}",
})?; self.dev_path()
))
})?;
// check the mode // check the mode
if !con_info.modes().contains(&mode) { if !con_info.modes().contains(&mode) {
@ -389,14 +406,20 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
.iter() .iter()
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(self, *encoder).chain_err(|| { encoder::Info::load_from_device(self, *encoder).chain_err(|| {
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path())) ErrorKind::DrmDev(format!(
"Error loading encoder info on {:?}",
self.dev_path()
))
}) })
}) })
.collect::<Result<Vec<encoder::Info>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc // and if any encoder supports the selected crtc
let resource_handles = self.resource_handles().chain_err(|| { let resource_handles = self.resource_handles().chain_err(|| {
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", self.dev_path())) ErrorKind::DrmDev(format!(
"Error loading drm resources on {:?}",
self.dev_path()
))
})?; })?;
if !encoders if !encoders
.iter() .iter()
@ -499,10 +522,7 @@ impl<A: ControlDevice + 'static> Drop for DrmDevice<A> {
pub trait DrmHandler<A: ControlDevice + 'static> { pub trait DrmHandler<A: ControlDevice + 'static> {
/// The `DrmBackend` of crtc has finished swapping buffers and new frame can now /// The `DrmBackend` of crtc has finished swapping buffers and new frame can now
/// (and should be immediately) be rendered. /// (and should be immediately) be rendered.
fn ready( fn ready(&mut self, device: &mut DrmDevice<A>, crtc: crtc::Handle, frame: u32, duration: Duration);
&mut self, device: &mut DrmDevice<A>, crtc: crtc::Handle,
frame: u32, duration: Duration,
);
/// The `DrmDevice` has thrown an error. /// The `DrmDevice` has thrown an error.
/// ///
/// The related backends are most likely *not* usable anymore and /// The related backends are most likely *not* usable anymore and
@ -548,17 +568,17 @@ where
if let crtc::Event::PageFlip(event) = event { if let crtc::Event::PageFlip(event) = event {
let dev = evlh.state().get_mut(dev_token); let dev = evlh.state().get_mut(dev_token);
if dev.active { if dev.active {
if let Some(backend) = dev.backends.get(&event.crtc).iter().flat_map(|x| x.upgrade()).next() { if let Some(backend) = dev.backends
.get(&event.crtc)
.iter()
.flat_map(|x| x.upgrade())
.next()
{
// we can now unlock the buffer // we can now unlock the buffer
backend.unlock_buffer(); backend.unlock_buffer();
trace!(logger, "Handling event for backend {:?}", event.crtc); trace!(logger, "Handling event for backend {:?}", event.crtc);
// and then call the user to render the next frame // and then call the user to render the next frame
handler.ready( handler.ready(dev, event.crtc, event.frame, event.duration);
dev,
event.crtc,
event.frame,
event.duration,
);
} else { } else {
dev.backends.remove(&event.crtc); dev.backends.remove(&event.crtc);
} }
@ -569,9 +589,9 @@ where
}; };
}, },
error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| { error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| {
let mut dev = evlh.state().get_mut(dev_token); let mut dev = evlh.state().get_mut(dev_token);
warn!(dev.logger, "DrmDevice errored: {}", error); warn!(dev.logger, "DrmDevice errored: {}", error);
handler.error(&mut dev, error.into()); handler.error(&mut dev, error.into());
}, },
} }
} }
@ -606,9 +626,7 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
if let Err(err) = backend.page_flip(None) { if let Err(err) = backend.page_flip(None) {
error!( error!(
device.logger, device.logger,
"Failed to activate crtc ({:?}) again. Error: {}", "Failed to activate crtc ({:?}) again. Error: {}", crtc, err
crtc,
err
); );
} }
} else { } else {

View File

@ -3,23 +3,22 @@
use super::{ffi, EGLSurface, PixelFormat}; use super::{ffi, EGLSurface, PixelFormat};
use super::error::*; use super::error::*;
use super::native; use super::native;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use gbm::{Device as GbmDevice}; use drm::Device as BasicDevice;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use drm::{Device as BasicDevice}; use drm::control::Device as ControlDevice;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use drm::control::{Device as ControlDevice}; use gbm::Device as GbmDevice;
use nix::libc::{c_void, c_int}; use nix::libc::{c_int, c_void};
use slog; use slog;
use std::ffi::{CString, CStr}; use std::ffi::{CStr, CString};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc;
use std::ptr;
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::ptr;
use std::rc::Rc;
/// EGL context for rendering /// EGL context for rendering
pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> { pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
@ -51,13 +50,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> DerefMut for EGLContext<B,
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> { impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
/// Create a new `EGLContext` from a given `NativeDisplay` /// Create a new `EGLContext` from a given `NativeDisplay`
pub fn new<L>( pub fn new<L>(
native: N, native: N, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L
attributes: GlAttributes,
reqs: PixelFormatRequirements,
logger: L
) -> Result<EGLContext<B, N>> ) -> Result<EGLContext<B, N>>
where where
L: Into<Option<::slog::Logger>> L: Into<Option<::slog::Logger>>,
{ {
let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl")); let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl"));
let ptr = native.ptr()?; let ptr = native.ptr()?;
@ -86,11 +82,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
} }
unsafe fn new_internal( unsafe fn new_internal(
ptr: ffi::NativeDisplayType, ptr: ffi::NativeDisplayType, mut attributes: GlAttributes, reqs: PixelFormatRequirements,
mut attributes: GlAttributes,
reqs: PixelFormatRequirements,
log: ::slog::Logger, log: ::slog::Logger,
) -> Result<( ) -> Result<
(
Rc<ffi::egl::types::EGLContext>, Rc<ffi::egl::types::EGLContext>,
Rc<ffi::egl::types::EGLDisplay>, Rc<ffi::egl::types::EGLDisplay>,
ffi::egl::types::EGLConfig, ffi::egl::types::EGLConfig,
@ -98,8 +93,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
PixelFormat, PixelFormat,
bool, 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
let version = match attributes.version { let version = match attributes.version {
@ -178,7 +173,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions); debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
let display = B::get_display(ptr, |e: &str| dp_extensions.iter().any(|s| s == e), log.clone()); let display = B::get_display(
ptr,
|e: &str| dp_extensions.iter().any(|s| s == e),
log.clone(),
);
if display == ffi::egl::NO_DISPLAY { if display == ffi::egl::NO_DISPLAY {
error!(log, "EGL Display is not valid"); error!(log, "EGL Display is not valid");
bail!(ErrorKind::DisplayNotSupported); bail!(ErrorKind::DisplayNotSupported);
@ -455,7 +454,9 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
// the list of gl extensions supported by the context // the list of gl extensions supported by the context
let gl_extensions = { let gl_extensions = {
let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _).to_bytes().to_vec(); let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _)
.to_bytes()
.to_vec();
let list = String::from_utf8(data).unwrap(); let list = String::from_utf8(data).unwrap();
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>() list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
}; };
@ -468,15 +469,24 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
config_id, config_id,
surface_attributes, surface_attributes,
desc, desc,
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"), extensions
gl_extensions.iter().any(|s| *s == "GL_OES_EGL_image" || *s == "GL_OES_EGL_image_base"), .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(&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(self, self.native.create_surface(args).chain_err(|| ErrorKind::SurfaceCreationFailed)?); let res = EGLSurface::new(
self,
self.native
.create_surface(args)
.chain_err(|| ErrorKind::SurfaceCreationFailed)?,
);
if res.is_ok() { if res.is_ok() {
debug!(self.logger, "EGL surface successfully created"); debug!(self.logger, "EGL surface successfully created");
} }

View File

@ -1,6 +1,6 @@
#![allow(missing_docs)] #![allow(missing_docs)]
pub use nix::libc::{c_long, c_void, c_uint, int32_t, uint64_t}; pub use nix::libc::{c_long, c_uint, c_void, int32_t, uint64_t};
pub type khronos_utime_nanoseconds_t = khronos_uint64_t; pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
pub type khronos_uint64_t = uint64_t; pub type khronos_uint64_t = uint64_t;
@ -37,43 +37,67 @@ pub mod egl {
* Lets do it ourselves... * Lets do it ourselves...
*/ */
#[allow(non_snake_case, unused_variables, dead_code)] #[inline] #[allow(non_snake_case, unused_variables, dead_code)]
pub unsafe fn BindWaylandDisplayWL(dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void) -> types::EGLBoolean { #[inline]
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean>(wayland_storage::BindWaylandDisplayWL.f)(dpy, display) pub unsafe fn BindWaylandDisplayWL(
dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void
) -> types::EGLBoolean {
__gl_imports::mem::transmute::<
_,
extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean,
>(wayland_storage::BindWaylandDisplayWL.f)(dpy, display)
} }
#[allow(non_snake_case, unused_variables, dead_code)] #[inline] #[allow(non_snake_case, unused_variables, dead_code)]
pub unsafe fn UnbindWaylandDisplayWL(dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void) -> types::EGLBoolean { #[inline]
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean>(wayland_storage::UnbindWaylandDisplayWL.f)(dpy, display) pub unsafe fn UnbindWaylandDisplayWL(
dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void
) -> types::EGLBoolean {
__gl_imports::mem::transmute::<
_,
extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean,
>(wayland_storage::UnbindWaylandDisplayWL.f)(dpy, display)
} }
#[allow(non_snake_case, unused_variables, dead_code)] #[inline] #[allow(non_snake_case, unused_variables, dead_code)]
pub unsafe fn QueryWaylandBufferWL(dpy: types::EGLDisplay, buffer: *mut __gl_imports::raw::c_void, attribute: types::EGLint, value: *mut types::EGLint) -> types::EGLBoolean { #[inline]
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void, types::EGLint, *mut types::EGLint) -> types::EGLBoolean>(wayland_storage::QueryWaylandBufferWL.f)(dpy, buffer, attribute, value) pub unsafe fn QueryWaylandBufferWL(
dpy: types::EGLDisplay, buffer: *mut __gl_imports::raw::c_void, attribute: types::EGLint,
value: *mut types::EGLint,
) -> types::EGLBoolean {
__gl_imports::mem::transmute::<
_,
extern "system" fn(
types::EGLDisplay,
*mut __gl_imports::raw::c_void,
types::EGLint,
*mut types::EGLint,
) -> types::EGLBoolean,
>(wayland_storage::QueryWaylandBufferWL.f)(dpy, buffer, attribute, value)
} }
mod wayland_storage { mod wayland_storage {
use super::__gl_imports::raw;
use super::FnPtr; use super::FnPtr;
use super::__gl_imports::raw;
pub static mut BindWaylandDisplayWL: FnPtr = FnPtr { pub static mut BindWaylandDisplayWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void, f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false is_loaded: false,
}; };
pub static mut UnbindWaylandDisplayWL: FnPtr = FnPtr { pub static mut UnbindWaylandDisplayWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void, f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false is_loaded: false,
}; };
pub static mut QueryWaylandBufferWL: FnPtr = FnPtr { pub static mut QueryWaylandBufferWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void, f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false is_loaded: false,
}; };
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub mod BindWaylandDisplayWL { pub mod BindWaylandDisplayWL {
use super::{wayland_storage, metaloadfn}; use super::{metaloadfn, wayland_storage};
use super::__gl_imports::raw;
use super::FnPtr; use super::FnPtr;
use super::__gl_imports::raw;
#[inline] #[inline]
#[allow(dead_code)] #[allow(dead_code)]
@ -82,18 +106,22 @@ pub mod egl {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void { pub fn load_with<F>(mut loadfn: F)
where
F: FnMut(&str) -> *const raw::c_void,
{
unsafe { unsafe {
wayland_storage::BindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[])) wayland_storage::BindWaylandDisplayWL =
FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
} }
} }
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub mod UnbindWaylandDisplayWL { pub mod UnbindWaylandDisplayWL {
use super::{wayland_storage, metaloadfn}; use super::{metaloadfn, wayland_storage};
use super::__gl_imports::raw;
use super::FnPtr; use super::FnPtr;
use super::__gl_imports::raw;
#[inline] #[inline]
#[allow(dead_code)] #[allow(dead_code)]
@ -102,18 +130,22 @@ pub mod egl {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void { pub fn load_with<F>(mut loadfn: F)
where
F: FnMut(&str) -> *const raw::c_void,
{
unsafe { unsafe {
wayland_storage::UnbindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[])) wayland_storage::UnbindWaylandDisplayWL =
FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
} }
} }
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub mod QueryWaylandBufferWL { pub mod QueryWaylandBufferWL {
use super::{wayland_storage, metaloadfn}; use super::{metaloadfn, wayland_storage};
use super::__gl_imports::raw;
use super::FnPtr; use super::FnPtr;
use super::__gl_imports::raw;
#[inline] #[inline]
#[allow(dead_code)] #[allow(dead_code)]
@ -122,9 +154,13 @@ pub mod egl {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void { pub fn load_with<F>(mut loadfn: F)
where
F: FnMut(&str) -> *const raw::c_void,
{
unsafe { unsafe {
wayland_storage::QueryWaylandBufferWL = FnPtr::new(metaloadfn(&mut loadfn, "eglQueryWaylandBufferWL", &[])) wayland_storage::QueryWaylandBufferWL =
FnPtr::new(metaloadfn(&mut loadfn, "eglQueryWaylandBufferWL", &[]))
} }
} }
} }

View File

@ -18,7 +18,7 @@ pub mod native;
pub mod surface; pub mod surface;
pub use self::surface::EGLSurface; pub use self::surface::EGLSurface;
pub mod wayland; pub mod wayland;
pub use self::wayland::{EGLWaylandExtensions, EGLImages, BufferAccessError}; pub use self::wayland::{BufferAccessError, EGLImages, EGLWaylandExtensions};
/// Error that can happen when swapping buffers. /// Error that can happen when swapping buffers.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -73,8 +73,12 @@ pub struct EglExtensionNotSupportedError(&'static [&'static str]);
impl fmt::Display for EglExtensionNotSupportedError { impl fmt::Display for EglExtensionNotSupportedError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> { 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, write!(
at least one is required: {:?}", self.0) formatter,
"None of the following EGL extensions is supported by the underlying EGL implementation,
at least one is required: {:?}",
self.0
)
} }
} }

View File

@ -1,24 +1,23 @@
//! Type safe native types for safe context/surface creation //! Type safe native types for safe context/surface creation
use super::ffi;
use super::error::*; use super::error::*;
use super::ffi;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use ::backend::drm::error::{Error as DrmError, ErrorKind as DrmErrorKind, Result as DrmResult}; use backend::drm::error::{Error as DrmError, ErrorKind as DrmErrorKind, Result as DrmResult};
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use gbm::{AsRaw, Device as GbmDevice, Format as GbmFormat, BufferObjectFlags, Surface as GbmSurface}; use gbm::{AsRaw, BufferObjectFlags, Device as GbmDevice, Format as GbmFormat, Surface as GbmSurface};
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use std::marker::PhantomData; use std::marker::PhantomData;
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
use std::ptr;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
use std::ptr;
#[cfg(feature = "backend_winit")]
use wayland_client::egl as wegl;
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
use winit::Window as WinitWindow; use winit::Window as WinitWindow;
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
use winit::os::unix::WindowExt; use winit::os::unix::WindowExt;
#[cfg(feature = "backend_winit")]
use wayland_client::egl as wegl;
/// Trait for typed backend variants (X11/Wayland/GBM) /// Trait for typed backend variants (X11/Wayland/GBM)
pub trait Backend { pub trait Backend {
@ -32,9 +31,7 @@ pub trait Backend {
/// The returned `EGLDisplay` needs to be a valid ptr for egl, /// The returned `EGLDisplay` needs to be a valid ptr for egl,
/// but there is no way to test that. /// but there is no way to test that.
unsafe fn get_display<F: Fn(&str) -> bool>( unsafe fn get_display<F: Fn(&str) -> bool>(
display: ffi::NativeDisplayType, display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
has_dp_extension: F,
log: ::slog::Logger,
) -> ffi::egl::types::EGLDisplay; ) -> ffi::egl::types::EGLDisplay;
} }
@ -45,24 +42,28 @@ pub enum Wayland {}
impl Backend for Wayland { impl Backend for Wayland {
type Surface = wegl::WlEglSurface; type Surface = wegl::WlEglSurface;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger) unsafe fn get_display<F>(
-> ffi::egl::types::EGLDisplay display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where where
F: Fn(&str) -> bool F: Fn(&str) -> bool,
{ {
if has_dp_extension("EGL_KHR_platform_wayland") if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() {
&& ffi::egl::GetPlatformDisplay::is_loaded() trace!(
{ log,
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland"); "EGL Display Initialization via EGL_KHR_platform_wayland"
);
ffi::egl::GetPlatformDisplay( ffi::egl::GetPlatformDisplay(
ffi::egl::PLATFORM_WAYLAND_KHR, ffi::egl::PLATFORM_WAYLAND_KHR,
display as *mut _, display as *mut _,
ptr::null(), ptr::null(),
) )
} else if has_dp_extension("EGL_EXT_platform_wayland") } else if has_dp_extension("EGL_EXT_platform_wayland") && ffi::egl::GetPlatformDisplayEXT::is_loaded()
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
{ {
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland"); trace!(
log,
"EGL Display Initialization via EGL_EXT_platform_wayland"
);
ffi::egl::GetPlatformDisplayEXT( ffi::egl::GetPlatformDisplayEXT(
ffi::egl::PLATFORM_WAYLAND_EXT, ffi::egl::PLATFORM_WAYLAND_EXT,
display as *mut _, display as *mut _,
@ -85,19 +86,16 @@ pub enum X11 {}
impl Backend for X11 { impl Backend for X11 {
type Surface = XlibWindow; type Surface = XlibWindow;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger) unsafe fn get_display<F>(
-> ffi::egl::types::EGLDisplay display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where where
F: Fn(&str) -> bool F: Fn(&str) -> bool,
{ {
if has_dp_extension("EGL_KHR_platform_x11") if has_dp_extension("EGL_KHR_platform_x11") && ffi::egl::GetPlatformDisplay::is_loaded() {
&& ffi::egl::GetPlatformDisplay::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11"); trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null()) ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_EXT_platform_x11") } else if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11"); trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null()) ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
} else { } else {
@ -115,24 +113,19 @@ pub struct Gbm<T: 'static> {
impl<T: 'static> Backend for Gbm<T> { impl<T: 'static> Backend for Gbm<T> {
type Surface = GbmSurface<T>; type Surface = GbmSurface<T>;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger) unsafe fn get_display<F>(
-> ffi::egl::types::EGLDisplay display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where where
F: Fn(&str) -> bool F: Fn(&str) -> bool,
{ {
if has_dp_extension("EGL_KHR_platform_gbm") if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
&& ffi::egl::GetPlatformDisplay::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm"); trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()) ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_MESA_platform_gbm") } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm"); trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_MESA_platform_gbm") } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
&& ffi::egl::GetPlatformDisplay::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm"); trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
} else { } else {
@ -224,7 +217,9 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
type Arguments = GbmSurfaceArguments; type Arguments = GbmSurfaceArguments;
type Error = DrmError; type Error = DrmError;
fn is_backend(&self) -> bool { true } fn is_backend(&self) -> bool {
true
}
fn ptr(&self) -> Result<ffi::NativeDisplayType> { fn ptr(&self) -> Result<ffi::NativeDisplayType> {
Ok(self.as_raw() as *const _) Ok(self.as_raw() as *const _)
@ -233,13 +228,10 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
fn create_surface(&self, args: GbmSurfaceArguments) -> DrmResult<GbmSurface<T>> { fn create_surface(&self, args: GbmSurfaceArguments) -> DrmResult<GbmSurface<T>> {
use backend::drm::error::ResultExt as DrmResultExt; use backend::drm::error::ResultExt as DrmResultExt;
DrmResultExt::chain_err(GbmDevice::create_surface( DrmResultExt::chain_err(
self, GbmDevice::create_surface(self, args.size.0, args.size.1, args.format, args.flags),
args.size.0, || DrmErrorKind::GbmInitFailed,
args.size.1, )
args.format,
args.flags,
), || DrmErrorKind::GbmInitFailed)
} }
} }
@ -255,15 +247,21 @@ pub unsafe trait NativeSurface {
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
unsafe impl NativeSurface for XlibWindow { unsafe impl NativeSurface for XlibWindow {
fn ptr(&self) -> ffi::NativeWindowType { self.0 as *const _ } fn ptr(&self) -> ffi::NativeWindowType {
self.0 as *const _
}
} }
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
unsafe impl NativeSurface for wegl::WlEglSurface { unsafe impl NativeSurface for wegl::WlEglSurface {
fn ptr(&self) -> ffi::NativeWindowType { self.ptr() as *const _ } fn ptr(&self) -> ffi::NativeWindowType {
self.ptr() as *const _
}
} }
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
unsafe impl<T: 'static> NativeSurface for GbmSurface<T> { unsafe impl<T: 'static> NativeSurface for GbmSurface<T> {
fn ptr(&self) -> ffi::NativeWindowType { self.as_raw() as *const _ } fn ptr(&self) -> ffi::NativeWindowType {
self.as_raw() as *const _
}
} }

View File

@ -4,7 +4,6 @@ use super::{EGLContext, SwapBuffersError};
use super::error::*; use super::error::*;
use super::ffi; use super::ffi;
use super::native; use super::native;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
@ -30,9 +29,8 @@ impl<N: native::NativeSurface> DerefMut for EGLSurface<N> {
} }
impl<N: native::NativeSurface> EGLSurface<N> { impl<N: native::NativeSurface> EGLSurface<N> {
pub(crate) fn new<B: native::Backend<Surface=N>, D: native::NativeDisplay<B>>( pub(crate) fn new<B: native::Backend<Surface = N>, D: native::NativeDisplay<B>>(
context: &EGLContext<B, D>, context: &EGLContext<B, D>, native: N
native: N,
) -> Result<EGLSurface<N>> { ) -> Result<EGLSurface<N>> {
let surface = unsafe { let surface = unsafe {
ffi::egl::CreateWindowSurface( ffi::egl::CreateWindowSurface(
@ -58,9 +56,7 @@ 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() { if let Some(display) = self.display.upgrade() {
let ret = unsafe { let ret = unsafe { ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _) };
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 {

View File

@ -10,12 +10,12 @@
//! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer` //! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer`
//! for rendering. //! for rendering.
use backend::graphics::egl::{EGLContext, EglExtensionNotSupportedError, ffi, native}; use backend::graphics::egl::{ffi, native, EGLContext, EglExtensionNotSupportedError};
use backend::graphics::egl::error::*; use backend::graphics::egl::error::*;
use backend::graphics::egl::ffi::egl::types::EGLImage; use backend::graphics::egl::ffi::egl::types::EGLImage;
use nix::libc::{c_uint}; use nix::libc::c_uint;
use std::rc::{Rc, Weak};
use std::fmt; use std::fmt;
use std::rc::{Rc, Weak};
use wayland_server::{Display, Resource}; use wayland_server::{Display, Resource};
use wayland_server::protocol::wl_buffer::WlBuffer; use wayland_server::protocol::wl_buffer::WlBuffer;
use wayland_sys::server::wl_display; use wayland_sys::server::wl_display;
@ -37,7 +37,9 @@ impl fmt::Debug for BufferAccessError {
match *self { match *self {
BufferAccessError::ContextLost => write!(formatter, "BufferAccessError::ContextLost"), BufferAccessError::ContextLost => write!(formatter, "BufferAccessError::ContextLost"),
BufferAccessError::NotManaged(_) => write!(formatter, "BufferAccessError::NotManaged"), BufferAccessError::NotManaged(_) => write!(formatter, "BufferAccessError::NotManaged"),
BufferAccessError::EGLImageCreationFailed => write!(formatter, "BufferAccessError::EGLImageCreationFailed"), BufferAccessError::EGLImageCreationFailed => {
write!(formatter, "BufferAccessError::EGLImageCreationFailed")
}
BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err), BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err),
} }
} }
@ -45,9 +47,11 @@ impl fmt::Debug for BufferAccessError {
impl fmt::Display for BufferAccessError { impl fmt::Display for BufferAccessError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
use ::std::error::Error; use std::error::Error;
match *self { match *self {
BufferAccessError::ContextLost | BufferAccessError::NotManaged(_) | BufferAccessError::EGLImageCreationFailed => write!(formatter, "{}", self.description()), BufferAccessError::ContextLost
| BufferAccessError::NotManaged(_)
| BufferAccessError::EGLImageCreationFailed => write!(formatter, "{}", self.description()),
BufferAccessError::EglExtensionNotSupported(ref err) => err.fmt(formatter), BufferAccessError::EglExtensionNotSupported(ref err) => err.fmt(formatter),
} }
} }
@ -102,11 +106,16 @@ pub enum TextureCreationError {
impl fmt::Display for TextureCreationError { impl fmt::Display for TextureCreationError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
use ::std::error::Error; use std::error::Error;
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::TextureBindingFailed(code) => write!(formatter, "{}. Gl error code: {:?}", self.description(), code), TextureCreationError::TextureBindingFailed(code) => write!(
formatter,
"{}. Gl error code: {:?}",
self.description(),
code
),
} }
} }
} }
@ -182,12 +191,19 @@ 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.
pub unsafe fn bind_to_texture(&self, plane: usize, tex_id: c_uint) -> ::std::result::Result<(), TextureCreationError> { pub unsafe fn bind_to_texture(
&self, plane: usize, tex_id: c_uint
) -> ::std::result::Result<(), TextureCreationError> {
if self.display.upgrade().is_some() { if self.display.upgrade().is_some() {
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); ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_tex_id);
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id); ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id);
ffi::gl::EGLImageTargetTexture2DOES(ffi::gl::TEXTURE_2D, *self.images.get(plane).ok_or(TextureCreationError::PlaneIndexOutOfBounds)?); ffi::gl::EGLImageTargetTexture2DOES(
ffi::gl::TEXTURE_2D,
*self.images
.get(plane)
.ok_or(TextureCreationError::PlaneIndexOutOfBounds)?,
);
let res = match ffi::egl::GetError() as u32 { let res = match ffi::egl::GetError() as u32 {
ffi::egl::SUCCESS => Ok(()), ffi::egl::SUCCESS => Ok(()),
err => Err(TextureCreationError::TextureBindingFailed(err)), err => Err(TextureCreationError::TextureBindingFailed(err)),
@ -204,7 +220,9 @@ impl Drop for EGLImages {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(display) = self.display.upgrade() { if let Some(display) = self.display.upgrade() {
for image in self.images.drain(..) { for image in self.images.drain(..) {
unsafe { ffi::egl::DestroyImageKHR(*display, image); } unsafe {
ffi::egl::DestroyImageKHR(*display, image);
}
} }
} }
self.buffer.release(); self.buffer.release();
@ -236,7 +254,9 @@ pub trait EGLWaylandExtensions {
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display); pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
impl EGLDisplay { impl EGLDisplay {
fn new<B: native::Backend, N: native::NativeDisplay<B>>(context: &EGLContext<B, N>, display: *mut wl_display) -> EGLDisplay { fn new<B: native::Backend, N: native::NativeDisplay<B>>(
context: &EGLContext<B, N>, display: *mut wl_display
) -> EGLDisplay {
EGLDisplay(Rc::downgrade(&context.display), display) EGLDisplay(Rc::downgrade(&context.display), display)
} }
@ -245,10 +265,19 @@ impl EGLDisplay {
/// In case the buffer is not managed by egl (but e.g. the wayland::shm module) /// 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 /// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer
/// to render it another way. /// to render it another way.
pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> { pub fn egl_buffer_contents(
&self, buffer: WlBuffer
) -> ::std::result::Result<EGLImages, BufferAccessError> {
if let Some(display) = self.0.upgrade() { if let Some(display) = self.0.upgrade() {
let mut format: i32 = 0; let mut format: i32 = 0;
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } { if unsafe {
ffi::egl::QueryWaylandBufferWL(
*display,
buffer.ptr() as *mut _,
ffi::egl::EGL_TEXTURE_FORMAT,
&mut format as *mut _,
) == 0
} {
return Err(BufferAccessError::NotManaged(buffer)); return Err(BufferAccessError::NotManaged(buffer));
} }
let format = match format { let format = match format {
@ -262,17 +291,38 @@ impl EGLDisplay {
}; };
let mut width: i32 = 0; let mut width: i32 = 0;
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } { if unsafe {
ffi::egl::QueryWaylandBufferWL(
*display,
buffer.ptr() as *mut _,
ffi::egl::WIDTH as i32,
&mut width as *mut _,
) == 0
} {
return Err(BufferAccessError::NotManaged(buffer)); return Err(BufferAccessError::NotManaged(buffer));
} }
let mut height: i32 = 0; let mut height: i32 = 0;
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } { if unsafe {
ffi::egl::QueryWaylandBufferWL(
*display,
buffer.ptr() as *mut _,
ffi::egl::HEIGHT as i32,
&mut height as *mut _,
) == 0
} {
return Err(BufferAccessError::NotManaged(buffer)); return Err(BufferAccessError::NotManaged(buffer));
} }
let mut inverted: i32 = 0; let mut inverted: i32 = 0;
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) != 0 } { if unsafe {
ffi::egl::QueryWaylandBufferWL(
*display,
buffer.ptr() as *mut _,
ffi::egl::WAYLAND_Y_INVERTED_WL,
&mut inverted as *mut _,
) != 0
} {
inverted = 1; inverted = 1;
} }
@ -281,17 +331,18 @@ impl EGLDisplay {
let mut out = Vec::with_capacity(3); let mut out = Vec::with_capacity(3);
out.push(ffi::egl::WAYLAND_PLANE_WL as i32); out.push(ffi::egl::WAYLAND_PLANE_WL as i32);
out.push(i as i32); out.push(i as i32);
out.push(ffi::egl::NONE as i32); out.push(ffi::egl::NONE as i32);
images.push({ images.push({
let image = let image = unsafe {
unsafe { ffi::egl::CreateImageKHR( ffi::egl::CreateImageKHR(
*display, *display,
ffi::egl::NO_CONTEXT, ffi::egl::NO_CONTEXT,
ffi::egl::WAYLAND_BUFFER_WL, ffi::egl::WAYLAND_BUFFER_WL,
buffer.ptr() as *mut _, buffer.ptr() as *mut _,
out.as_ptr(), out.as_ptr(),
) }; )
};
if image == ffi::egl::NO_IMAGE_KHR { if image == ffi::egl::NO_IMAGE_KHR {
return Err(BufferAccessError::EGLImageCreationFailed); return Err(BufferAccessError::EGLImageCreationFailed);
} else { } else {
@ -319,14 +370,15 @@ impl Drop for EGLDisplay {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(display) = self.0.upgrade() { if let Some(display) = self.0.upgrade() {
if !self.1.is_null() { if !self.1.is_null() {
unsafe { ffi::egl::UnbindWaylandDisplayWL(*display, self.1 as *mut _); } unsafe {
ffi::egl::UnbindWaylandDisplayWL(*display, self.1 as *mut _);
}
} }
} }
} }
} }
impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E> impl<E: EGLWaylandExtensions> EGLWaylandExtensions 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)
} }
@ -335,7 +387,9 @@ impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E>
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLWaylandExtensions for EGLContext<B, N> { impl<B: native::Backend, N: native::NativeDisplay<B>> EGLWaylandExtensions 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(&["EGL_WL_bind_wayland_display"])); bail!(ErrorKind::EglExtensionNotSupported(&[
"EGL_WL_bind_wayland_display"
]));
} }
if !self.egl_to_texture_support { if !self.egl_to_texture_support {
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"])); bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));

View File

@ -1,8 +1,8 @@
//! Glium compatibility module //! Glium compatibility module
use backend::graphics::egl::{EGLGraphicsBackend, SwapBuffersError}; use backend::graphics::egl::{EGLGraphicsBackend, SwapBuffersError};
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
use backend::graphics::egl::error::Result as EGLResult; use backend::graphics::egl::error::Result as EGLResult;
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
use glium::Frame; use glium::Frame;
use glium::SwapBuffersError as GliumSwapBuffersError; use glium::SwapBuffersError as GliumSwapBuffersError;
use glium::backend::{Backend, Context, Facade}; use glium::backend::{Backend, Context, Facade};
@ -76,13 +76,13 @@ impl<T: EGLGraphicsBackend + 'static> From<T> for GliumGraphicsBackend<T> {
} }
} }
impl<T: EGLGraphicsBackend + EGLWaylandExtensions + 'static> EGLWaylandExtensions for GliumGraphicsBackend<T> { impl<T: EGLGraphicsBackend + EGLWaylandExtensions + 'static> EGLWaylandExtensions
for GliumGraphicsBackend<T> {
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> { fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
(*self.backend).0.bind_wl_display(display) (*self.backend).0.bind_wl_display(display)
} }
} }
unsafe impl<T: EGLGraphicsBackend> Backend for InternalBackend<T> { unsafe impl<T: EGLGraphicsBackend> Backend for InternalBackend<T> {
fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> { fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> {
self.0.swap_buffers().map_err(Into::into) self.0.swap_buffers().map_err(Into::into)

View File

@ -9,10 +9,10 @@
//! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this //! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this
//! backend. //! backend.
use drm::Device as BasicDevice;
use drm::control::Device as ControlDevice;
use backend::drm::{drm_device_bind, DrmDevice, DrmHandler}; use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
use backend::session::{Session, SessionObserver}; use backend::session::{Session, SessionObserver};
use drm::Device as BasicDevice;
use drm::control::Device as ControlDevice;
use nix::fcntl; use nix::fcntl;
use nix::sys::stat::dev_t; use nix::sys::stat::dev_t;
use std::collections::HashMap; use std::collections::HashMap;
@ -59,11 +59,8 @@ pub struct UdevBackend<
logger: ::slog::Logger, logger: ::slog::Logger,
} }
impl< impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevHandler<H> + 'static>
H: DrmHandler<SessionFdDrmDevice> + 'static, UdevBackend<H, S, T> {
S: Session + 'static,
T: UdevHandler<H> + 'static,
> UdevBackend<H, S, T> {
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state. /// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
/// ///
/// ## Arguments /// ## Arguments
@ -244,7 +241,12 @@ where
) { ) {
Ok(fd) => SessionFdDrmDevice(fd), Ok(fd) => SessionFdDrmDevice(fd),
Err(err) => { Err(err) => {
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err); warn!(
logger,
"Unable to open drm device {:?}, Error: {:?}. Skipping",
path,
err
);
continue; continue;
} }
} }
@ -355,16 +357,16 @@ where
} }
/// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime. /// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime.
pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> {
{
/// Called on initialization for every known device and when a new device is detected. /// Called on initialization for every known device and when a new device is detected.
/// ///
/// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device. /// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device.
/// ///
/// ## Panics /// ## Panics
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
fn device_added<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>) fn device_added<'a, S: Into<StateProxy<'a>>>(
-> Option<H>; &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>
) -> Option<H>;
/// Called when an open device is changed. /// Called when an open device is changed.
/// ///
/// This usually indicates that some connectors did become available or were unplugged. The handler /// This usually indicates that some connectors did become available or were unplugged. The handler
@ -372,7 +374,9 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static>
/// ///
/// ## Panics /// ## Panics
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
fn device_changed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>); fn device_changed<'a, S: Into<StateProxy<'a>>>(
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
);
/// Called when a device was removed. /// Called when a device was removed.
/// ///
/// The device will not accept any operations anymore and its file descriptor will be closed once /// The device will not accept any operations anymore and its file descriptor will be closed once
@ -380,7 +384,9 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static>
/// ///
/// ## Panics /// ## Panics
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
fn device_removed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>); fn device_removed<'a, S: Into<StateProxy<'a>>>(
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
);
/// Called when the udev context has encountered and error. /// Called when the udev context has encountered and error.
/// ///
/// ## Panics /// ## Panics

View File

@ -1,12 +1,12 @@
//! Implementation of backend traits for types provided by `winit` //! Implementation of backend traits for types provided by `winit`
use backend::graphics::GraphicsBackend; use backend::graphics::GraphicsBackend;
use backend::graphics::egl::{EGLGraphicsBackend, EGLContext, EGLSurface, PixelFormat, SwapBuffersError}; use backend::graphics::egl::{EGLContext, EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError};
use backend::graphics::egl::context::GlAttributes;
use backend::graphics::egl::error as egl_error; use backend::graphics::egl::error as egl_error;
use backend::graphics::egl::error::Result as EGLResult; use backend::graphics::egl::error::Result as EGLResult;
use backend::graphics::egl::native; use backend::graphics::egl::native;
use backend::graphics::egl::context::GlAttributes; use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState, use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent, KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent, PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
@ -16,10 +16,10 @@ use std::cmp;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor,
MouseScrollDelta, Touch, TouchPhase, WindowBuilder, WindowEvent, Window as WinitWindow};
use wayland_client::egl as wegl; use wayland_client::egl as wegl;
use wayland_server::Display; use wayland_server::Display;
use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor,
MouseScrollDelta, Touch, TouchPhase, Window as WinitWindow, WindowBuilder, WindowEvent};
error_chain! { error_chain! {
errors { errors {
@ -139,32 +139,18 @@ where
let reqs = Default::default(); let reqs = Default::default();
let window = Rc::new( let window = Rc::new(
if native::NativeDisplay::<native::Wayland>::is_backend(&winit_window) { if native::NativeDisplay::<native::Wayland>::is_backend(&winit_window) {
let context = EGLContext::<native::Wayland, WinitWindow>::new( let context =
winit_window, EGLContext::<native::Wayland, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
attributes,
reqs,
log.clone(),
)?;
let surface = context.create_surface(())?; let surface = context.create_surface(())?;
Window::Wayland { Window::Wayland { context, surface }
context,
surface
}
} else if native::NativeDisplay::<native::X11>::is_backend(&winit_window) { } else if native::NativeDisplay::<native::X11>::is_backend(&winit_window) {
let context = EGLContext::<native::X11, WinitWindow>::new( let context =
winit_window, EGLContext::<native::X11, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
attributes,
reqs,
log.clone(),
)?;
let surface = context.create_surface(())?; let surface = context.create_surface(())?;
Window::X11 { Window::X11 { context, surface }
context,
surface
}
} else { } else {
bail!(ErrorKind::NotSupported); bail!(ErrorKind::NotSupported);
} },
); );
Ok(( Ok((
@ -237,8 +223,14 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
fn is_current(&self) -> bool { fn is_current(&self) -> bool {
match *self.window { match *self.window {
Window::Wayland { ref context, ref surface } => context.is_current() && surface.is_current(), Window::Wayland {
Window::X11 { ref context, ref surface } => context.is_current() && surface.is_current(), ref context,
ref surface,
} => context.is_current() && surface.is_current(),
Window::X11 {
ref context,
ref surface,
} => context.is_current() && surface.is_current(),
} }
} }
@ -649,8 +641,10 @@ impl InputBackend for WinitInputBackend {
trace!(logger, "Resizing window to {:?}", (x, y)); trace!(logger, "Resizing window to {:?}", (x, y));
window.window().set_inner_size(x, y); window.window().set_inner_size(x, y);
match **window { match **window {
Window::Wayland { ref surface, .. } => surface.resize(x as i32, y as i32, 0, 0), Window::Wayland { ref surface, .. } => {
_ => {}, surface.resize(x as i32, y as i32, 0, 0)
}
_ => {}
}; };
} }
( (

View File

@ -449,8 +449,7 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Wl(ref shell) => { ShellClientKind::Wl(ref shell) => {
let mutex = let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();
if guard.0.pending_ping == 0 { if guard.0.pending_ping == 0 {
return Err(()); return Err(());
@ -487,8 +486,7 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Wl(ref shell) => { ShellClientKind::Wl(ref shell) => {
let mutex = let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();
Ok(f(&mut guard.0.data)) Ok(f(&mut guard.0.data))
} }

View File

@ -271,8 +271,7 @@ where
{ {
wl_shell_surface::Implementation { wl_shell_surface::Implementation {
pong: |evlh, idata, _, shell_surface, serial| { pong: |evlh, idata, _, shell_surface, serial| {
let &(_, ref shell) = let &(_, ref shell) = unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
let valid = { let valid = {
let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) }; let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();

View File

@ -230,9 +230,8 @@ fn destroy_surface(surface: &zxdg_surface_v6::ZxdgSurfaceV6) {
let ptr = surface.get_user_data(); let ptr = surface.get_user_data();
surface.set_user_data(::std::ptr::null_mut()); surface.set_user_data(::std::ptr::null_mut());
// drop the state // drop the state
let data = unsafe { let data =
Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6)) unsafe { Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6)) };
};
// explicit call to drop to not forget what we're doing here // explicit call to drop to not forget what we're doing here
::std::mem::drop(data); ::std::mem::drop(data);
} }
@ -544,9 +543,8 @@ where
with_surface_toplevel_data(idata, toplevel, |toplevel_data| { with_surface_toplevel_data(idata, toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_ptr = toplevel_surface_parent.get_user_data(); let parent_ptr = toplevel_surface_parent.get_user_data();
let &(ref parent_surface, _) = unsafe { let &(ref parent_surface, _) =
&*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6)) unsafe { &*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6)) };
};
unsafe { parent_surface.clone_unchecked() } unsafe { parent_surface.clone_unchecked() }
}) })
}); });

View File

@ -43,6 +43,8 @@ containers:
- !Container base - !Container base
- !Env HOME: /work/.vagga/nightly-home - !Env HOME: /work/.vagga/nightly-home
- !Sh curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host x86_64-unknown-linux-gnu --default-toolchain nightly --no-modify-path - !Sh curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host x86_64-unknown-linux-gnu --default-toolchain nightly --no-modify-path
- !Env PATH: /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/work/.vagga/nightly-home/.cargo/bin:/work/.vagga/nightly-home/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/
- !Sh rustup component add rustfmt-preview
commands: commands:
update-stable: !Command update-stable: !Command