Use new rustfmt-preview
This commit is contained in:
parent
25c1e30fb3
commit
66c011c942
|
@ -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")
|
||||
|
|
4
build.rs
4
build.rs
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
.create_backend(crtc, mode, vec![connector_info.handle()])
|
||||
.unwrap());
|
||||
let renderer = GliumDrawer::from(
|
||||
device
|
||||
.create_backend(crtc, mode, vec![connector_info.handle()])
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,10 +177,10 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
|||
&glium::DrawParameters {
|
||||
blend: blending,
|
||||
..Default::default()
|
||||
}
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn draw(&self) -> Frame {
|
||||
|
|
|
@ -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
|
||||
|
@ -34,25 +35,24 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
|
|||
Some(Some((buffer, (_x, _y)))) => {
|
||||
// we ignore hotspot coordinates in this simple example
|
||||
match if let Some(display) = display.borrow().as_ref() {
|
||||
display.egl_buffer_contents(buffer)
|
||||
} else {
|
||||
Err(BufferAccessError::NotManaged(buffer))
|
||||
}
|
||||
{
|
||||
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 {
|
||||
size: (10, 10),
|
||||
position: (10, 10),
|
||||
serial: 42,
|
||||
}
|
||||
new_popup: |_, _, _| PopupConfigure {
|
||||
size: (10, 10),
|
||||
position: (10, 10),
|
||||
serial: 42,
|
||||
},
|
||||
move_: |_, _, _, _, _| {},
|
||||
resize: |_, _, _, _, _, _| {},
|
||||
grab: |_, _, _, _, _| {},
|
||||
change_display_state: |_, _, _, _, _, _, _| {
|
||||
ToplevelConfigure {
|
||||
size: None,
|
||||
states: vec![],
|
||||
serial: 42,
|
||||
}
|
||||
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>>>)
|
||||
-> (
|
||||
CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
||||
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
|
||||
Rc<RefCell<MyWindowMap>>,
|
||||
) {
|
||||
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(
|
||||
|
|
|
@ -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,27 +34,29 @@ 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) {
|
||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||
x += subdata.x;
|
||||
y += subdata.y;
|
||||
}
|
||||
let my_rect = Rectangle {
|
||||
x,
|
||||
y,
|
||||
width: w,
|
||||
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))
|
||||
});
|
||||
TraversalAction::Break
|
||||
|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;
|
||||
}
|
||||
let my_rect = Rectangle {
|
||||
x,
|
||||
y,
|
||||
width: w,
|
||||
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)));
|
||||
TraversalAction::Break
|
||||
} else {
|
||||
TraversalAction::DoChildren((x, y))
|
||||
}
|
||||
} else {
|
||||
TraversalAction::DoChildren((x, y))
|
||||
TraversalAction::SkipChildren
|
||||
}
|
||||
} 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) {
|
||||
|
|
268
examples/udev.rs
268
examples/udev.rs
|
@ -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,17 +93,18 @@ 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| {
|
||||
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
|
||||
self.running.store(false, Ordering::SeqCst);
|
||||
false
|
||||
} else if modifiers.logo && keysym == xkb::KEY_Return && state == KeyState::Pressed {
|
||||
let _ = Command::new("weston-terminal").spawn();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
self.keyboard
|
||||
.input(keycode, state, serial, |modifiers, keysym| {
|
||||
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
|
||||
self.running.store(false, Ordering::SeqCst);
|
||||
false
|
||||
} else if modifiers.logo && keysym == xkb::KEY_Return && state == KeyState::Pressed {
|
||||
let _ = Command::new("weston-terminal").spawn();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
}
|
||||
fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) {
|
||||
let (x, y) = (evt.dx(), evt.dy());
|
||||
|
@ -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());
|
||||
// create a backend
|
||||
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,73 +485,77 @@ 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| {
|
||||
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
|
||||
.with_surface_tree_upward(
|
||||
wl_surface,
|
||||
initial_place,
|
||||
|_surface, attributes, role, &(mut x, mut y)| {
|
||||
// there is actually something to draw !
|
||||
if attributes.user_data.texture.is_none() {
|
||||
let mut remove = false;
|
||||
match attributes.user_data.buffer {
|
||||
Some(Buffer::Egl { ref images }) => {
|
||||
match images.format {
|
||||
Format::RGB | Format::RGBA => {
|
||||
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));
|
||||
},
|
||||
_ => {},
|
||||
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
|
||||
.with_surface_tree_upward(
|
||||
wl_surface,
|
||||
initial_place,
|
||||
|_surface, attributes, role, &(mut x, mut y)| {
|
||||
// there is actually something to draw !
|
||||
if attributes.user_data.texture.is_none() {
|
||||
let mut remove = false;
|
||||
match attributes.user_data.buffer {
|
||||
Some(Buffer::Egl { ref images }) => {
|
||||
match images.format {
|
||||
Format::RGB | Format::RGBA => {
|
||||
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));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
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 Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||
x += subdata.x;
|
||||
y += subdata.y;
|
||||
if let Some(ref texture) = attributes.user_data.texture {
|
||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||
x += subdata.x;
|
||||
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,
|
||||
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();
|
||||
}
|
||||
});
|
||||
},
|
||||
)
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,36 +44,40 @@ 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)
|
||||
unsafe {
|
||||
surface
|
||||
.make_current()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?
|
||||
.make_current()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?
|
||||
};
|
||||
surface
|
||||
.swap_buffers()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
.swap_buffers()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
|
||||
// init the first screen
|
||||
// (must be done before calling page_flip for the first time)
|
||||
let mut front_bo = surface
|
||||
.lock_front_buffer()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
.lock_front_buffer()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
|
||||
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,
|
||||
GbmFormat::ARGB8888,
|
||||
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
||||
).chain_err(|| ErrorKind::GbmInitFailed)?);
|
||||
let cursor = Cell::new(context
|
||||
.create_buffer_object(
|
||||
1,
|
||||
1,
|
||||
GbmFormat::ARGB8888,
|
||||
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
||||
)
|
||||
.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,32 +232,39 @@ 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)
|
||||
unsafe {
|
||||
surface
|
||||
.make_current()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?
|
||||
.make_current()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?
|
||||
};
|
||||
surface
|
||||
.swap_buffers()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
.swap_buffers()
|
||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||
|
||||
// Clean up next_buffer
|
||||
{
|
||||
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,20 +417,19 @@ 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
|
||||
.context
|
||||
.create_buffer_object(
|
||||
w,
|
||||
h,
|
||||
GbmFormat::ARGB8888,
|
||||
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
||||
)
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||
let mut cursor = self.backend
|
||||
.context
|
||||
.create_buffer_object(
|
||||
w,
|
||||
h,
|
||||
GbmFormat::ARGB8888,
|
||||
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
||||
)
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||
cursor
|
||||
.write(&**buffer)
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||
.write(&**buffer)
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?
|
||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||
|
||||
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),
|
||||
).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);
|
||||
}
|
||||
|
||||
|
@ -421,17 +479,20 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
|
|||
// neither weston, wlc or wlroots bother with that as well.
|
||||
// so we just assume we got at least two buffers to do flipping.
|
||||
let mut next_bo = self.surface
|
||||
.lock_front_buffer()
|
||||
.expect("Surface only has one front buffer. Not supported by smithay");
|
||||
.lock_front_buffer()
|
||||
.expect("Surface only has one front buffer. Not supported by smithay");
|
||||
|
||||
// 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 {
|
||||
let fb = framebuffer::create(&*self.backend.context, &*next_bo)
|
||||
.map_err(|_| SwapBuffersError::ContextLost)?;
|
||||
.map_err(|_| SwapBuffersError::ContextLost)?;
|
||||
next_bo.set_userdata(fb).unwrap();
|
||||
fb
|
||||
};
|
||||
|
|
|
@ -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,10 +388,12 @@ 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
|
||||
if !con_info.modes().contains(&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);
|
||||
}
|
||||
|
@ -569,9 +589,9 @@ where
|
|||
};
|
||||
},
|
||||
error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| {
|
||||
let mut dev = evlh.state().get_mut(dev_token);
|
||||
warn!(dev.logger, "DrmDevice errored: {}", error);
|
||||
handler.error(&mut dev, error.into());
|
||||
let mut dev = evlh.state().get_mut(dev_token);
|
||||
warn!(dev.logger, "DrmDevice errored: {}", error);
|
||||
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) {
|
||||
error!(
|
||||
device.logger,
|
||||
"Failed to activate crtc ({:?}) again. Error: {}",
|
||||
crtc,
|
||||
err
|
||||
"Failed to activate crtc ({:?}) again. Error: {}", crtc, err
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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", &[]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
F: Fn(&str) -> bool,
|
||||
{
|
||||
if has_dp_extension("EGL_KHR_platform_x11")
|
||||
&& ffi::egl::GetPlatformDisplay::is_loaded()
|
||||
{
|
||||
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
|
||||
F: Fn(&str) -> bool,
|
||||
{
|
||||
if has_dp_extension("EGL_KHR_platform_gbm")
|
||||
&& ffi::egl::GetPlatformDisplay::is_loaded()
|
||||
{
|
||||
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 _
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -281,17 +331,18 @@ impl EGLDisplay {
|
|||
let mut out = Vec::with_capacity(3);
|
||||
out.push(ffi::egl::WAYLAND_PLANE_WL as i32);
|
||||
out.push(i as i32);
|
||||
out.push(ffi::egl::NONE as i32);
|
||||
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(),
|
||||
) };
|
||||
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"]));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
(
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() }
|
||||
})
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue