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
;;
"cargo-fmt")
vagga cargo-$TRAVIS_RUST_VERSION install -f rustfmt-nightly &&
vagga cargo-$TRAVIS_RUST_VERSION fmt -- --write-mode=diff
;;
"cargo-clippy")

View File

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

View File

@ -20,18 +20,18 @@ use drm::control::crtc;
use drm::control::encoder::Info as EncoderInfo;
use drm::result::Error as DrmError;
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 smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
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::roles::Role;
use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell;
use std::fs::{File, OpenOptions};
use std::os::unix::io::RawFd;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::RawFd;
use std::rc::Rc;
use std::time::Duration;
@ -64,8 +64,10 @@ fn main() {
let mut options = OpenOptions::new();
options.read(true);
options.write(true);
let mut device =
DrmDevice::new(Card(options.clone().open("/dev/dri/card0").unwrap()), log.clone()).unwrap();
let mut device = DrmDevice::new(
Card(options.clone().open("/dev/dri/card0").unwrap()),
log.clone(),
).unwrap();
// Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap();
@ -74,9 +76,7 @@ fn main() {
let connector_info = res_handles
.connectors()
.iter()
.map(|conn| {
ConnectorInfo::load_from_device(&device, *conn).unwrap()
})
.map(|conn| ConnectorInfo::load_from_device(&device, *conn).unwrap())
.find(|conn| conn.connection_state() == ConnectorState::Connected)
.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.)
// Initialize the hardware backend
let renderer = GliumDrawer::from(device
let renderer = GliumDrawer::from(
device
.create_backend(crtc, mode, vec![connector_info.handle()])
.unwrap());
.unwrap(),
);
{
/*
* Initialize glium
@ -114,7 +116,7 @@ fn main() {
Some(egl_display)
} else {
None
}
},
));
/*
@ -123,7 +125,8 @@ fn main() {
init_shm_global(&mut event_loop, vec![], log.clone());
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone());
let (compositor_token, _shell_state_token, window_map) =
init_shell(&mut event_loop, log.clone(), egl_display.clone());
/*
* Add a listening socket:
@ -162,7 +165,9 @@ pub struct 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();
frame.clear_color(0.8, 0.8, 0.9, 1.0);
// redraw the frame, in a simple but inneficient way
@ -185,19 +190,21 @@ impl DrmHandler<Card> for DrmHandlerImpl {
Some(Buffer::Egl { ref images }) => {
match images.format {
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.
attributes.user_data.texture = None;
remove = true;
},
}
};
},
}
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 {
attributes.user_data.buffer = None;
@ -239,8 +246,7 @@ impl DrmHandler<Card> for DrmHandlerImpl {
frame.finish().unwrap();
}
fn error(&mut self, _device: &mut DrmDevice<Card>,
error: DrmError) {
fn error(&mut self, _device: &mut DrmDevice<Card>, error: DrmError) {
panic!("{:?}", error);
}
}

View File

@ -1,10 +1,10 @@
use glium;
use glium::{Frame, Surface, GlObject};
use glium::{Frame, GlObject, Surface};
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::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 std::borrow::Borrow;
use std::ops::Deref;
@ -120,9 +120,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
Texture2d::new(&self.display, image).unwrap()
}
pub fn texture_from_egl(&self, images: &EGLImages)
-> Option<Texture2d>
{
pub fn texture_from_egl(&self, images: &EGLImages) -> Option<Texture2d> {
let format = match images.format {
Format::RGB => UncompressedFloatFormat::U8U8U8,
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
@ -136,15 +134,19 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
images.width,
images.height,
).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)
}
pub fn render_texture(&self, target: &mut glium::Frame, texture: &Texture2d,
y_inverted: bool, surface_dimensions: (u32, u32),
surface_location: (i32, i32), screen_size: (u32, u32),
blending: glium::Blend)
{
pub fn render_texture(
&self, target: &mut glium::Frame, texture: &Texture2d, y_inverted: bool,
surface_dimensions: (u32, u32), surface_location: (i32, i32), screen_size: (u32, u32),
blending: glium::Blend,
) {
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);
@ -175,7 +177,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
&glium::DrawParameters {
blend: blending,
..Default::default()
}
},
)
.unwrap();
}

View File

@ -1,7 +1,7 @@
use super::WindowMap;
use smithay::backend::graphics::egl::wayland::{Format, BufferAccessError};
use glium::texture::Texture2d;
use rand;
use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format};
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
SurfaceUserImplementation};
@ -25,7 +25,8 @@ pub enum Buffer {
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 {
commit: |_, display, surface, token| {
// we retrieve the contents of the associated buffer and copy it
@ -37,22 +38,21 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
display.egl_buffer_contents(buffer)
} else {
Err(BufferAccessError::NotManaged(buffer))
}
{
} {
Ok(images) => {
match images.format {
Format::RGB => {},
Format::RGBA => {},
Format::RGB => {}
Format::RGBA => {}
_ => {
// we don't handle the more complex formats here.
attributes.user_data.buffer = None;
attributes.user_data.texture = None;
return;
},
}
};
attributes.user_data.texture = None;
attributes.user_data.buffer = Some(Buffer::Egl { images });
},
}
Err(BufferAccessError::NotManaged(buffer)) => {
shm_buffer_contents(&buffer, |slice, data| {
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) });
}).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!");
buffer.release();
},
}
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 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
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
{
@ -113,22 +114,18 @@ where
serial: 42,
}
},
new_popup: |_, _, _| {
PopupConfigure {
new_popup: |_, _, _| PopupConfigure {
size: (10, 10),
position: (10, 10),
serial: 42,
}
},
move_: |_, _, _, _, _| {},
resize: |_, _, _, _, _, _| {},
grab: |_, _, _, _, _| {},
change_display_state: |_, _, _, _, _, _, _| {
ToplevelConfigure {
change_display_state: |_, _, _, _, _, _, _| ToplevelConfigure {
size: None,
states: vec![],
serial: 42,
}
},
show_window_menu: |_, _, _, _, _, _, _| {},
}
@ -155,12 +152,12 @@ pub type MyWindowMap = WindowMap<
>;
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>>>>,
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
Rc<RefCell<MyWindowMap>>,
) {
) {
let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone());
let window_map = Rc::new(RefCell::new(WindowMap::<_, _, _, (), _>::new(

View File

@ -19,8 +19,9 @@ where
SD: 'static,
{
// 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)
-> Option<(wl_surface::WlSurface, (f64, f64))>
fn matching<F>(
&self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F
) -> Option<(wl_surface::WlSurface, (f64, f64))>
where
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
{
@ -33,7 +34,8 @@ where
let _ = ctoken.with_surface_tree_downward(
wl_surface,
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 Some((w, h)) = get_size(attributes) {
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.x;
y += subdata.y;
@ -45,15 +47,16 @@ where
height: h,
};
if my_rect.contains((point.0 as i32, point.1 as i32)) {
found = wl_surface.clone().map(|s| {
(s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64))
});
found = wl_surface
.clone()
.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 {
TraversalAction::SkipChildren
}
},
);
}
@ -151,8 +154,9 @@ where
None
}
pub fn get_surface_and_bring_to_top(&mut self, point: (f64, f64))
-> Option<(wl_surface::WlSurface, (f64, f64))> {
pub fn get_surface_and_bring_to_top(
&mut self, point: (f64, f64)
) -> Option<(wl_surface::WlSurface, (f64, f64))> {
let mut found = None;
for (i, w) in self.windows.iter().enumerate() {
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {

View File

@ -1,14 +1,14 @@
extern crate drm;
#[macro_use]
extern crate glium;
extern crate rand;
extern crate input as libinput;
extern crate image;
extern crate udev;
extern crate input as libinput;
extern crate rand;
#[macro_use(define_roles)]
extern crate smithay;
extern crate xkbcommon;
extern crate udev;
extern crate wayland_server;
extern crate xkbcommon;
#[macro_use]
extern crate slog;
@ -21,25 +21,26 @@ mod helpers;
use drm::control::{Device as ControlDevice, ResourceInfo};
use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState};
use drm::control::encoder::Info as EncoderInfo;
use drm::control::crtc;
use drm::control::encoder::Info as EncoderInfo;
use drm::result::Error as DrmError;
use glium::{Blend, Surface};
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
use image::{ImageBuffer, Rgba};
use libinput::{Libinput, Device as LibinputDevice, event};
use libinput::{event, Device as LibinputDevice, Libinput};
use libinput::event::keyboard::KeyboardEventTrait;
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData, Buffer};
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::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay, Format};
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerButtonEvent,
PointerAxisEvent, KeyState};
use smithay::backend::libinput::{LibinputInputBackend, libinput_bind, PointerAxisEvent as LibinputPointerAxisEvent, LibinputSessionInterface};
use smithay::backend::udev::{UdevBackend, UdevHandler, udev_backend_bind, primary_gpu, SessionFdDrmDevice};
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format};
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
PointerAxisEvent, PointerButtonEvent};
use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface,
PointerAxisEvent as LibinputPointerAxisEvent};
use smithay::backend::session::{Session, SessionNotifier};
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::roles::Role;
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
@ -48,15 +49,15 @@ use smithay::wayland::shm::init_shm_global;
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::Error as IoError;
use std::path::PathBuf;
use std::process::Command;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use std::path::PathBuf;
use std::process::Command;
use xkbcommon::xkb::keysyms as xkb;
use wayland_server::{Display, StateToken, StateProxy};
use wayland_server::{Display, StateProxy, StateToken};
use wayland_server::protocol::{wl_output, wl_pointer};
use xkbcommon::xkb::keysyms as xkb;
struct LibinputInputHandler {
log: Logger,
@ -92,7 +93,8 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
let serial = self.next_serial();
self.keyboard.input(keycode, state, serial, |modifiers, keysym| {
self.keyboard
.input(keycode, state, serial, |modifiers, keysym| {
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
self.running.store(false, Ordering::SeqCst);
false
@ -110,7 +112,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
let mut location = self.pointer_location.borrow_mut();
location.0 += x;
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(
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
serial,
@ -118,7 +122,10 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
);
}
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);
let serial = self.next_serial();
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
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!(),
);
@ -196,7 +205,8 @@ fn main() {
*/
init_shm_global(&mut event_loop, vec![], log.clone());
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
let (compositor_token, _shell_state_token, window_map) =
init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
/*
* Initialize session on the current tty
@ -221,8 +231,11 @@ fn main() {
let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
let bytes = include_bytes!("resources/cursor2.rgba");
let udev_token
= UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl {
let udev_token = UdevBackend::new(
&mut event_loop,
&context,
session.clone(),
UdevHandlerImpl {
compositor_token,
active_egl_context,
backends: HashMap::new(),
@ -232,7 +245,9 @@ fn main() {
pointer_location: pointer_location.clone(),
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
logger: log.clone(),
}, log.clone()).unwrap();
},
log.clone(),
).unwrap();
let udev_session_id = notifier.register(udev_token.clone());
@ -283,7 +298,9 @@ fn main() {
/*
* 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());
libinput_context.udev_assign_seat(&seat).unwrap();
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
@ -337,7 +354,9 @@ struct 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):
let res_handles = device.resource_handles().unwrap();
@ -345,9 +364,7 @@ impl UdevHandlerImpl {
let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors()
.iter()
.map(|conn| {
ConnectorInfo::load_from_device(device, *conn).unwrap()
})
.map(|conn| ConnectorInfo::load_from_device(device, *conn).unwrap())
.filter(|conn| conn.connection_state() == ConnectorState::Connected)
.inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type()))
.collect();
@ -356,16 +373,26 @@ impl UdevHandlerImpl {
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
for connector_info in connector_infos {
let encoder_infos = connector_info.encoders().iter().flat_map(|encoder_handle| 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 crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
if !backends.contains_key(&crtc) {
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
// create a backend
let renderer = GliumDrawer::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
renderer.set_cursor_representation(&self.pointer_image, (2, 2)).unwrap();
renderer
.set_cursor_representation(&self.pointer_image, (2, 2))
.unwrap();
// render first frame
{
@ -386,8 +413,9 @@ impl 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.
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();
@ -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
let mut state = state.into();
let backends = self.backends.get(&state.get(device).device_id()).unwrap();
*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 device = state.get(device);
@ -439,7 +471,10 @@ pub struct 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) {
{
let (x, y) = *self.pointer_location.borrow();
@ -450,9 +485,8 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
// redraw the frame, in a simple but inneficient way
{
let screen_dimensions = drawer.get_framebuffer_dimensions();
self.window_map
.borrow()
.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
self.window_map.borrow().with_windows_from_bottom_to_top(
|toplevel_surface, initial_place| {
if let Some(wl_surface) = toplevel_surface.get_surface() {
// this surface is a root of a subsurface tree that needs to be drawn
self.compositor_token
@ -467,19 +501,21 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
Some(Buffer::Egl { ref images }) => {
match images.format {
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.
attributes.user_data.texture = None;
remove = true;
},
}
};
},
}
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;
@ -500,7 +536,9 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
Buffer::Shm { .. } => false,
},
match *attributes.user_data.buffer.as_ref().unwrap() {
Buffer::Egl { ref images } => (images.width, images.height),
Buffer::Egl { ref images } => {
(images.width, images.height)
}
Buffer::Shm { ref size, .. } => *size,
},
(x, y),
@ -516,7 +554,8 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
)
.unwrap();
}
});
},
);
}
if let Err(err) = frame.finish() {
error!(self.logger, "Error during rendering: {:?}", err);
@ -524,8 +563,7 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
}
}
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>,
error: DrmError) {
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) {
error!(self.logger, "{:?}", error);
}
}

View File

@ -12,7 +12,7 @@ extern crate wayland_server;
mod helpers;
use glium::Surface;
use helpers::{init_shell, GliumDrawer, MyWindowMap, Buffer};
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap};
use slog::{Drain, Logger};
use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
@ -143,7 +143,7 @@ fn main() {
Some(egl_display)
} else {
None
}
},
));
let (w, h) = renderer.get_framebuffer_dimensions();
@ -155,7 +155,8 @@ fn main() {
init_shm_global(&mut event_loop, vec![], log.clone());
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display);
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());
@ -240,19 +241,21 @@ fn main() {
Some(Buffer::Egl { ref images }) => {
match images.format {
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.
attributes.user_data.texture = None;
remove = true;
},
}
};
},
}
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;
@ -280,14 +283,16 @@ fn main() {
glium::Blend {
color: glium::BlendingFunction::Addition {
source: glium::LinearBlendingFactor::One,
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
destination:
glium::LinearBlendingFactor::OneMinusSourceAlpha,
},
alpha: glium::BlendingFunction::Addition {
source: glium::LinearBlendingFactor::One,
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
destination:
glium::LinearBlendingFactor::OneMinusSourceAlpha,
},
..Default::default()
}
},
);
TraversalAction::DoChildren((x, y))
} else {

View File

@ -1,13 +1,14 @@
use super::error::*;
use super::DevPath;
use super::error::*;
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::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::{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 nix::libc::c_void;
use std::cell::Cell;
@ -34,11 +35,8 @@ pub(crate) struct DrmBackendInternal<A: Device + 'static> {
impl<A: Device + 'static> DrmBackend<A> {
pub(crate) fn new(
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>,
crtc: crtc::Handle,
mode: Mode,
connectors: Vec<connector::Handle>,
log: ::slog::Logger,
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>, crtc: crtc::Handle, mode: Mode,
connectors: Vec<connector::Handle>, log: ::slog::Logger,
) -> Result<Self> {
// logger already initialized by the DrmDevice
info!(log, "Initializing DrmBackend");
@ -46,13 +44,13 @@ impl<A: Device + 'static> DrmBackend<A> {
let (w, h) = mode.size();
debug!(log, "Creating Surface");
let surface = context.create_surface(
GbmSurfaceArguments {
let surface = context
.create_surface(GbmSurfaceArguments {
size: (w as u32, h as u32),
format: GbmFormat::XRGB8888,
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
}
).chain_err(|| ErrorKind::GbmInitFailed)?;
})
.chain_err(|| ErrorKind::GbmInitFailed)?;
// make it active for the first `crtc::set`
// (which is needed before the first page_flip)
@ -74,8 +72,12 @@ impl<A: Device + 'static> DrmBackend<A> {
debug!(log, "FrontBuffer color format: {:?}", front_bo.format());
// we need a framebuffer for the front buffer
let fb = framebuffer::create(&*context, &*front_bo)
.chain_err(|| ErrorKind::DrmDev(format!("Error creating framebuffer on {:?}", context.dev_path())))?;
let fb = framebuffer::create(&*context, &*front_bo).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error creating framebuffer on {:?}",
context.dev_path()
))
})?;
debug!(log, "Initialize screen");
crtc::set(
@ -85,14 +87,23 @@ impl<A: Device + 'static> DrmBackend<A> {
&connectors,
(0, 0),
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();
let cursor = Cell::new(context.create_buffer_object(
1, 1,
let cursor = Cell::new(context
.create_buffer_object(
1,
1,
GbmFormat::ARGB8888,
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
).chain_err(|| ErrorKind::GbmInitFailed)?);
)
.chain_err(|| ErrorKind::GbmInitFailed)?);
Ok(DrmBackend {
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)
}
@ -121,8 +131,12 @@ impl<A: Device + 'static> DrmBackend<A> {
///
/// Errors if the new connector does not support the currently set `Mode`
pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> {
let info = connector::Info::load_from_device(&*self.backend.context, connector)
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.backend.context.dev_path())))?;
let info = connector::Info::load_from_device(&*self.backend.context, connector).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error loading connector info on {:?}",
self.backend.context.dev_path()
))
})?;
// check if the connector can handle the current mode
if info.modes().contains(&self.mode) {
@ -130,15 +144,22 @@ impl<A: Device + 'static> DrmBackend<A> {
let encoders = info.encoders()
.iter()
.map(|encoder| {
encoder::Info::load_from_device(&*self.backend.context, *encoder)
.chain_err(|| ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.backend.context.dev_path())))
encoder::Info::load_from_device(&*self.backend.context, *encoder).chain_err(|| {
ErrorKind::DrmDev(format!(
"Error loading encoder info on {:?}",
self.backend.context.dev_path()
))
})
})
.collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc
let resource_handles = self.backend.context
.resource_handles()
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.backend.context.dev_path())))?;
let resource_handles = self.backend.context.resource_handles().chain_err(|| {
ErrorKind::DrmDev(format!(
"Error loading resources on {:?}",
self.backend.context.dev_path()
))
})?;
if !encoders
.iter()
.map(|encoder| encoder.possible_crtcs())
@ -193,7 +214,12 @@ impl<A: Device + 'static> DrmBackend<A> {
// check the connectors
for connector in &self.connectors {
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()
.contains(&mode)
{
@ -206,14 +232,18 @@ impl<A: Device + 'static> DrmBackend<A> {
// Recreate the surface and the related resources to match the new
// resolution.
debug!(self.backend.logger, "Reinitializing surface for new mode: {}:{}", w, h);
let surface = self.backend.context.create_surface(
GbmSurfaceArguments {
debug!(
self.backend.logger,
"Reinitializing surface for new mode: {}:{}", w, h
);
let surface = self.backend
.context
.create_surface(GbmSurfaceArguments {
size: (w as u32, h as u32),
format: GbmFormat::XRGB8888,
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
}
).chain_err(|| ErrorKind::GbmInitFailed)?;
})
.chain_err(|| ErrorKind::GbmInitFailed)?;
// make it active for the first `crtc::set`
// (which is needed before the first page_flip)
@ -231,7 +261,10 @@ impl<A: Device + 'static> DrmBackend<A> {
if let Some(mut old_bo) = self.backend.next_buffer.take() {
if let Ok(Some(fb)) = old_bo.take_userdata() {
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()
.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
let dev_path = self.backend.context.dev_path();
@ -261,13 +298,22 @@ impl<A: Device + 'static> DrmBackend<A> {
&self.connectors,
(0, 0),
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
});
if let Ok(Some(fb)) = old_front_bo.take_userdata() {
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");
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.crtc,
(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(
@ -364,8 +417,7 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
debug!(self.backend.logger, "Importing cursor");
// import the cursor into a buffer we can render
let mut cursor = self
.backend
let mut cursor = self.backend
.context
.create_buffer_object(
w,
@ -389,9 +441,12 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
(hotspot.0 as i32, hotspot.1 as i32),
).is_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())),
)?;
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()
))
})?;
}
// and store it
@ -409,7 +464,10 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
res
} {
// 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);
}
@ -426,7 +484,10 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
// create a framebuffer if the front buffer does not have one already
// (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 {
info
} else {

View File

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

View File

@ -3,23 +3,22 @@
use super::{ffi, EGLSurface, PixelFormat};
use super::error::*;
use super::native;
#[cfg(feature = "backend_drm")]
use gbm::{Device as GbmDevice};
use drm::Device as BasicDevice;
#[cfg(feature = "backend_drm")]
use drm::{Device as BasicDevice};
use drm::control::Device as ControlDevice;
#[cfg(feature = "backend_drm")]
use drm::control::{Device as ControlDevice};
use nix::libc::{c_void, c_int};
use gbm::Device as GbmDevice;
use nix::libc::{c_int, c_void};
use slog;
use std::ffi::{CString, CStr};
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::rc::Rc;
use std::ptr;
use std::mem;
use std::ops::{Deref, DerefMut};
#[cfg(feature = "backend_drm")]
use std::os::unix::io::{AsRawFd, RawFd};
use std::ptr;
use std::rc::Rc;
/// EGL context for rendering
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> {
/// Create a new `EGLContext` from a given `NativeDisplay`
pub fn new<L>(
native: N,
attributes: GlAttributes,
reqs: PixelFormatRequirements,
logger: L
native: N, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L
) -> Result<EGLContext<B, N>>
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 ptr = native.ptr()?;
@ -86,11 +82,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
}
unsafe fn new_internal(
ptr: ffi::NativeDisplayType,
mut attributes: GlAttributes,
reqs: PixelFormatRequirements,
ptr: ffi::NativeDisplayType, mut attributes: GlAttributes, reqs: PixelFormatRequirements,
log: ::slog::Logger,
) -> Result<(
) -> Result<
(
Rc<ffi::egl::types::EGLContext>,
Rc<ffi::egl::types::EGLDisplay>,
ffi::egl::types::EGLConfig,
@ -98,8 +93,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
PixelFormat,
bool,
bool,
)>
{
),
> {
// If no version is given, try OpenGLES 3.0, if available,
// fallback to 2.0 otherwise
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);
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 {
error!(log, "EGL Display is not valid");
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
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();
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,
surface_attributes,
desc,
extensions.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"),
extensions
.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
pub fn create_surface(&self, args: N::Arguments) -> Result<EGLSurface<B::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() {
debug!(self.logger, "EGL surface successfully created");
}

View File

@ -1,6 +1,6 @@
#![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_uint64_t = uint64_t;
@ -37,43 +37,67 @@ pub mod egl {
* Lets do it ourselves...
*/
#[allow(non_snake_case, unused_variables, dead_code)] #[inline]
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]
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]
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]
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]
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)
#[allow(non_snake_case, unused_variables, dead_code)]
#[inline]
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 {
use super::__gl_imports::raw;
use super::FnPtr;
use super::__gl_imports::raw;
pub static mut BindWaylandDisplayWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false
is_loaded: false,
};
pub static mut UnbindWaylandDisplayWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false
is_loaded: false,
};
pub static mut QueryWaylandBufferWL: FnPtr = FnPtr {
f: super::missing_fn_panic as *const raw::c_void,
is_loaded: false
is_loaded: false,
};
}
#[allow(non_snake_case)]
pub mod BindWaylandDisplayWL {
use super::{wayland_storage, metaloadfn};
use super::__gl_imports::raw;
use super::{metaloadfn, wayland_storage};
use super::FnPtr;
use super::__gl_imports::raw;
#[inline]
#[allow(dead_code)]
@ -82,18 +106,22 @@ pub mod egl {
}
#[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 {
wayland_storage::BindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
wayland_storage::BindWaylandDisplayWL =
FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
}
}
}
#[allow(non_snake_case)]
pub mod UnbindWaylandDisplayWL {
use super::{wayland_storage, metaloadfn};
use super::__gl_imports::raw;
use super::{metaloadfn, wayland_storage};
use super::FnPtr;
use super::__gl_imports::raw;
#[inline]
#[allow(dead_code)]
@ -102,18 +130,22 @@ pub mod egl {
}
#[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 {
wayland_storage::UnbindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
wayland_storage::UnbindWaylandDisplayWL =
FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
}
}
}
#[allow(non_snake_case)]
pub mod QueryWaylandBufferWL {
use super::{wayland_storage, metaloadfn};
use super::__gl_imports::raw;
use super::{metaloadfn, wayland_storage};
use super::FnPtr;
use super::__gl_imports::raw;
#[inline]
#[allow(dead_code)]
@ -122,9 +154,13 @@ pub mod egl {
}
#[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 {
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 use self::surface::EGLSurface;
pub mod wayland;
pub use self::wayland::{EGLWaylandExtensions, EGLImages, BufferAccessError};
pub use self::wayland::{BufferAccessError, EGLImages, EGLWaylandExtensions};
/// Error that can happen when swapping buffers.
#[derive(Debug, Clone, PartialEq)]
@ -73,8 +73,12 @@ pub struct EglExtensionNotSupportedError(&'static [&'static str]);
impl fmt::Display for EglExtensionNotSupportedError {
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,
at least one is required: {:?}", self.0)
write!(
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
use super::ffi;
use super::error::*;
use super::ffi;
#[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")]
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")]
use std::marker::PhantomData;
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
use std::ptr;
#[cfg(feature = "backend_drm")]
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")]
use winit::Window as WinitWindow;
#[cfg(feature = "backend_winit")]
use winit::os::unix::WindowExt;
#[cfg(feature = "backend_winit")]
use wayland_client::egl as wegl;
/// Trait for typed backend variants (X11/Wayland/GBM)
pub trait Backend {
@ -32,9 +31,7 @@ pub trait Backend {
/// The returned `EGLDisplay` needs to be a valid ptr for egl,
/// but there is no way to test that.
unsafe fn get_display<F: Fn(&str) -> bool>(
display: ffi::NativeDisplayType,
has_dp_extension: F,
log: ::slog::Logger,
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay;
}
@ -45,24 +42,28 @@ pub enum Wayland {}
impl Backend for Wayland {
type Surface = wegl::WlEglSurface;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
-> ffi::egl::types::EGLDisplay
unsafe fn get_display<F>(
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where
F: Fn(&str) -> bool
F: Fn(&str) -> bool,
{
if has_dp_extension("EGL_KHR_platform_wayland")
&& ffi::egl::GetPlatformDisplay::is_loaded()
{
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(
log,
"EGL Display Initialization via EGL_KHR_platform_wayland"
);
ffi::egl::GetPlatformDisplay(
ffi::egl::PLATFORM_WAYLAND_KHR,
display as *mut _,
ptr::null(),
)
} else if has_dp_extension("EGL_EXT_platform_wayland")
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
} else if has_dp_extension("EGL_EXT_platform_wayland") && 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::PLATFORM_WAYLAND_EXT,
display as *mut _,
@ -85,19 +86,16 @@ pub enum X11 {}
impl Backend for X11 {
type Surface = XlibWindow;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
-> ffi::egl::types::EGLDisplay
unsafe fn get_display<F>(
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where
F: Fn(&str) -> bool
{
if has_dp_extension("EGL_KHR_platform_x11")
&& ffi::egl::GetPlatformDisplay::is_loaded()
F: Fn(&str) -> bool,
{
if has_dp_extension("EGL_KHR_platform_x11") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_EXT_platform_x11")
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
{
} else if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
} else {
@ -115,24 +113,19 @@ pub struct Gbm<T: 'static> {
impl<T: 'static> Backend for Gbm<T> {
type Surface = GbmSurface<T>;
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
-> ffi::egl::types::EGLDisplay
unsafe fn get_display<F>(
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
) -> ffi::egl::types::EGLDisplay
where
F: Fn(&str) -> bool
{
if has_dp_extension("EGL_KHR_platform_gbm")
&& ffi::egl::GetPlatformDisplay::is_loaded()
F: Fn(&str) -> bool,
{
if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_MESA_platform_gbm")
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
{
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
} else if has_dp_extension("EGL_MESA_platform_gbm")
&& ffi::egl::GetPlatformDisplay::is_loaded()
{
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
} else {
@ -224,7 +217,9 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
type Arguments = GbmSurfaceArguments;
type Error = DrmError;
fn is_backend(&self) -> bool { true }
fn is_backend(&self) -> bool {
true
}
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
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>> {
use backend::drm::error::ResultExt as DrmResultExt;
DrmResultExt::chain_err(GbmDevice::create_surface(
self,
args.size.0,
args.size.1,
args.format,
args.flags,
), || DrmErrorKind::GbmInitFailed)
DrmResultExt::chain_err(
GbmDevice::create_surface(self, args.size.0, args.size.1, args.format, args.flags),
|| DrmErrorKind::GbmInitFailed,
)
}
}
@ -255,15 +247,21 @@ pub unsafe trait NativeSurface {
#[cfg(feature = "backend_winit")]
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")]
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")]
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::ffi;
use super::native;
use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak};
@ -30,9 +29,8 @@ impl<N: native::NativeSurface> DerefMut for EGLSurface<N> {
}
impl<N: native::NativeSurface> EGLSurface<N> {
pub(crate) fn new<B: native::Backend<Surface=N>, D: native::NativeDisplay<B>>(
context: &EGLContext<B, D>,
native: N,
pub(crate) fn new<B: native::Backend<Surface = N>, D: native::NativeDisplay<B>>(
context: &EGLContext<B, D>, native: N
) -> Result<EGLSurface<N>> {
let surface = unsafe {
ffi::egl::CreateWindowSurface(
@ -58,9 +56,7 @@ impl<N: native::NativeSurface> EGLSurface<N> {
/// Swaps buffers at the end of a frame.
pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
if let Some(display) = self.display.upgrade() {
let ret = unsafe {
ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _)
};
let ret = unsafe { ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _) };
if ret == 0 {
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`
//! 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::ffi::egl::types::EGLImage;
use nix::libc::{c_uint};
use std::rc::{Rc, Weak};
use nix::libc::c_uint;
use std::fmt;
use std::rc::{Rc, Weak};
use wayland_server::{Display, Resource};
use wayland_server::protocol::wl_buffer::WlBuffer;
use wayland_sys::server::wl_display;
@ -37,7 +37,9 @@ impl fmt::Debug for BufferAccessError {
match *self {
BufferAccessError::ContextLost => write!(formatter, "BufferAccessError::ContextLost"),
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),
}
}
@ -45,9 +47,11 @@ impl fmt::Debug for BufferAccessError {
impl fmt::Display for BufferAccessError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
use ::std::error::Error;
use std::error::Error;
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),
}
}
@ -102,11 +106,16 @@ pub enum TextureCreationError {
impl fmt::Display for TextureCreationError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
use ::std::error::Error;
use std::error::Error;
match *self {
TextureCreationError::ContextLost => 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
///
/// 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() {
let mut old_tex_id: i32 = 0;
ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_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 {
ffi::egl::SUCCESS => Ok(()),
err => Err(TextureCreationError::TextureBindingFailed(err)),
@ -204,7 +220,9 @@ impl Drop for EGLImages {
fn drop(&mut self) {
if let Some(display) = self.display.upgrade() {
for image in self.images.drain(..) {
unsafe { ffi::egl::DestroyImageKHR(*display, image); }
unsafe {
ffi::egl::DestroyImageKHR(*display, image);
}
}
}
self.buffer.release();
@ -236,7 +254,9 @@ pub trait EGLWaylandExtensions {
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
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)
}
@ -245,10 +265,19 @@ impl EGLDisplay {
/// In case the buffer is not managed by egl (but e.g. the wayland::shm module)
/// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer
/// to render it another way.
pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> {
pub fn egl_buffer_contents(
&self, buffer: WlBuffer
) -> ::std::result::Result<EGLImages, BufferAccessError> {
if let Some(display) = self.0.upgrade() {
let mut format: i32 = 0;
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));
}
let format = match format {
@ -262,17 +291,38 @@ impl EGLDisplay {
};
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));
}
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));
}
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;
}
@ -284,14 +334,15 @@ impl EGLDisplay {
out.push(ffi::egl::NONE as i32);
images.push({
let image =
unsafe { ffi::egl::CreateImageKHR(
let image = unsafe {
ffi::egl::CreateImageKHR(
*display,
ffi::egl::NO_CONTEXT,
ffi::egl::WAYLAND_BUFFER_WL,
buffer.ptr() as *mut _,
out.as_ptr(),
) };
)
};
if image == ffi::egl::NO_IMAGE_KHR {
return Err(BufferAccessError::EGLImageCreationFailed);
} else {
@ -319,14 +370,15 @@ impl Drop for EGLDisplay {
fn drop(&mut self) {
if let Some(display) = self.0.upgrade() {
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> {
(**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> {
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
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 {
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));

View File

@ -1,8 +1,8 @@
//! Glium compatibility module
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::wayland::{EGLDisplay, EGLWaylandExtensions};
use glium::Frame;
use glium::SwapBuffersError as GliumSwapBuffersError;
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> {
(*self.backend).0.bind_wl_display(display)
}
}
unsafe impl<T: EGLGraphicsBackend> Backend for InternalBackend<T> {
fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> {
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
//! backend.
use drm::Device as BasicDevice;
use drm::control::Device as ControlDevice;
use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
use backend::session::{Session, SessionObserver};
use drm::Device as BasicDevice;
use drm::control::Device as ControlDevice;
use nix::fcntl;
use nix::sys::stat::dev_t;
use std::collections::HashMap;
@ -59,11 +59,8 @@ pub struct UdevBackend<
logger: ::slog::Logger,
}
impl<
H: DrmHandler<SessionFdDrmDevice> + 'static,
S: Session + 'static,
T: UdevHandler<H> + 'static,
> UdevBackend<H, S, T> {
impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevHandler<H> + 'static>
UdevBackend<H, S, T> {
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
///
/// ## Arguments
@ -244,7 +241,12 @@ where
) {
Ok(fd) => SessionFdDrmDevice(fd),
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;
}
}
@ -355,16 +357,16 @@ where
}
/// 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.
///
/// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device.
///
/// ## Panics
/// 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>)
-> Option<H>;
fn device_added<'a, S: Into<StateProxy<'a>>>(
&mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>
) -> Option<H>;
/// Called when an open device is changed.
///
/// 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 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.
///
/// 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 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.
///
/// ## Panics

View File

@ -1,12 +1,12 @@
//! Implementation of backend traits for types provided by `winit`
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::Result as EGLResult;
use backend::graphics::egl::native;
use backend::graphics::egl::context::GlAttributes;
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
@ -16,10 +16,10 @@ use std::cmp;
use std::error;
use std::fmt;
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_server::Display;
use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor,
MouseScrollDelta, Touch, TouchPhase, Window as WinitWindow, WindowBuilder, WindowEvent};
error_chain! {
errors {
@ -139,32 +139,18 @@ where
let reqs = Default::default();
let window = Rc::new(
if native::NativeDisplay::<native::Wayland>::is_backend(&winit_window) {
let context = EGLContext::<native::Wayland, WinitWindow>::new(
winit_window,
attributes,
reqs,
log.clone(),
)?;
let context =
EGLContext::<native::Wayland, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
let surface = context.create_surface(())?;
Window::Wayland {
context,
surface
}
Window::Wayland { context, surface }
} else if native::NativeDisplay::<native::X11>::is_backend(&winit_window) {
let context = EGLContext::<native::X11, WinitWindow>::new(
winit_window,
attributes,
reqs,
log.clone(),
)?;
let context =
EGLContext::<native::X11, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
let surface = context.create_surface(())?;
Window::X11 {
context,
surface
}
Window::X11 { context, surface }
} else {
bail!(ErrorKind::NotSupported);
}
},
);
Ok((
@ -237,8 +223,14 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
fn is_current(&self) -> bool {
match *self.window {
Window::Wayland { ref context, ref surface } => context.is_current() && surface.is_current(),
Window::X11 { ref context, ref surface } => context.is_current() && surface.is_current(),
Window::Wayland {
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));
window.window().set_inner_size(x, y);
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 {
ShellClientKind::Wl(ref shell) => {
let mutex =
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap();
if guard.0.pending_ping == 0 {
return Err(());
@ -487,8 +486,7 @@ impl<SD> ShellClient<SD> {
}
match self.kind {
ShellClientKind::Wl(ref shell) => {
let mutex =
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap();
Ok(f(&mut guard.0.data))
}

View File

@ -271,8 +271,7 @@ where
{
wl_shell_surface::Implementation {
pong: |evlh, idata, _, shell_surface, serial| {
let &(_, ref shell) =
unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
let &(_, ref shell) = unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
let valid = {
let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) };
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();
surface.set_user_data(::std::ptr::null_mut());
// drop the state
let data = unsafe {
Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6))
};
let data =
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
::std::mem::drop(data);
}
@ -544,9 +543,8 @@ where
with_surface_toplevel_data(idata, toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_ptr = toplevel_surface_parent.get_user_data();
let &(ref parent_surface, _) = unsafe {
&*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6))
};
let &(ref parent_surface, _) =
unsafe { &*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6)) };
unsafe { parent_surface.clone_unchecked() }
})
});

View File

@ -43,6 +43,8 @@ containers:
- !Container base
- !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
- !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:
update-stable: !Command