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
|
vagga cargo-$TRAVIS_RUST_VERSION doc --no-deps
|
||||||
;;
|
;;
|
||||||
"cargo-fmt")
|
"cargo-fmt")
|
||||||
vagga cargo-$TRAVIS_RUST_VERSION install -f rustfmt-nightly &&
|
|
||||||
vagga cargo-$TRAVIS_RUST_VERSION fmt -- --write-mode=diff
|
vagga cargo-$TRAVIS_RUST_VERSION fmt -- --write-mode=diff
|
||||||
;;
|
;;
|
||||||
"cargo-clippy")
|
"cargo-clippy")
|
||||||
|
|
4
build.rs
4
build.rs
|
@ -40,9 +40,7 @@ fn main() {
|
||||||
(3, 2),
|
(3, 2),
|
||||||
Profile::Compatibility,
|
Profile::Compatibility,
|
||||||
Fallbacks::None,
|
Fallbacks::None,
|
||||||
[
|
["GL_OES_EGL_image"],
|
||||||
"GL_OES_EGL_image",
|
|
||||||
],
|
|
||||||
).write_bindings(gl_generator::GlobalGenerator, &mut file)
|
).write_bindings(gl_generator::GlobalGenerator, &mut file)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,18 @@ use drm::control::crtc;
|
||||||
use drm::control::encoder::Info as EncoderInfo;
|
use drm::control::encoder::Info as EncoderInfo;
|
||||||
use drm::result::Error as DrmError;
|
use drm::result::Error as DrmError;
|
||||||
use glium::{Blend, Surface};
|
use glium::{Blend, Surface};
|
||||||
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData, Buffer};
|
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
|
||||||
use slog::{Drain, Logger};
|
use slog::{Drain, Logger};
|
||||||
use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
|
use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::wayland::{Format, EGLDisplay, EGLWaylandExtensions};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format};
|
||||||
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::shm::init_shm_global;
|
use smithay::wayland::shm::init_shm_global;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::os::unix::io::RawFd;
|
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::os::unix::io::RawFd;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -64,8 +64,10 @@ fn main() {
|
||||||
let mut options = OpenOptions::new();
|
let mut options = OpenOptions::new();
|
||||||
options.read(true);
|
options.read(true);
|
||||||
options.write(true);
|
options.write(true);
|
||||||
let mut device =
|
let mut device = DrmDevice::new(
|
||||||
DrmDevice::new(Card(options.clone().open("/dev/dri/card0").unwrap()), log.clone()).unwrap();
|
Card(options.clone().open("/dev/dri/card0").unwrap()),
|
||||||
|
log.clone(),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
// Get a set of all modesetting resource handles (excluding planes):
|
// Get a set of all modesetting resource handles (excluding planes):
|
||||||
let res_handles = device.resource_handles().unwrap();
|
let res_handles = device.resource_handles().unwrap();
|
||||||
|
@ -74,9 +76,7 @@ fn main() {
|
||||||
let connector_info = res_handles
|
let connector_info = res_handles
|
||||||
.connectors()
|
.connectors()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|conn| {
|
.map(|conn| ConnectorInfo::load_from_device(&device, *conn).unwrap())
|
||||||
ConnectorInfo::load_from_device(&device, *conn).unwrap()
|
|
||||||
})
|
|
||||||
.find(|conn| conn.connection_state() == ConnectorState::Connected)
|
.find(|conn| conn.connection_state() == ConnectorState::Connected)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -96,9 +96,11 @@ fn main() {
|
||||||
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
||||||
|
|
||||||
// Initialize the hardware backend
|
// Initialize the hardware backend
|
||||||
let renderer = GliumDrawer::from(device
|
let renderer = GliumDrawer::from(
|
||||||
|
device
|
||||||
.create_backend(crtc, mode, vec![connector_info.handle()])
|
.create_backend(crtc, mode, vec![connector_info.handle()])
|
||||||
.unwrap());
|
.unwrap(),
|
||||||
|
);
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Initialize glium
|
* Initialize glium
|
||||||
|
@ -114,7 +116,7 @@ fn main() {
|
||||||
Some(egl_display)
|
Some(egl_display)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -123,7 +125,8 @@ fn main() {
|
||||||
|
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(&mut event_loop, vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display.clone());
|
let (compositor_token, _shell_state_token, window_map) =
|
||||||
|
init_shell(&mut event_loop, log.clone(), egl_display.clone());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a listening socket:
|
* Add a listening socket:
|
||||||
|
@ -162,7 +165,9 @@ pub struct DrmHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrmHandler<Card> for DrmHandlerImpl {
|
impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
fn ready(&mut self, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle, _frame: u32, _duration: Duration) {
|
fn ready(
|
||||||
|
&mut self, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle, _frame: u32, _duration: Duration
|
||||||
|
) {
|
||||||
let mut frame = self.drawer.draw();
|
let mut frame = self.drawer.draw();
|
||||||
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
||||||
// redraw the frame, in a simple but inneficient way
|
// redraw the frame, in a simple but inneficient way
|
||||||
|
@ -185,19 +190,21 @@ impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
Some(Buffer::Egl { ref images }) => {
|
Some(Buffer::Egl { ref images }) => {
|
||||||
match images.format {
|
match images.format {
|
||||||
Format::RGB | Format::RGBA => {
|
Format::RGB | Format::RGBA => {
|
||||||
attributes.user_data.texture = self.drawer.texture_from_egl(&images);
|
attributes.user_data.texture =
|
||||||
},
|
self.drawer.texture_from_egl(&images);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// we don't handle the more complex formats here.
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
remove = true;
|
remove = true;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
Some(Buffer::Shm { ref data, ref size }) => {
|
Some(Buffer::Shm { ref data, ref size }) => {
|
||||||
attributes.user_data.texture = Some(self.drawer.texture_from_mem(data, *size));
|
attributes.user_data.texture =
|
||||||
},
|
Some(self.drawer.texture_from_mem(data, *size));
|
||||||
_ => {},
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
if remove {
|
if remove {
|
||||||
attributes.user_data.buffer = None;
|
attributes.user_data.buffer = None;
|
||||||
|
@ -239,8 +246,7 @@ impl DrmHandler<Card> for DrmHandlerImpl {
|
||||||
frame.finish().unwrap();
|
frame.finish().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, _device: &mut DrmDevice<Card>,
|
fn error(&mut self, _device: &mut DrmDevice<Card>, error: DrmError) {
|
||||||
error: DrmError) {
|
|
||||||
panic!("{:?}", error);
|
panic!("{:?}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use glium;
|
use glium;
|
||||||
use glium::{Frame, Surface, GlObject};
|
use glium::{Frame, GlObject, Surface};
|
||||||
use glium::index::PrimitiveType;
|
use glium::index::PrimitiveType;
|
||||||
use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d};
|
use glium::texture::{MipmapsOption, Texture2d, UncompressedFloatFormat};
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::error::Result as EGLResult;
|
use smithay::backend::graphics::egl::error::Result as EGLResult;
|
||||||
use smithay::backend::graphics::egl::wayland::{Format, EGLImages, EGLDisplay, EGLWaylandExtensions};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format};
|
||||||
use smithay::backend::graphics::glium::GliumGraphicsBackend;
|
use smithay::backend::graphics::glium::GliumGraphicsBackend;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
@ -120,9 +120,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
Texture2d::new(&self.display, image).unwrap()
|
Texture2d::new(&self.display, image).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture_from_egl(&self, images: &EGLImages)
|
pub fn texture_from_egl(&self, images: &EGLImages) -> Option<Texture2d> {
|
||||||
-> Option<Texture2d>
|
|
||||||
{
|
|
||||||
let format = match images.format {
|
let format = match images.format {
|
||||||
Format::RGB => UncompressedFloatFormat::U8U8U8,
|
Format::RGB => UncompressedFloatFormat::U8U8U8,
|
||||||
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
|
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
|
||||||
|
@ -136,15 +134,19 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
images.width,
|
images.width,
|
||||||
images.height,
|
images.height,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
unsafe { images.bind_to_texture(0, opengl_texture.get_id()).expect("Failed to bind to texture"); }
|
unsafe {
|
||||||
|
images
|
||||||
|
.bind_to_texture(0, opengl_texture.get_id())
|
||||||
|
.expect("Failed to bind to texture");
|
||||||
|
}
|
||||||
Some(opengl_texture)
|
Some(opengl_texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_texture(&self, target: &mut glium::Frame, texture: &Texture2d,
|
pub fn render_texture(
|
||||||
y_inverted: bool, surface_dimensions: (u32, u32),
|
&self, target: &mut glium::Frame, texture: &Texture2d, y_inverted: bool,
|
||||||
surface_location: (i32, i32), screen_size: (u32, u32),
|
surface_dimensions: (u32, u32), surface_location: (i32, i32), screen_size: (u32, u32),
|
||||||
blending: glium::Blend)
|
blending: glium::Blend,
|
||||||
{
|
) {
|
||||||
let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
|
let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
|
||||||
let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32);
|
let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32);
|
||||||
|
|
||||||
|
@ -175,7 +177,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
&glium::DrawParameters {
|
&glium::DrawParameters {
|
||||||
blend: blending,
|
blend: blending,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::WindowMap;
|
use super::WindowMap;
|
||||||
use smithay::backend::graphics::egl::wayland::{Format, BufferAccessError};
|
|
||||||
use glium::texture::Texture2d;
|
use glium::texture::Texture2d;
|
||||||
use rand;
|
use rand;
|
||||||
|
use smithay::backend::graphics::egl::wayland::{BufferAccessError, Format};
|
||||||
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages};
|
||||||
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
|
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
|
||||||
SurfaceUserImplementation};
|
SurfaceUserImplementation};
|
||||||
|
@ -25,7 +25,8 @@ pub enum Buffer {
|
||||||
Shm { data: Vec<u8>, size: (u32, u32) },
|
Shm { data: Vec<u8>, size: (u32, u32) },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>> {
|
pub fn surface_implementation(
|
||||||
|
) -> SurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>> {
|
||||||
SurfaceUserImplementation {
|
SurfaceUserImplementation {
|
||||||
commit: |_, display, surface, token| {
|
commit: |_, display, surface, token| {
|
||||||
// we retrieve the contents of the associated buffer and copy it
|
// we retrieve the contents of the associated buffer and copy it
|
||||||
|
@ -37,22 +38,21 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
|
||||||
display.egl_buffer_contents(buffer)
|
display.egl_buffer_contents(buffer)
|
||||||
} else {
|
} else {
|
||||||
Err(BufferAccessError::NotManaged(buffer))
|
Err(BufferAccessError::NotManaged(buffer))
|
||||||
}
|
} {
|
||||||
{
|
|
||||||
Ok(images) => {
|
Ok(images) => {
|
||||||
match images.format {
|
match images.format {
|
||||||
Format::RGB => {},
|
Format::RGB => {}
|
||||||
Format::RGBA => {},
|
Format::RGBA => {}
|
||||||
_ => {
|
_ => {
|
||||||
// we don't handle the more complex formats here.
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.buffer = None;
|
attributes.user_data.buffer = None;
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
attributes.user_data.buffer = Some(Buffer::Egl { images });
|
attributes.user_data.buffer = Some(Buffer::Egl { images });
|
||||||
},
|
}
|
||||||
Err(BufferAccessError::NotManaged(buffer)) => {
|
Err(BufferAccessError::NotManaged(buffer)) => {
|
||||||
shm_buffer_contents(&buffer, |slice, data| {
|
shm_buffer_contents(&buffer, |slice, data| {
|
||||||
let offset = data.offset as usize;
|
let offset = data.offset as usize;
|
||||||
|
@ -68,7 +68,7 @@ pub fn surface_implementation() -> SurfaceUserImplementation<SurfaceData, Roles,
|
||||||
attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) });
|
attributes.user_data.buffer = Some(Buffer::Shm { data: new_vec, size: (data.width as u32, data.height as u32) });
|
||||||
}).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!");
|
}).expect("Got EGL buffer with no set EGLDisplay. You need to unbind your EGLContexts before dropping them!");
|
||||||
buffer.release();
|
buffer.release();
|
||||||
},
|
}
|
||||||
Err(err) => panic!("EGL error: {}", err),
|
Err(err) => panic!("EGL error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,8 @@ pub struct ShellIData<F> {
|
||||||
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, (), F>>>,
|
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, (), F>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shell_implementation<F>() -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ShellIData<F>, ()>
|
pub fn shell_implementation<F>(
|
||||||
|
) -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ShellIData<F>, ()>
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
||||||
{
|
{
|
||||||
|
@ -113,22 +114,18 @@ where
|
||||||
serial: 42,
|
serial: 42,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new_popup: |_, _, _| {
|
new_popup: |_, _, _| PopupConfigure {
|
||||||
PopupConfigure {
|
|
||||||
size: (10, 10),
|
size: (10, 10),
|
||||||
position: (10, 10),
|
position: (10, 10),
|
||||||
serial: 42,
|
serial: 42,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
move_: |_, _, _, _, _| {},
|
move_: |_, _, _, _, _| {},
|
||||||
resize: |_, _, _, _, _, _| {},
|
resize: |_, _, _, _, _, _| {},
|
||||||
grab: |_, _, _, _, _| {},
|
grab: |_, _, _, _, _| {},
|
||||||
change_display_state: |_, _, _, _, _, _, _| {
|
change_display_state: |_, _, _, _, _, _, _| ToplevelConfigure {
|
||||||
ToplevelConfigure {
|
|
||||||
size: None,
|
size: None,
|
||||||
states: vec![],
|
states: vec![],
|
||||||
serial: 42,
|
serial: 42,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
show_window_menu: |_, _, _, _, _, _, _| {},
|
show_window_menu: |_, _, _, _, _, _, _| {},
|
||||||
}
|
}
|
||||||
|
@ -155,8 +152,8 @@ pub type MyWindowMap = WindowMap<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub fn init_shell(
|
pub fn init_shell(
|
||||||
evl: &mut EventLoop, log: ::slog::Logger, data: Rc<RefCell<Option<EGLDisplay>>>)
|
evl: &mut EventLoop, log: ::slog::Logger, data: Rc<RefCell<Option<EGLDisplay>>>
|
||||||
-> (
|
) -> (
|
||||||
CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
CompositorToken<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>>,
|
||||||
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
|
StateToken<ShellState<SurfaceData, Roles, Rc<RefCell<Option<EGLDisplay>>>, ()>>,
|
||||||
Rc<RefCell<MyWindowMap>>,
|
Rc<RefCell<MyWindowMap>>,
|
||||||
|
|
|
@ -19,8 +19,9 @@ where
|
||||||
SD: 'static,
|
SD: 'static,
|
||||||
{
|
{
|
||||||
// Find the topmost surface under this point if any and the location of this point in the surface
|
// Find the topmost surface under this point if any and the location of this point in the surface
|
||||||
fn matching<F>(&self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F)
|
fn matching<F>(
|
||||||
-> Option<(wl_surface::WlSurface, (f64, f64))>
|
&self, point: (f64, f64), ctoken: CompositorToken<U, R, CID>, get_size: F
|
||||||
|
) -> Option<(wl_surface::WlSurface, (f64, f64))>
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<U>) -> Option<(i32, i32)>,
|
||||||
{
|
{
|
||||||
|
@ -33,7 +34,8 @@ where
|
||||||
let _ = ctoken.with_surface_tree_downward(
|
let _ = ctoken.with_surface_tree_downward(
|
||||||
wl_surface,
|
wl_surface,
|
||||||
self.location,
|
self.location,
|
||||||
|wl_surface, attributes, role, &(mut x, mut y)| if let Some((w, h)) = get_size(attributes) {
|
|wl_surface, attributes, role, &(mut x, mut y)| {
|
||||||
|
if let Some((w, h)) = get_size(attributes) {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.x;
|
||||||
y += subdata.y;
|
y += subdata.y;
|
||||||
|
@ -45,15 +47,16 @@ where
|
||||||
height: h,
|
height: h,
|
||||||
};
|
};
|
||||||
if my_rect.contains((point.0 as i32, point.1 as i32)) {
|
if my_rect.contains((point.0 as i32, point.1 as i32)) {
|
||||||
found = wl_surface.clone().map(|s| {
|
found = wl_surface
|
||||||
(s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64))
|
.clone()
|
||||||
});
|
.map(|s| (s, (point.0 - my_rect.x as f64, point.1 - my_rect.y as f64)));
|
||||||
TraversalAction::Break
|
TraversalAction::Break
|
||||||
} else {
|
} else {
|
||||||
TraversalAction::DoChildren((x, y))
|
TraversalAction::DoChildren((x, y))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TraversalAction::SkipChildren
|
TraversalAction::SkipChildren
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -151,8 +154,9 @@ where
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_surface_and_bring_to_top(&mut self, point: (f64, f64))
|
pub fn get_surface_and_bring_to_top(
|
||||||
-> Option<(wl_surface::WlSurface, (f64, f64))> {
|
&mut self, point: (f64, f64)
|
||||||
|
) -> Option<(wl_surface::WlSurface, (f64, f64))> {
|
||||||
let mut found = None;
|
let mut found = None;
|
||||||
for (i, w) in self.windows.iter().enumerate() {
|
for (i, w) in self.windows.iter().enumerate() {
|
||||||
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
if let Some(surface) = w.matching(point, self.ctoken, &self.get_size) {
|
||||||
|
|
142
examples/udev.rs
142
examples/udev.rs
|
@ -1,14 +1,14 @@
|
||||||
extern crate drm;
|
extern crate drm;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
extern crate rand;
|
|
||||||
extern crate input as libinput;
|
|
||||||
extern crate image;
|
extern crate image;
|
||||||
extern crate udev;
|
extern crate input as libinput;
|
||||||
|
extern crate rand;
|
||||||
#[macro_use(define_roles)]
|
#[macro_use(define_roles)]
|
||||||
extern crate smithay;
|
extern crate smithay;
|
||||||
extern crate xkbcommon;
|
extern crate udev;
|
||||||
extern crate wayland_server;
|
extern crate wayland_server;
|
||||||
|
extern crate xkbcommon;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate slog;
|
extern crate slog;
|
||||||
|
@ -21,25 +21,26 @@ mod helpers;
|
||||||
|
|
||||||
use drm::control::{Device as ControlDevice, ResourceInfo};
|
use drm::control::{Device as ControlDevice, ResourceInfo};
|
||||||
use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState};
|
use drm::control::connector::{Info as ConnectorInfo, State as ConnectorState};
|
||||||
use drm::control::encoder::Info as EncoderInfo;
|
|
||||||
use drm::control::crtc;
|
use drm::control::crtc;
|
||||||
|
use drm::control::encoder::Info as EncoderInfo;
|
||||||
use drm::result::Error as DrmError;
|
use drm::result::Error as DrmError;
|
||||||
use glium::{Blend, Surface};
|
use glium::{Blend, Surface};
|
||||||
|
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap, Roles, SurfaceData};
|
||||||
use image::{ImageBuffer, Rgba};
|
use image::{ImageBuffer, Rgba};
|
||||||
use libinput::{Libinput, Device as LibinputDevice, event};
|
use libinput::{event, Device as LibinputDevice, Libinput};
|
||||||
use libinput::event::keyboard::KeyboardEventTrait;
|
use libinput::event::keyboard::KeyboardEventTrait;
|
||||||
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData, Buffer};
|
|
||||||
use slog::{Drain, Logger};
|
use slog::{Drain, Logger};
|
||||||
use smithay::backend::drm::{DrmBackend, DrmDevice, DrmHandler, DevPath};
|
use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler};
|
||||||
use smithay::backend::graphics::GraphicsBackend;
|
use smithay::backend::graphics::GraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay, Format};
|
use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format};
|
||||||
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, PointerButtonEvent,
|
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyState, KeyboardKeyEvent,
|
||||||
PointerAxisEvent, KeyState};
|
PointerAxisEvent, PointerButtonEvent};
|
||||||
use smithay::backend::libinput::{LibinputInputBackend, libinput_bind, PointerAxisEvent as LibinputPointerAxisEvent, LibinputSessionInterface};
|
use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface,
|
||||||
use smithay::backend::udev::{UdevBackend, UdevHandler, udev_backend_bind, primary_gpu, SessionFdDrmDevice};
|
PointerAxisEvent as LibinputPointerAxisEvent};
|
||||||
use smithay::backend::session::{Session, SessionNotifier};
|
use smithay::backend::session::{Session, SessionNotifier};
|
||||||
use smithay::backend::session::direct::{direct_session_bind, DirectSession};
|
use smithay::backend::session::direct::{direct_session_bind, DirectSession};
|
||||||
|
use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, UdevBackend, UdevHandler};
|
||||||
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
||||||
|
@ -48,15 +49,15 @@ use smithay::wayland::shm::init_shm_global;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::path::PathBuf;
|
use wayland_server::{Display, StateProxy, StateToken};
|
||||||
use std::process::Command;
|
|
||||||
use xkbcommon::xkb::keysyms as xkb;
|
|
||||||
use wayland_server::{Display, StateToken, StateProxy};
|
|
||||||
use wayland_server::protocol::{wl_output, wl_pointer};
|
use wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
|
use xkbcommon::xkb::keysyms as xkb;
|
||||||
|
|
||||||
struct LibinputInputHandler {
|
struct LibinputInputHandler {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
|
@ -92,7 +93,8 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
||||||
|
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
self.keyboard.input(keycode, state, serial, |modifiers, keysym| {
|
self.keyboard
|
||||||
|
.input(keycode, state, serial, |modifiers, keysym| {
|
||||||
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
|
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace {
|
||||||
self.running.store(false, Ordering::SeqCst);
|
self.running.store(false, Ordering::SeqCst);
|
||||||
false
|
false
|
||||||
|
@ -110,7 +112,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
let mut location = self.pointer_location.borrow_mut();
|
let mut location = self.pointer_location.borrow_mut();
|
||||||
location.0 += x;
|
location.0 += x;
|
||||||
location.1 += y;
|
location.1 += y;
|
||||||
let under = self.window_map.borrow().get_surface_under((location.0, location.1));
|
let under = self.window_map
|
||||||
|
.borrow()
|
||||||
|
.get_surface_under((location.0, location.1));
|
||||||
self.pointer.motion(
|
self.pointer.motion(
|
||||||
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
|
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
|
||||||
serial,
|
serial,
|
||||||
|
@ -118,7 +122,10 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) {
|
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) {
|
||||||
let (x, y) = (evt.absolute_x_transformed(self.screen_size.0), evt.absolute_y_transformed(self.screen_size.1));
|
let (x, y) = (
|
||||||
|
evt.absolute_x_transformed(self.screen_size.0),
|
||||||
|
evt.absolute_y_transformed(self.screen_size.1),
|
||||||
|
);
|
||||||
*self.pointer_location.borrow_mut() = (x, y);
|
*self.pointer_location.borrow_mut() = (x, y);
|
||||||
let serial = self.next_serial();
|
let serial = self.next_serial();
|
||||||
let under = self.window_map.borrow().get_surface_under((x, y));
|
let under = self.window_map.borrow().get_surface_under((x, y));
|
||||||
|
@ -177,7 +184,9 @@ fn main() {
|
||||||
|
|
||||||
// A logger facility, here we use the terminal for this example
|
// A logger facility, here we use the terminal for this example
|
||||||
let log = Logger::root(
|
let log = Logger::root(
|
||||||
slog_term::FullFormat::new(slog_term::PlainSyncDecorator::new(std::io::stdout())).build().fuse(),
|
slog_term::FullFormat::new(slog_term::PlainSyncDecorator::new(std::io::stdout()))
|
||||||
|
.build()
|
||||||
|
.fuse(),
|
||||||
o!(),
|
o!(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -196,7 +205,8 @@ fn main() {
|
||||||
*/
|
*/
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(&mut event_loop, vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
|
let (compositor_token, _shell_state_token, window_map) =
|
||||||
|
init_shell(&mut event_loop, log.clone(), active_egl_context.clone());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize session on the current tty
|
* Initialize session on the current tty
|
||||||
|
@ -221,8 +231,11 @@ fn main() {
|
||||||
let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
|
let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();
|
||||||
|
|
||||||
let bytes = include_bytes!("resources/cursor2.rgba");
|
let bytes = include_bytes!("resources/cursor2.rgba");
|
||||||
let udev_token
|
let udev_token = UdevBackend::new(
|
||||||
= UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl {
|
&mut event_loop,
|
||||||
|
&context,
|
||||||
|
session.clone(),
|
||||||
|
UdevHandlerImpl {
|
||||||
compositor_token,
|
compositor_token,
|
||||||
active_egl_context,
|
active_egl_context,
|
||||||
backends: HashMap::new(),
|
backends: HashMap::new(),
|
||||||
|
@ -232,7 +245,9 @@ fn main() {
|
||||||
pointer_location: pointer_location.clone(),
|
pointer_location: pointer_location.clone(),
|
||||||
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
}, log.clone()).unwrap();
|
},
|
||||||
|
log.clone(),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
let udev_session_id = notifier.register(udev_token.clone());
|
let udev_session_id = notifier.register(udev_token.clone());
|
||||||
|
|
||||||
|
@ -283,7 +298,9 @@ fn main() {
|
||||||
/*
|
/*
|
||||||
* Initialize libinput backend
|
* Initialize libinput backend
|
||||||
*/
|
*/
|
||||||
let mut libinput_context = Libinput::new_from_udev::<LibinputSessionInterface<Rc<RefCell<DirectSession>>>>(session.into(), &context);
|
let mut libinput_context = Libinput::new_from_udev::<
|
||||||
|
LibinputSessionInterface<Rc<RefCell<DirectSession>>>,
|
||||||
|
>(session.into(), &context);
|
||||||
let libinput_session_id = notifier.register(libinput_context.clone());
|
let libinput_session_id = notifier.register(libinput_context.clone());
|
||||||
libinput_context.udev_assign_seat(&seat).unwrap();
|
libinput_context.udev_assign_seat(&seat).unwrap();
|
||||||
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||||
|
@ -337,7 +354,9 @@ struct UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandlerImpl {
|
impl UdevHandlerImpl {
|
||||||
pub fn scan_connectors(&self, device: &mut DrmDevice<SessionFdDrmDevice>) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> {
|
pub fn scan_connectors(
|
||||||
|
&self, device: &mut DrmDevice<SessionFdDrmDevice>
|
||||||
|
) -> HashMap<crtc::Handle, GliumDrawer<DrmBackend<SessionFdDrmDevice>>> {
|
||||||
// Get a set of all modesetting resource handles (excluding planes):
|
// Get a set of all modesetting resource handles (excluding planes):
|
||||||
let res_handles = device.resource_handles().unwrap();
|
let res_handles = device.resource_handles().unwrap();
|
||||||
|
|
||||||
|
@ -345,9 +364,7 @@ impl UdevHandlerImpl {
|
||||||
let connector_infos: Vec<ConnectorInfo> = res_handles
|
let connector_infos: Vec<ConnectorInfo> = res_handles
|
||||||
.connectors()
|
.connectors()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|conn| {
|
.map(|conn| ConnectorInfo::load_from_device(device, *conn).unwrap())
|
||||||
ConnectorInfo::load_from_device(device, *conn).unwrap()
|
|
||||||
})
|
|
||||||
.filter(|conn| conn.connection_state() == ConnectorState::Connected)
|
.filter(|conn| conn.connection_state() == ConnectorState::Connected)
|
||||||
.inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type()))
|
.inspect(|conn| info!(self.logger, "Connected: {:?}", conn.connector_type()))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -356,16 +373,26 @@ impl UdevHandlerImpl {
|
||||||
|
|
||||||
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
|
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
|
||||||
for connector_info in connector_infos {
|
for connector_info in connector_infos {
|
||||||
let encoder_infos = connector_info.encoders().iter().flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle)).collect::<Vec<EncoderInfo>>();
|
let encoder_infos = connector_info
|
||||||
|
.encoders()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|encoder_handle| EncoderInfo::load_from_device(device, *encoder_handle))
|
||||||
|
.collect::<Vec<EncoderInfo>>();
|
||||||
for encoder_info in encoder_infos {
|
for encoder_info in encoder_infos {
|
||||||
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
||||||
if !backends.contains_key(&crtc) {
|
if !backends.contains_key(&crtc) {
|
||||||
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
let mode = connector_info.modes()[0]; // Use first mode (usually highest resoltion, but in reality you should filter and sort and check and match with other connectors, if you use more then one.)
|
||||||
// create a backend
|
// create a backend
|
||||||
let renderer = GliumDrawer::from(device.create_backend(crtc, mode, vec![connector_info.handle()]).unwrap());
|
let renderer = GliumDrawer::from(
|
||||||
|
device
|
||||||
|
.create_backend(crtc, mode, vec![connector_info.handle()])
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
// create cursor
|
// create cursor
|
||||||
renderer.set_cursor_representation(&self.pointer_image, (2, 2)).unwrap();
|
renderer
|
||||||
|
.set_cursor_representation(&self.pointer_image, (2, 2))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// render first frame
|
// render first frame
|
||||||
{
|
{
|
||||||
|
@ -386,8 +413,9 @@ impl UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
fn device_added<'a, S: Into<StateProxy<'a>>>(&mut self, _state: S, device: &mut DrmDevice<SessionFdDrmDevice>) -> Option<DrmHandlerImpl>
|
fn device_added<'a, S: Into<StateProxy<'a>>>(
|
||||||
{
|
&mut self, _state: S, device: &mut DrmDevice<SessionFdDrmDevice>
|
||||||
|
) -> Option<DrmHandlerImpl> {
|
||||||
// init hardware acceleration on the primary gpu.
|
// init hardware acceleration on the primary gpu.
|
||||||
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||||
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display).ok();
|
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display).ok();
|
||||||
|
@ -405,14 +433,18 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_changed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>) {
|
fn device_changed<'a, S: Into<StateProxy<'a>>>(
|
||||||
|
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
|
||||||
|
) {
|
||||||
//quick and dirt, just re-init all backends
|
//quick and dirt, just re-init all backends
|
||||||
let mut state = state.into();
|
let mut state = state.into();
|
||||||
let backends = self.backends.get(&state.get(device).device_id()).unwrap();
|
let backends = self.backends.get(&state.get(device).device_id()).unwrap();
|
||||||
*backends.borrow_mut() = self.scan_connectors(state.get_mut(device));
|
*backends.borrow_mut() = self.scan_connectors(state.get_mut(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_removed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>) {
|
fn device_removed<'a, S: Into<StateProxy<'a>>>(
|
||||||
|
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
|
||||||
|
) {
|
||||||
let state = state.into();
|
let state = state.into();
|
||||||
let device = state.get(device);
|
let device = state.get(device);
|
||||||
|
|
||||||
|
@ -439,7 +471,10 @@ pub struct DrmHandlerImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
fn ready(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, crtc: crtc::Handle, _frame: u32, _duration: Duration) {
|
fn ready(
|
||||||
|
&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, crtc: crtc::Handle, _frame: u32,
|
||||||
|
_duration: Duration,
|
||||||
|
) {
|
||||||
if let Some(drawer) = self.backends.borrow().get(&crtc) {
|
if let Some(drawer) = self.backends.borrow().get(&crtc) {
|
||||||
{
|
{
|
||||||
let (x, y) = *self.pointer_location.borrow();
|
let (x, y) = *self.pointer_location.borrow();
|
||||||
|
@ -450,9 +485,8 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
// redraw the frame, in a simple but inneficient way
|
// redraw the frame, in a simple but inneficient way
|
||||||
{
|
{
|
||||||
let screen_dimensions = drawer.get_framebuffer_dimensions();
|
let screen_dimensions = drawer.get_framebuffer_dimensions();
|
||||||
self.window_map
|
self.window_map.borrow().with_windows_from_bottom_to_top(
|
||||||
.borrow()
|
|toplevel_surface, initial_place| {
|
||||||
.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
|
|
||||||
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
||||||
// this surface is a root of a subsurface tree that needs to be drawn
|
// this surface is a root of a subsurface tree that needs to be drawn
|
||||||
self.compositor_token
|
self.compositor_token
|
||||||
|
@ -467,19 +501,21 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
Some(Buffer::Egl { ref images }) => {
|
Some(Buffer::Egl { ref images }) => {
|
||||||
match images.format {
|
match images.format {
|
||||||
Format::RGB | Format::RGBA => {
|
Format::RGB | Format::RGBA => {
|
||||||
attributes.user_data.texture = drawer.texture_from_egl(&images);
|
attributes.user_data.texture =
|
||||||
},
|
drawer.texture_from_egl(&images);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// we don't handle the more complex formats here.
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
remove = true;
|
remove = true;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
Some(Buffer::Shm { ref data, ref size }) => {
|
Some(Buffer::Shm { ref data, ref size }) => {
|
||||||
attributes.user_data.texture = Some(drawer.texture_from_mem(data, *size));
|
attributes.user_data.texture =
|
||||||
},
|
Some(drawer.texture_from_mem(data, *size));
|
||||||
_ => {},
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
if remove {
|
if remove {
|
||||||
attributes.user_data.buffer = None;
|
attributes.user_data.buffer = None;
|
||||||
|
@ -500,7 +536,9 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
Buffer::Shm { .. } => false,
|
Buffer::Shm { .. } => false,
|
||||||
},
|
},
|
||||||
match *attributes.user_data.buffer.as_ref().unwrap() {
|
match *attributes.user_data.buffer.as_ref().unwrap() {
|
||||||
Buffer::Egl { ref images } => (images.width, images.height),
|
Buffer::Egl { ref images } => {
|
||||||
|
(images.width, images.height)
|
||||||
|
}
|
||||||
Buffer::Shm { ref size, .. } => *size,
|
Buffer::Shm { ref size, .. } => *size,
|
||||||
},
|
},
|
||||||
(x, y),
|
(x, y),
|
||||||
|
@ -516,7 +554,8 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Err(err) = frame.finish() {
|
if let Err(err) = frame.finish() {
|
||||||
error!(self.logger, "Error during rendering: {:?}", err);
|
error!(self.logger, "Error during rendering: {:?}", err);
|
||||||
|
@ -524,8 +563,7 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>,
|
fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) {
|
||||||
error: DrmError) {
|
|
||||||
error!(self.logger, "{:?}", error);
|
error!(self.logger, "{:?}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ extern crate wayland_server;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
use glium::Surface;
|
use glium::Surface;
|
||||||
use helpers::{init_shell, GliumDrawer, MyWindowMap, Buffer};
|
use helpers::{init_shell, Buffer, GliumDrawer, MyWindowMap};
|
||||||
use slog::{Drain, Logger};
|
use slog::{Drain, Logger};
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
|
use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format};
|
||||||
|
@ -143,7 +143,7 @@ fn main() {
|
||||||
Some(egl_display)
|
Some(egl_display)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
let (w, h) = renderer.get_framebuffer_dimensions();
|
let (w, h) = renderer.get_framebuffer_dimensions();
|
||||||
|
@ -155,7 +155,8 @@ fn main() {
|
||||||
|
|
||||||
init_shm_global(&mut event_loop, vec![], log.clone());
|
init_shm_global(&mut event_loop, vec![], log.clone());
|
||||||
|
|
||||||
let (compositor_token, _shell_state_token, window_map) = init_shell(&mut event_loop, log.clone(), egl_display);
|
let (compositor_token, _shell_state_token, window_map) =
|
||||||
|
init_shell(&mut event_loop, log.clone(), egl_display);
|
||||||
|
|
||||||
let (seat_token, _) = Seat::new(&mut event_loop, "winit".into(), log.clone());
|
let (seat_token, _) = Seat::new(&mut event_loop, "winit".into(), log.clone());
|
||||||
|
|
||||||
|
@ -240,19 +241,21 @@ fn main() {
|
||||||
Some(Buffer::Egl { ref images }) => {
|
Some(Buffer::Egl { ref images }) => {
|
||||||
match images.format {
|
match images.format {
|
||||||
Format::RGB | Format::RGBA => {
|
Format::RGB | Format::RGBA => {
|
||||||
attributes.user_data.texture = drawer.texture_from_egl(&images);
|
attributes.user_data.texture =
|
||||||
},
|
drawer.texture_from_egl(&images);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// we don't handle the more complex formats here.
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.texture = None;
|
||||||
remove = true;
|
remove = true;
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
Some(Buffer::Shm { ref data, ref size }) => {
|
Some(Buffer::Shm { ref data, ref size }) => {
|
||||||
attributes.user_data.texture = Some(drawer.texture_from_mem(data, *size));
|
attributes.user_data.texture =
|
||||||
},
|
Some(drawer.texture_from_mem(data, *size));
|
||||||
_ => {},
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
if remove {
|
if remove {
|
||||||
attributes.user_data.buffer = None;
|
attributes.user_data.buffer = None;
|
||||||
|
@ -280,14 +283,16 @@ fn main() {
|
||||||
glium::Blend {
|
glium::Blend {
|
||||||
color: glium::BlendingFunction::Addition {
|
color: glium::BlendingFunction::Addition {
|
||||||
source: glium::LinearBlendingFactor::One,
|
source: glium::LinearBlendingFactor::One,
|
||||||
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
destination:
|
||||||
|
glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
},
|
},
|
||||||
alpha: glium::BlendingFunction::Addition {
|
alpha: glium::BlendingFunction::Addition {
|
||||||
source: glium::LinearBlendingFactor::One,
|
source: glium::LinearBlendingFactor::One,
|
||||||
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
destination:
|
||||||
|
glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
TraversalAction::DoChildren((x, y))
|
TraversalAction::DoChildren((x, y))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use super::error::*;
|
|
||||||
use super::DevPath;
|
use super::DevPath;
|
||||||
|
use super::error::*;
|
||||||
use backend::graphics::GraphicsBackend;
|
use backend::graphics::GraphicsBackend;
|
||||||
use backend::graphics::egl::{EGLGraphicsBackend, EGLContext, EGLSurface, PixelFormat, SwapBuffersError};
|
use backend::graphics::egl::{EGLContext, EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError};
|
||||||
use backend::graphics::egl::error::Result as EGLResult;
|
use backend::graphics::egl::error::Result as EGLResult;
|
||||||
use backend::graphics::egl::native::{Gbm, GbmSurfaceArguments};
|
use backend::graphics::egl::native::{Gbm, GbmSurfaceArguments};
|
||||||
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
|
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
|
||||||
use drm::control::{Device, ResourceInfo};
|
use drm::control::{Device, ResourceInfo};
|
||||||
use drm::control::{connector, crtc, encoder, framebuffer, Mode};
|
use drm::control::{connector, crtc, encoder, framebuffer, Mode};
|
||||||
use gbm::{Device as GbmDevice, BufferObject, BufferObjectFlags, Format as GbmFormat, Surface as GbmSurface, SurfaceBufferHandle};
|
use gbm::{BufferObject, BufferObjectFlags, Device as GbmDevice, Format as GbmFormat, Surface as GbmSurface,
|
||||||
|
SurfaceBufferHandle};
|
||||||
use image::{ImageBuffer, Rgba};
|
use image::{ImageBuffer, Rgba};
|
||||||
use nix::libc::c_void;
|
use nix::libc::c_void;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -34,11 +35,8 @@ pub(crate) struct DrmBackendInternal<A: Device + 'static> {
|
||||||
|
|
||||||
impl<A: Device + 'static> DrmBackend<A> {
|
impl<A: Device + 'static> DrmBackend<A> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>,
|
context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>, crtc: crtc::Handle, mode: Mode,
|
||||||
crtc: crtc::Handle,
|
connectors: Vec<connector::Handle>, log: ::slog::Logger,
|
||||||
mode: Mode,
|
|
||||||
connectors: Vec<connector::Handle>,
|
|
||||||
log: ::slog::Logger,
|
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
// logger already initialized by the DrmDevice
|
// logger already initialized by the DrmDevice
|
||||||
info!(log, "Initializing DrmBackend");
|
info!(log, "Initializing DrmBackend");
|
||||||
|
@ -46,13 +44,13 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
let (w, h) = mode.size();
|
let (w, h) = mode.size();
|
||||||
|
|
||||||
debug!(log, "Creating Surface");
|
debug!(log, "Creating Surface");
|
||||||
let surface = context.create_surface(
|
let surface = context
|
||||||
GbmSurfaceArguments {
|
.create_surface(GbmSurfaceArguments {
|
||||||
size: (w as u32, h as u32),
|
size: (w as u32, h as u32),
|
||||||
format: GbmFormat::XRGB8888,
|
format: GbmFormat::XRGB8888,
|
||||||
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
||||||
}
|
})
|
||||||
).chain_err(|| ErrorKind::GbmInitFailed)?;
|
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||||
|
|
||||||
// make it active for the first `crtc::set`
|
// make it active for the first `crtc::set`
|
||||||
// (which is needed before the first page_flip)
|
// (which is needed before the first page_flip)
|
||||||
|
@ -74,8 +72,12 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
debug!(log, "FrontBuffer color format: {:?}", front_bo.format());
|
debug!(log, "FrontBuffer color format: {:?}", front_bo.format());
|
||||||
|
|
||||||
// we need a framebuffer for the front buffer
|
// we need a framebuffer for the front buffer
|
||||||
let fb = framebuffer::create(&*context, &*front_bo)
|
let fb = framebuffer::create(&*context, &*front_bo).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error creating framebuffer on {:?}", context.dev_path())))?;
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error creating framebuffer on {:?}",
|
||||||
|
context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
debug!(log, "Initialize screen");
|
debug!(log, "Initialize screen");
|
||||||
crtc::set(
|
crtc::set(
|
||||||
|
@ -85,14 +87,23 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
&connectors,
|
&connectors,
|
||||||
(0, 0),
|
(0, 0),
|
||||||
Some(mode),
|
Some(mode),
|
||||||
).chain_err(|| ErrorKind::DrmDev(format!("Error setting crtc {:?} on {:?}", crtc, context.dev_path())))?;
|
).chain_err(|| {
|
||||||
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error setting crtc {:?} on {:?}",
|
||||||
|
crtc,
|
||||||
|
context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
front_bo.set_userdata(fb).unwrap();
|
front_bo.set_userdata(fb).unwrap();
|
||||||
|
|
||||||
let cursor = Cell::new(context.create_buffer_object(
|
let cursor = Cell::new(context
|
||||||
1, 1,
|
.create_buffer_object(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
GbmFormat::ARGB8888,
|
GbmFormat::ARGB8888,
|
||||||
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
|
||||||
).chain_err(|| ErrorKind::GbmInitFailed)?);
|
)
|
||||||
|
.chain_err(|| ErrorKind::GbmInitFailed)?);
|
||||||
|
|
||||||
Ok(DrmBackend {
|
Ok(DrmBackend {
|
||||||
backend: Rc::new(DrmBackendInternal {
|
backend: Rc::new(DrmBackendInternal {
|
||||||
|
@ -110,8 +121,7 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn weak(&self) -> Weak<DrmBackendInternal<A>>
|
pub(crate) fn weak(&self) -> Weak<DrmBackendInternal<A>> {
|
||||||
{
|
|
||||||
Rc::downgrade(&self.backend)
|
Rc::downgrade(&self.backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,8 +131,12 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
///
|
///
|
||||||
/// Errors if the new connector does not support the currently set `Mode`
|
/// Errors if the new connector does not support the currently set `Mode`
|
||||||
pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> {
|
pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> {
|
||||||
let info = connector::Info::load_from_device(&*self.backend.context, connector)
|
let info = connector::Info::load_from_device(&*self.backend.context, connector).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.backend.context.dev_path())))?;
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading connector info on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
// check if the connector can handle the current mode
|
// check if the connector can handle the current mode
|
||||||
if info.modes().contains(&self.mode) {
|
if info.modes().contains(&self.mode) {
|
||||||
|
@ -130,15 +144,22 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
let encoders = info.encoders()
|
let encoders = info.encoders()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|encoder| {
|
.map(|encoder| {
|
||||||
encoder::Info::load_from_device(&*self.backend.context, *encoder)
|
encoder::Info::load_from_device(&*self.backend.context, *encoder).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.backend.context.dev_path())))
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading encoder info on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<encoder::Info>>>()?;
|
.collect::<Result<Vec<encoder::Info>>>()?;
|
||||||
|
|
||||||
// and if any encoder supports the selected crtc
|
// and if any encoder supports the selected crtc
|
||||||
let resource_handles = self.backend.context
|
let resource_handles = self.backend.context.resource_handles().chain_err(|| {
|
||||||
.resource_handles()
|
ErrorKind::DrmDev(format!(
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading resources on {:?}", self.backend.context.dev_path())))?;
|
"Error loading resources on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
if !encoders
|
if !encoders
|
||||||
.iter()
|
.iter()
|
||||||
.map(|encoder| encoder.possible_crtcs())
|
.map(|encoder| encoder.possible_crtcs())
|
||||||
|
@ -193,7 +214,12 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
// check the connectors
|
// check the connectors
|
||||||
for connector in &self.connectors {
|
for connector in &self.connectors {
|
||||||
if !connector::Info::load_from_device(&*self.backend.context, *connector)
|
if !connector::Info::load_from_device(&*self.backend.context, *connector)
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.backend.context.dev_path())))?
|
.chain_err(|| {
|
||||||
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading connector info on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})?
|
||||||
.modes()
|
.modes()
|
||||||
.contains(&mode)
|
.contains(&mode)
|
||||||
{
|
{
|
||||||
|
@ -206,14 +232,18 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
|
|
||||||
// Recreate the surface and the related resources to match the new
|
// Recreate the surface and the related resources to match the new
|
||||||
// resolution.
|
// resolution.
|
||||||
debug!(self.backend.logger, "Reinitializing surface for new mode: {}:{}", w, h);
|
debug!(
|
||||||
let surface = self.backend.context.create_surface(
|
self.backend.logger,
|
||||||
GbmSurfaceArguments {
|
"Reinitializing surface for new mode: {}:{}", w, h
|
||||||
|
);
|
||||||
|
let surface = self.backend
|
||||||
|
.context
|
||||||
|
.create_surface(GbmSurfaceArguments {
|
||||||
size: (w as u32, h as u32),
|
size: (w as u32, h as u32),
|
||||||
format: GbmFormat::XRGB8888,
|
format: GbmFormat::XRGB8888,
|
||||||
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
flags: BufferObjectFlags::SCANOUT | BufferObjectFlags::RENDERING,
|
||||||
}
|
})
|
||||||
).chain_err(|| ErrorKind::GbmInitFailed)?;
|
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||||
|
|
||||||
// make it active for the first `crtc::set`
|
// make it active for the first `crtc::set`
|
||||||
// (which is needed before the first page_flip)
|
// (which is needed before the first page_flip)
|
||||||
|
@ -231,7 +261,10 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
if let Some(mut old_bo) = self.backend.next_buffer.take() {
|
if let Some(mut old_bo) = self.backend.next_buffer.take() {
|
||||||
if let Ok(Some(fb)) = old_bo.take_userdata() {
|
if let Ok(Some(fb)) = old_bo.take_userdata() {
|
||||||
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
|
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
|
||||||
warn!(self.backend.logger, "Error releasing old back_buffer framebuffer: {:?}", err);
|
warn!(
|
||||||
|
self.backend.logger,
|
||||||
|
"Error releasing old back_buffer framebuffer: {:?}", err
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +277,11 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
.lock_front_buffer()
|
.lock_front_buffer()
|
||||||
.chain_err(|| ErrorKind::FailedToSwap)?;
|
.chain_err(|| ErrorKind::FailedToSwap)?;
|
||||||
|
|
||||||
debug!(self.backend.logger, "FrontBuffer color format: {:?}", front_bo.format());
|
debug!(
|
||||||
|
self.backend.logger,
|
||||||
|
"FrontBuffer color format: {:?}",
|
||||||
|
front_bo.format()
|
||||||
|
);
|
||||||
|
|
||||||
// we also need a new framebuffer for the front buffer
|
// we also need a new framebuffer for the front buffer
|
||||||
let dev_path = self.backend.context.dev_path();
|
let dev_path = self.backend.context.dev_path();
|
||||||
|
@ -261,13 +298,22 @@ impl<A: Device + 'static> DrmBackend<A> {
|
||||||
&self.connectors,
|
&self.connectors,
|
||||||
(0, 0),
|
(0, 0),
|
||||||
Some(mode),
|
Some(mode),
|
||||||
).chain_err(|| ErrorKind::DrmDev(format!("Error setting crtc {:?} on {:?}", self.backend.crtc, self.backend.context.dev_path())))?;
|
).chain_err(|| {
|
||||||
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error setting crtc {:?} on {:?}",
|
||||||
|
self.backend.crtc,
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
front_bo
|
front_bo
|
||||||
});
|
});
|
||||||
if let Ok(Some(fb)) = old_front_bo.take_userdata() {
|
if let Ok(Some(fb)) = old_front_bo.take_userdata() {
|
||||||
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
|
if let Err(err) = framebuffer::destroy(&*self.backend.context, fb.handle()) {
|
||||||
warn!(self.backend.logger, "Error releasing old front_buffer framebuffer: {:?}", err);
|
warn!(
|
||||||
|
self.backend.logger,
|
||||||
|
"Error releasing old front_buffer framebuffer: {:?}", err
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +340,9 @@ impl<A: Device + 'static> DrmBackendInternal<A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn page_flip(&self, fb: Option<&framebuffer::Info>) -> ::std::result::Result<(), SwapBuffersError> {
|
pub(crate) fn page_flip(
|
||||||
|
&self, fb: Option<&framebuffer::Info>
|
||||||
|
) -> ::std::result::Result<(), SwapBuffersError> {
|
||||||
trace!(self.logger, "Queueing Page flip");
|
trace!(self.logger, "Queueing Page flip");
|
||||||
|
|
||||||
let fb = *fb.unwrap_or(&self.current_frame_buffer.get());
|
let fb = *fb.unwrap_or(&self.current_frame_buffer.get());
|
||||||
|
@ -354,7 +402,12 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
|
||||||
&*self.backend.context,
|
&*self.backend.context,
|
||||||
self.backend.crtc,
|
self.backend.crtc,
|
||||||
(x as i32, y as i32),
|
(x as i32, y as i32),
|
||||||
).chain_err(|| ErrorKind::DrmDev(format!("Error moving cursor on {:?}", self.backend.context.dev_path())))
|
).chain_err(|| {
|
||||||
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error moving cursor on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor_representation(
|
fn set_cursor_representation(
|
||||||
|
@ -364,8 +417,7 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
|
||||||
debug!(self.backend.logger, "Importing cursor");
|
debug!(self.backend.logger, "Importing cursor");
|
||||||
|
|
||||||
// import the cursor into a buffer we can render
|
// import the cursor into a buffer we can render
|
||||||
let mut cursor = self
|
let mut cursor = self.backend
|
||||||
.backend
|
|
||||||
.context
|
.context
|
||||||
.create_buffer_object(
|
.create_buffer_object(
|
||||||
w,
|
w,
|
||||||
|
@ -389,9 +441,12 @@ impl<A: Device + 'static> GraphicsBackend for DrmBackend<A> {
|
||||||
(hotspot.0 as i32, hotspot.1 as i32),
|
(hotspot.0 as i32, hotspot.1 as i32),
|
||||||
).is_err()
|
).is_err()
|
||||||
{
|
{
|
||||||
crtc::set_cursor(&*self.backend.context, self.backend.crtc, &cursor).chain_err(
|
crtc::set_cursor(&*self.backend.context, self.backend.crtc, &cursor).chain_err(|| {
|
||||||
|| ErrorKind::DrmDev(format!("Failed to set cursor on {:?}", self.backend.context.dev_path())),
|
ErrorKind::DrmDev(format!(
|
||||||
)?;
|
"Failed to set cursor on {:?}",
|
||||||
|
self.backend.context.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and store it
|
// and store it
|
||||||
|
@ -409,7 +464,10 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
|
||||||
res
|
res
|
||||||
} {
|
} {
|
||||||
// We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
|
// We cannot call lock_front_buffer anymore without releasing the previous buffer, which will happen when the page flip is done
|
||||||
warn!(self.backend.logger, "Tried to swap a DrmBackend with a queued flip");
|
warn!(
|
||||||
|
self.backend.logger,
|
||||||
|
"Tried to swap a DrmBackend with a queued flip"
|
||||||
|
);
|
||||||
return Err(SwapBuffersError::AlreadySwapped);
|
return Err(SwapBuffersError::AlreadySwapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +484,10 @@ impl<A: Device + 'static> EGLGraphicsBackend for DrmBackend<A> {
|
||||||
|
|
||||||
// create a framebuffer if the front buffer does not have one already
|
// create a framebuffer if the front buffer does not have one already
|
||||||
// (they are reused by gbm)
|
// (they are reused by gbm)
|
||||||
let maybe_fb = next_bo.userdata().map_err(|_| SwapBuffersError::ContextLost)?.cloned();
|
let maybe_fb = next_bo
|
||||||
|
.userdata()
|
||||||
|
.map_err(|_| SwapBuffersError::ContextLost)?
|
||||||
|
.cloned();
|
||||||
let fb = if let Some(info) = maybe_fb {
|
let fb = if let Some(info) = maybe_fb {
|
||||||
info
|
info
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -212,29 +212,29 @@
|
||||||
use backend::graphics::egl::context::{EGLContext, GlAttributes};
|
use backend::graphics::egl::context::{EGLContext, GlAttributes};
|
||||||
use backend::graphics::egl::error::Result as EGLResult;
|
use backend::graphics::egl::error::Result as EGLResult;
|
||||||
use backend::graphics::egl::native::Gbm;
|
use backend::graphics::egl::native::Gbm;
|
||||||
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
|
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
|
||||||
#[cfg(feature = "backend_session")]
|
#[cfg(feature = "backend_session")]
|
||||||
use backend::session::SessionObserver;
|
use backend::session::SessionObserver;
|
||||||
use drm::Device as BasicDevice;
|
use drm::Device as BasicDevice;
|
||||||
use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};
|
use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};
|
||||||
use drm::control::Device as ControlDevice;
|
use drm::control::Device as ControlDevice;
|
||||||
use drm::result::Error as DrmError;
|
|
||||||
use drm::control::framebuffer;
|
use drm::control::framebuffer;
|
||||||
|
use drm::result::Error as DrmError;
|
||||||
use gbm::Device as GbmDevice;
|
use gbm::Device as GbmDevice;
|
||||||
use nix;
|
use nix;
|
||||||
|
use nix::sys::stat::{dev_t, fstat};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::io::Result as IoResult;
|
use std::io::Result as IoResult;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use nix::sys::stat::{dev_t, fstat};
|
|
||||||
use wayland_server::{EventLoopHandle, StateToken};
|
|
||||||
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
|
|
||||||
#[cfg(feature = "backend_session")]
|
#[cfg(feature = "backend_session")]
|
||||||
use wayland_server::{Display, StateProxy};
|
use wayland_server::{Display, StateProxy};
|
||||||
|
use wayland_server::{EventLoopHandle, StateToken};
|
||||||
|
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
|
||||||
|
|
||||||
mod backend;
|
mod backend;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -299,7 +299,9 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let device_id = fstat(dev.as_raw_fd()).chain_err(|| ErrorKind::UnableToGetDeviceId)?.st_rdev;
|
let device_id = fstat(dev.as_raw_fd())
|
||||||
|
.chain_err(|| ErrorKind::UnableToGetDeviceId)?
|
||||||
|
.st_rdev;
|
||||||
|
|
||||||
let mut drm = DrmDevice {
|
let mut drm = DrmDevice {
|
||||||
// Open the gbm device from the drm device and create a context based on that
|
// Open the gbm device from the drm device and create a context based on that
|
||||||
|
@ -326,17 +328,30 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
|
||||||
// we want to mode-set, so we better be the master
|
// we want to mode-set, so we better be the master
|
||||||
drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?;
|
drm.set_master().chain_err(|| ErrorKind::DrmMasterFailed)?;
|
||||||
|
|
||||||
let res_handles = drm.resource_handles()
|
let res_handles = drm.resource_handles().chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", drm.dev_path())))?;
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading drm resources on {:?}",
|
||||||
|
drm.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
for &con in res_handles.connectors() {
|
for &con in res_handles.connectors() {
|
||||||
let con_info = connector::Info::load_from_device(&drm, con)
|
let con_info = connector::Info::load_from_device(&drm, con).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading connector info on {:?}", drm.dev_path())))?;
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading connector info on {:?}",
|
||||||
|
drm.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
if let Some(enc) = con_info.current_encoder() {
|
if let Some(enc) = con_info.current_encoder() {
|
||||||
let enc_info = encoder::Info::load_from_device(&drm, enc)
|
let enc_info = encoder::Info::load_from_device(&drm, enc).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", drm.dev_path())))?;
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading encoder info on {:?}",
|
||||||
|
drm.dev_path()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
if let Some(crtc) = enc_info.current_crtc() {
|
if let Some(crtc) = enc_info.current_crtc() {
|
||||||
let info = crtc::Info::load_from_device(&drm, crtc)
|
let info = crtc::Info::load_from_device(&drm, crtc).chain_err(|| {
|
||||||
.chain_err(|| ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", drm.dev_path())))?;
|
ErrorKind::DrmDev(format!("Error loading crtc info on {:?}", drm.dev_path()))
|
||||||
|
})?;
|
||||||
drm.old_state
|
drm.old_state
|
||||||
.entry(crtc)
|
.entry(crtc)
|
||||||
.or_insert((info, Vec::new()))
|
.or_insert((info, Vec::new()))
|
||||||
|
@ -358,7 +373,7 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
|
||||||
&mut self, crtc: crtc::Handle, mode: Mode, connectors: I
|
&mut self, crtc: crtc::Handle, mode: Mode, connectors: I
|
||||||
) -> Result<DrmBackend<A>>
|
) -> Result<DrmBackend<A>>
|
||||||
where
|
where
|
||||||
I: Into<Vec<connector::Handle>>
|
I: Into<Vec<connector::Handle>>,
|
||||||
{
|
{
|
||||||
if self.backends.contains_key(&crtc) {
|
if self.backends.contains_key(&crtc) {
|
||||||
bail!(ErrorKind::CrtcAlreadyInUse(crtc));
|
bail!(ErrorKind::CrtcAlreadyInUse(crtc));
|
||||||
|
@ -373,9 +388,11 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
|
||||||
|
|
||||||
// check if we have an encoder for every connector and the mode mode
|
// check if we have an encoder for every connector and the mode mode
|
||||||
for connector in &connectors {
|
for connector in &connectors {
|
||||||
let con_info = connector::Info::load_from_device(self, *connector)
|
let con_info = connector::Info::load_from_device(self, *connector).chain_err(|| {
|
||||||
.chain_err(|| {
|
ErrorKind::DrmDev(format!(
|
||||||
ErrorKind::DrmDev(format!("Error loading connector info on {:?}", self.dev_path()))
|
"Error loading connector info on {:?}",
|
||||||
|
self.dev_path()
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// check the mode
|
// check the mode
|
||||||
|
@ -389,14 +406,20 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|encoder| {
|
.map(|encoder| {
|
||||||
encoder::Info::load_from_device(self, *encoder).chain_err(|| {
|
encoder::Info::load_from_device(self, *encoder).chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading encoder info on {:?}", self.dev_path()))
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading encoder info on {:?}",
|
||||||
|
self.dev_path()
|
||||||
|
))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<encoder::Info>>>()?;
|
.collect::<Result<Vec<encoder::Info>>>()?;
|
||||||
|
|
||||||
// and if any encoder supports the selected crtc
|
// and if any encoder supports the selected crtc
|
||||||
let resource_handles = self.resource_handles().chain_err(|| {
|
let resource_handles = self.resource_handles().chain_err(|| {
|
||||||
ErrorKind::DrmDev(format!("Error loading drm resources on {:?}", self.dev_path()))
|
ErrorKind::DrmDev(format!(
|
||||||
|
"Error loading drm resources on {:?}",
|
||||||
|
self.dev_path()
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
if !encoders
|
if !encoders
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -499,10 +522,7 @@ impl<A: ControlDevice + 'static> Drop for DrmDevice<A> {
|
||||||
pub trait DrmHandler<A: ControlDevice + 'static> {
|
pub trait DrmHandler<A: ControlDevice + 'static> {
|
||||||
/// The `DrmBackend` of crtc has finished swapping buffers and new frame can now
|
/// The `DrmBackend` of crtc has finished swapping buffers and new frame can now
|
||||||
/// (and should be immediately) be rendered.
|
/// (and should be immediately) be rendered.
|
||||||
fn ready(
|
fn ready(&mut self, device: &mut DrmDevice<A>, crtc: crtc::Handle, frame: u32, duration: Duration);
|
||||||
&mut self, device: &mut DrmDevice<A>, crtc: crtc::Handle,
|
|
||||||
frame: u32, duration: Duration,
|
|
||||||
);
|
|
||||||
/// The `DrmDevice` has thrown an error.
|
/// The `DrmDevice` has thrown an error.
|
||||||
///
|
///
|
||||||
/// The related backends are most likely *not* usable anymore and
|
/// The related backends are most likely *not* usable anymore and
|
||||||
|
@ -548,17 +568,17 @@ where
|
||||||
if let crtc::Event::PageFlip(event) = event {
|
if let crtc::Event::PageFlip(event) = event {
|
||||||
let dev = evlh.state().get_mut(dev_token);
|
let dev = evlh.state().get_mut(dev_token);
|
||||||
if dev.active {
|
if dev.active {
|
||||||
if let Some(backend) = dev.backends.get(&event.crtc).iter().flat_map(|x| x.upgrade()).next() {
|
if let Some(backend) = dev.backends
|
||||||
|
.get(&event.crtc)
|
||||||
|
.iter()
|
||||||
|
.flat_map(|x| x.upgrade())
|
||||||
|
.next()
|
||||||
|
{
|
||||||
// we can now unlock the buffer
|
// we can now unlock the buffer
|
||||||
backend.unlock_buffer();
|
backend.unlock_buffer();
|
||||||
trace!(logger, "Handling event for backend {:?}", event.crtc);
|
trace!(logger, "Handling event for backend {:?}", event.crtc);
|
||||||
// and then call the user to render the next frame
|
// and then call the user to render the next frame
|
||||||
handler.ready(
|
handler.ready(dev, event.crtc, event.frame, event.duration);
|
||||||
dev,
|
|
||||||
event.crtc,
|
|
||||||
event.frame,
|
|
||||||
event.duration,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
dev.backends.remove(&event.crtc);
|
dev.backends.remove(&event.crtc);
|
||||||
}
|
}
|
||||||
|
@ -606,9 +626,7 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
|
||||||
if let Err(err) = backend.page_flip(None) {
|
if let Err(err) = backend.page_flip(None) {
|
||||||
error!(
|
error!(
|
||||||
device.logger,
|
device.logger,
|
||||||
"Failed to activate crtc ({:?}) again. Error: {}",
|
"Failed to activate crtc ({:?}) again. Error: {}", crtc, err
|
||||||
crtc,
|
|
||||||
err
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,23 +3,22 @@
|
||||||
use super::{ffi, EGLSurface, PixelFormat};
|
use super::{ffi, EGLSurface, PixelFormat};
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
use super::native;
|
use super::native;
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use gbm::{Device as GbmDevice};
|
use drm::Device as BasicDevice;
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use drm::{Device as BasicDevice};
|
use drm::control::Device as ControlDevice;
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use drm::control::{Device as ControlDevice};
|
use gbm::Device as GbmDevice;
|
||||||
use nix::libc::{c_void, c_int};
|
use nix::libc::{c_int, c_void};
|
||||||
use slog;
|
use slog;
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::{CStr, CString};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::ptr;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// EGL context for rendering
|
/// EGL context for rendering
|
||||||
pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
pub struct EGLContext<B: native::Backend, N: native::NativeDisplay<B>> {
|
||||||
|
@ -51,13 +50,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> DerefMut for EGLContext<B,
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
/// Create a new `EGLContext` from a given `NativeDisplay`
|
/// Create a new `EGLContext` from a given `NativeDisplay`
|
||||||
pub fn new<L>(
|
pub fn new<L>(
|
||||||
native: N,
|
native: N, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L
|
||||||
attributes: GlAttributes,
|
|
||||||
reqs: PixelFormatRequirements,
|
|
||||||
logger: L
|
|
||||||
) -> Result<EGLContext<B, N>>
|
) -> Result<EGLContext<B, N>>
|
||||||
where
|
where
|
||||||
L: Into<Option<::slog::Logger>>
|
L: Into<Option<::slog::Logger>>,
|
||||||
{
|
{
|
||||||
let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl"));
|
let log = ::slog_or_stdlog(logger.into()).new(o!("smithay_module" => "renderer_egl"));
|
||||||
let ptr = native.ptr()?;
|
let ptr = native.ptr()?;
|
||||||
|
@ -86,11 +82,10 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn new_internal(
|
unsafe fn new_internal(
|
||||||
ptr: ffi::NativeDisplayType,
|
ptr: ffi::NativeDisplayType, mut attributes: GlAttributes, reqs: PixelFormatRequirements,
|
||||||
mut attributes: GlAttributes,
|
|
||||||
reqs: PixelFormatRequirements,
|
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
) -> Result<(
|
) -> Result<
|
||||||
|
(
|
||||||
Rc<ffi::egl::types::EGLContext>,
|
Rc<ffi::egl::types::EGLContext>,
|
||||||
Rc<ffi::egl::types::EGLDisplay>,
|
Rc<ffi::egl::types::EGLDisplay>,
|
||||||
ffi::egl::types::EGLConfig,
|
ffi::egl::types::EGLConfig,
|
||||||
|
@ -98,8 +93,8 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
PixelFormat,
|
PixelFormat,
|
||||||
bool,
|
bool,
|
||||||
bool,
|
bool,
|
||||||
)>
|
),
|
||||||
{
|
> {
|
||||||
// If no version is given, try OpenGLES 3.0, if available,
|
// If no version is given, try OpenGLES 3.0, if available,
|
||||||
// fallback to 2.0 otherwise
|
// fallback to 2.0 otherwise
|
||||||
let version = match attributes.version {
|
let version = match attributes.version {
|
||||||
|
@ -178,7 +173,11 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
|
|
||||||
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
|
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
|
||||||
|
|
||||||
let display = B::get_display(ptr, |e: &str| dp_extensions.iter().any(|s| s == e), log.clone());
|
let display = B::get_display(
|
||||||
|
ptr,
|
||||||
|
|e: &str| dp_extensions.iter().any(|s| s == e),
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
if display == ffi::egl::NO_DISPLAY {
|
if display == ffi::egl::NO_DISPLAY {
|
||||||
error!(log, "EGL Display is not valid");
|
error!(log, "EGL Display is not valid");
|
||||||
bail!(ErrorKind::DisplayNotSupported);
|
bail!(ErrorKind::DisplayNotSupported);
|
||||||
|
@ -455,7 +454,9 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
|
|
||||||
// the list of gl extensions supported by the context
|
// the list of gl extensions supported by the context
|
||||||
let gl_extensions = {
|
let gl_extensions = {
|
||||||
let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _).to_bytes().to_vec();
|
let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _)
|
||||||
|
.to_bytes()
|
||||||
|
.to_vec();
|
||||||
let list = String::from_utf8(data).unwrap();
|
let list = String::from_utf8(data).unwrap();
|
||||||
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
|
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
@ -468,15 +469,24 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
config_id,
|
config_id,
|
||||||
surface_attributes,
|
surface_attributes,
|
||||||
desc,
|
desc,
|
||||||
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"),
|
extensions
|
||||||
gl_extensions.iter().any(|s| *s == "GL_OES_EGL_image" || *s == "GL_OES_EGL_image_base"),
|
.iter()
|
||||||
|
.any(|s| *s == "EGL_WL_bind_wayland_display"),
|
||||||
|
gl_extensions
|
||||||
|
.iter()
|
||||||
|
.any(|s| *s == "GL_OES_EGL_image" || *s == "GL_OES_EGL_image_base"),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a surface for rendering
|
/// Creates a surface for rendering
|
||||||
pub fn create_surface(&self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
pub fn create_surface(&self, args: N::Arguments) -> Result<EGLSurface<B::Surface>> {
|
||||||
trace!(self.logger, "Creating EGL window surface.");
|
trace!(self.logger, "Creating EGL window surface.");
|
||||||
let res = EGLSurface::new(self, self.native.create_surface(args).chain_err(|| ErrorKind::SurfaceCreationFailed)?);
|
let res = EGLSurface::new(
|
||||||
|
self,
|
||||||
|
self.native
|
||||||
|
.create_surface(args)
|
||||||
|
.chain_err(|| ErrorKind::SurfaceCreationFailed)?,
|
||||||
|
);
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
debug!(self.logger, "EGL surface successfully created");
|
debug!(self.logger, "EGL surface successfully created");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
pub use nix::libc::{c_long, c_void, c_uint, int32_t, uint64_t};
|
pub use nix::libc::{c_long, c_uint, c_void, int32_t, uint64_t};
|
||||||
|
|
||||||
pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
|
pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
|
||||||
pub type khronos_uint64_t = uint64_t;
|
pub type khronos_uint64_t = uint64_t;
|
||||||
|
@ -37,43 +37,67 @@ pub mod egl {
|
||||||
* Lets do it ourselves...
|
* Lets do it ourselves...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[allow(non_snake_case, unused_variables, dead_code)] #[inline]
|
#[allow(non_snake_case, unused_variables, dead_code)]
|
||||||
pub unsafe fn BindWaylandDisplayWL(dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void) -> types::EGLBoolean {
|
#[inline]
|
||||||
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean>(wayland_storage::BindWaylandDisplayWL.f)(dpy, display)
|
pub unsafe fn BindWaylandDisplayWL(
|
||||||
|
dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void
|
||||||
|
) -> types::EGLBoolean {
|
||||||
|
__gl_imports::mem::transmute::<
|
||||||
|
_,
|
||||||
|
extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean,
|
||||||
|
>(wayland_storage::BindWaylandDisplayWL.f)(dpy, display)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case, unused_variables, dead_code)] #[inline]
|
#[allow(non_snake_case, unused_variables, dead_code)]
|
||||||
pub unsafe fn UnbindWaylandDisplayWL(dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void) -> types::EGLBoolean {
|
#[inline]
|
||||||
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean>(wayland_storage::UnbindWaylandDisplayWL.f)(dpy, display)
|
pub unsafe fn UnbindWaylandDisplayWL(
|
||||||
|
dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void
|
||||||
|
) -> types::EGLBoolean {
|
||||||
|
__gl_imports::mem::transmute::<
|
||||||
|
_,
|
||||||
|
extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void) -> types::EGLBoolean,
|
||||||
|
>(wayland_storage::UnbindWaylandDisplayWL.f)(dpy, display)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case, unused_variables, dead_code)] #[inline]
|
#[allow(non_snake_case, unused_variables, dead_code)]
|
||||||
pub unsafe fn QueryWaylandBufferWL(dpy: types::EGLDisplay, buffer: *mut __gl_imports::raw::c_void, attribute: types::EGLint, value: *mut types::EGLint) -> types::EGLBoolean {
|
#[inline]
|
||||||
__gl_imports::mem::transmute::<_, extern "system" fn(types::EGLDisplay, *mut __gl_imports::raw::c_void, types::EGLint, *mut types::EGLint) -> types::EGLBoolean>(wayland_storage::QueryWaylandBufferWL.f)(dpy, buffer, attribute, value)
|
pub unsafe fn QueryWaylandBufferWL(
|
||||||
|
dpy: types::EGLDisplay, buffer: *mut __gl_imports::raw::c_void, attribute: types::EGLint,
|
||||||
|
value: *mut types::EGLint,
|
||||||
|
) -> types::EGLBoolean {
|
||||||
|
__gl_imports::mem::transmute::<
|
||||||
|
_,
|
||||||
|
extern "system" fn(
|
||||||
|
types::EGLDisplay,
|
||||||
|
*mut __gl_imports::raw::c_void,
|
||||||
|
types::EGLint,
|
||||||
|
*mut types::EGLint,
|
||||||
|
) -> types::EGLBoolean,
|
||||||
|
>(wayland_storage::QueryWaylandBufferWL.f)(dpy, buffer, attribute, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
mod wayland_storage {
|
mod wayland_storage {
|
||||||
use super::__gl_imports::raw;
|
|
||||||
use super::FnPtr;
|
use super::FnPtr;
|
||||||
|
use super::__gl_imports::raw;
|
||||||
pub static mut BindWaylandDisplayWL: FnPtr = FnPtr {
|
pub static mut BindWaylandDisplayWL: FnPtr = FnPtr {
|
||||||
f: super::missing_fn_panic as *const raw::c_void,
|
f: super::missing_fn_panic as *const raw::c_void,
|
||||||
is_loaded: false
|
is_loaded: false,
|
||||||
};
|
};
|
||||||
pub static mut UnbindWaylandDisplayWL: FnPtr = FnPtr {
|
pub static mut UnbindWaylandDisplayWL: FnPtr = FnPtr {
|
||||||
f: super::missing_fn_panic as *const raw::c_void,
|
f: super::missing_fn_panic as *const raw::c_void,
|
||||||
is_loaded: false
|
is_loaded: false,
|
||||||
};
|
};
|
||||||
pub static mut QueryWaylandBufferWL: FnPtr = FnPtr {
|
pub static mut QueryWaylandBufferWL: FnPtr = FnPtr {
|
||||||
f: super::missing_fn_panic as *const raw::c_void,
|
f: super::missing_fn_panic as *const raw::c_void,
|
||||||
is_loaded: false
|
is_loaded: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod BindWaylandDisplayWL {
|
pub mod BindWaylandDisplayWL {
|
||||||
use super::{wayland_storage, metaloadfn};
|
use super::{metaloadfn, wayland_storage};
|
||||||
use super::__gl_imports::raw;
|
|
||||||
use super::FnPtr;
|
use super::FnPtr;
|
||||||
|
use super::__gl_imports::raw;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -82,18 +106,22 @@ pub mod egl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void {
|
pub fn load_with<F>(mut loadfn: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&str) -> *const raw::c_void,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
wayland_storage::BindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
|
wayland_storage::BindWaylandDisplayWL =
|
||||||
|
FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod UnbindWaylandDisplayWL {
|
pub mod UnbindWaylandDisplayWL {
|
||||||
use super::{wayland_storage, metaloadfn};
|
use super::{metaloadfn, wayland_storage};
|
||||||
use super::__gl_imports::raw;
|
|
||||||
use super::FnPtr;
|
use super::FnPtr;
|
||||||
|
use super::__gl_imports::raw;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -102,18 +130,22 @@ pub mod egl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void {
|
pub fn load_with<F>(mut loadfn: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&str) -> *const raw::c_void,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
wayland_storage::UnbindWaylandDisplayWL = FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
|
wayland_storage::UnbindWaylandDisplayWL =
|
||||||
|
FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod QueryWaylandBufferWL {
|
pub mod QueryWaylandBufferWL {
|
||||||
use super::{wayland_storage, metaloadfn};
|
use super::{metaloadfn, wayland_storage};
|
||||||
use super::__gl_imports::raw;
|
|
||||||
use super::FnPtr;
|
use super::FnPtr;
|
||||||
|
use super::__gl_imports::raw;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -122,9 +154,13 @@ pub mod egl {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn load_with<F>(mut loadfn: F) where F: FnMut(&str) -> *const raw::c_void {
|
pub fn load_with<F>(mut loadfn: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&str) -> *const raw::c_void,
|
||||||
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
wayland_storage::QueryWaylandBufferWL = FnPtr::new(metaloadfn(&mut loadfn, "eglQueryWaylandBufferWL", &[]))
|
wayland_storage::QueryWaylandBufferWL =
|
||||||
|
FnPtr::new(metaloadfn(&mut loadfn, "eglQueryWaylandBufferWL", &[]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub mod native;
|
||||||
pub mod surface;
|
pub mod surface;
|
||||||
pub use self::surface::EGLSurface;
|
pub use self::surface::EGLSurface;
|
||||||
pub mod wayland;
|
pub mod wayland;
|
||||||
pub use self::wayland::{EGLWaylandExtensions, EGLImages, BufferAccessError};
|
pub use self::wayland::{BufferAccessError, EGLImages, EGLWaylandExtensions};
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
/// Error that can happen when swapping buffers.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -73,8 +73,12 @@ pub struct EglExtensionNotSupportedError(&'static [&'static str]);
|
||||||
|
|
||||||
impl fmt::Display for EglExtensionNotSupportedError {
|
impl fmt::Display for EglExtensionNotSupportedError {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
write!(formatter, "None of the following EGL extensions is supported by the underlying EGL implementation,
|
write!(
|
||||||
at least one is required: {:?}", self.0)
|
formatter,
|
||||||
|
"None of the following EGL extensions is supported by the underlying EGL implementation,
|
||||||
|
at least one is required: {:?}",
|
||||||
|
self.0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
//! Type safe native types for safe context/surface creation
|
//! Type safe native types for safe context/surface creation
|
||||||
|
|
||||||
use super::ffi;
|
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
|
use super::ffi;
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use ::backend::drm::error::{Error as DrmError, ErrorKind as DrmErrorKind, Result as DrmResult};
|
use backend::drm::error::{Error as DrmError, ErrorKind as DrmErrorKind, Result as DrmResult};
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use gbm::{AsRaw, Device as GbmDevice, Format as GbmFormat, BufferObjectFlags, Surface as GbmSurface};
|
use gbm::{AsRaw, BufferObjectFlags, Device as GbmDevice, Format as GbmFormat, Surface as GbmSurface};
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
|
|
||||||
use std::ptr;
|
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
#[cfg(any(feature = "backend_drm", feature = "backend_winit"))]
|
||||||
|
use std::ptr;
|
||||||
|
#[cfg(feature = "backend_winit")]
|
||||||
|
use wayland_client::egl as wegl;
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
use winit::Window as WinitWindow;
|
use winit::Window as WinitWindow;
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
use winit::os::unix::WindowExt;
|
use winit::os::unix::WindowExt;
|
||||||
#[cfg(feature = "backend_winit")]
|
|
||||||
use wayland_client::egl as wegl;
|
|
||||||
|
|
||||||
/// Trait for typed backend variants (X11/Wayland/GBM)
|
/// Trait for typed backend variants (X11/Wayland/GBM)
|
||||||
pub trait Backend {
|
pub trait Backend {
|
||||||
|
@ -32,9 +31,7 @@ pub trait Backend {
|
||||||
/// The returned `EGLDisplay` needs to be a valid ptr for egl,
|
/// The returned `EGLDisplay` needs to be a valid ptr for egl,
|
||||||
/// but there is no way to test that.
|
/// but there is no way to test that.
|
||||||
unsafe fn get_display<F: Fn(&str) -> bool>(
|
unsafe fn get_display<F: Fn(&str) -> bool>(
|
||||||
display: ffi::NativeDisplayType,
|
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
|
||||||
has_dp_extension: F,
|
|
||||||
log: ::slog::Logger,
|
|
||||||
) -> ffi::egl::types::EGLDisplay;
|
) -> ffi::egl::types::EGLDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,24 +42,28 @@ pub enum Wayland {}
|
||||||
impl Backend for Wayland {
|
impl Backend for Wayland {
|
||||||
type Surface = wegl::WlEglSurface;
|
type Surface = wegl::WlEglSurface;
|
||||||
|
|
||||||
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
|
unsafe fn get_display<F>(
|
||||||
-> ffi::egl::types::EGLDisplay
|
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
|
||||||
|
) -> ffi::egl::types::EGLDisplay
|
||||||
where
|
where
|
||||||
F: Fn(&str) -> bool
|
F: Fn(&str) -> bool,
|
||||||
{
|
{
|
||||||
if has_dp_extension("EGL_KHR_platform_wayland")
|
if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||||
&& ffi::egl::GetPlatformDisplay::is_loaded()
|
trace!(
|
||||||
{
|
log,
|
||||||
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
|
"EGL Display Initialization via EGL_KHR_platform_wayland"
|
||||||
|
);
|
||||||
ffi::egl::GetPlatformDisplay(
|
ffi::egl::GetPlatformDisplay(
|
||||||
ffi::egl::PLATFORM_WAYLAND_KHR,
|
ffi::egl::PLATFORM_WAYLAND_KHR,
|
||||||
display as *mut _,
|
display as *mut _,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
)
|
)
|
||||||
} else if has_dp_extension("EGL_EXT_platform_wayland")
|
} else if has_dp_extension("EGL_EXT_platform_wayland") && ffi::egl::GetPlatformDisplayEXT::is_loaded()
|
||||||
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
|
|
||||||
{
|
{
|
||||||
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland");
|
trace!(
|
||||||
|
log,
|
||||||
|
"EGL Display Initialization via EGL_EXT_platform_wayland"
|
||||||
|
);
|
||||||
ffi::egl::GetPlatformDisplayEXT(
|
ffi::egl::GetPlatformDisplayEXT(
|
||||||
ffi::egl::PLATFORM_WAYLAND_EXT,
|
ffi::egl::PLATFORM_WAYLAND_EXT,
|
||||||
display as *mut _,
|
display as *mut _,
|
||||||
|
@ -85,19 +86,16 @@ pub enum X11 {}
|
||||||
impl Backend for X11 {
|
impl Backend for X11 {
|
||||||
type Surface = XlibWindow;
|
type Surface = XlibWindow;
|
||||||
|
|
||||||
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
|
unsafe fn get_display<F>(
|
||||||
-> ffi::egl::types::EGLDisplay
|
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
|
||||||
|
) -> ffi::egl::types::EGLDisplay
|
||||||
where
|
where
|
||||||
F: Fn(&str) -> bool
|
F: Fn(&str) -> bool,
|
||||||
{
|
|
||||||
if has_dp_extension("EGL_KHR_platform_x11")
|
|
||||||
&& 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");
|
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
|
||||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
|
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
|
||||||
} else if has_dp_extension("EGL_EXT_platform_x11")
|
} else if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
|
||||||
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
|
|
||||||
{
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
|
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
|
||||||
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
|
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,24 +113,19 @@ pub struct Gbm<T: 'static> {
|
||||||
impl<T: 'static> Backend for Gbm<T> {
|
impl<T: 'static> Backend for Gbm<T> {
|
||||||
type Surface = GbmSurface<T>;
|
type Surface = GbmSurface<T>;
|
||||||
|
|
||||||
unsafe fn get_display<F>(display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger)
|
unsafe fn get_display<F>(
|
||||||
-> ffi::egl::types::EGLDisplay
|
display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger
|
||||||
|
) -> ffi::egl::types::EGLDisplay
|
||||||
where
|
where
|
||||||
F: Fn(&str) -> bool
|
F: Fn(&str) -> bool,
|
||||||
{
|
|
||||||
if has_dp_extension("EGL_KHR_platform_gbm")
|
|
||||||
&& 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");
|
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
|
||||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
||||||
} else if has_dp_extension("EGL_MESA_platform_gbm")
|
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
|
||||||
&& ffi::egl::GetPlatformDisplayEXT::is_loaded()
|
|
||||||
{
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
||||||
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
||||||
} else if has_dp_extension("EGL_MESA_platform_gbm")
|
} else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
|
||||||
&& ffi::egl::GetPlatformDisplay::is_loaded()
|
|
||||||
{
|
|
||||||
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
||||||
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null())
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,7 +217,9 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
|
||||||
type Arguments = GbmSurfaceArguments;
|
type Arguments = GbmSurfaceArguments;
|
||||||
type Error = DrmError;
|
type Error = DrmError;
|
||||||
|
|
||||||
fn is_backend(&self) -> bool { true }
|
fn is_backend(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
|
fn ptr(&self) -> Result<ffi::NativeDisplayType> {
|
||||||
Ok(self.as_raw() as *const _)
|
Ok(self.as_raw() as *const _)
|
||||||
|
@ -233,13 +228,10 @@ unsafe impl<A: AsRawFd + 'static, T: 'static> NativeDisplay<Gbm<T>> for GbmDevic
|
||||||
fn create_surface(&self, args: GbmSurfaceArguments) -> DrmResult<GbmSurface<T>> {
|
fn create_surface(&self, args: GbmSurfaceArguments) -> DrmResult<GbmSurface<T>> {
|
||||||
use backend::drm::error::ResultExt as DrmResultExt;
|
use backend::drm::error::ResultExt as DrmResultExt;
|
||||||
|
|
||||||
DrmResultExt::chain_err(GbmDevice::create_surface(
|
DrmResultExt::chain_err(
|
||||||
self,
|
GbmDevice::create_surface(self, args.size.0, args.size.1, args.format, args.flags),
|
||||||
args.size.0,
|
|| DrmErrorKind::GbmInitFailed,
|
||||||
args.size.1,
|
)
|
||||||
args.format,
|
|
||||||
args.flags,
|
|
||||||
), || DrmErrorKind::GbmInitFailed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,15 +247,21 @@ pub unsafe trait NativeSurface {
|
||||||
|
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
unsafe impl NativeSurface for XlibWindow {
|
unsafe impl NativeSurface for XlibWindow {
|
||||||
fn ptr(&self) -> ffi::NativeWindowType { self.0 as *const _ }
|
fn ptr(&self) -> ffi::NativeWindowType {
|
||||||
|
self.0 as *const _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_winit")]
|
#[cfg(feature = "backend_winit")]
|
||||||
unsafe impl NativeSurface for wegl::WlEglSurface {
|
unsafe impl NativeSurface for wegl::WlEglSurface {
|
||||||
fn ptr(&self) -> ffi::NativeWindowType { self.ptr() as *const _ }
|
fn ptr(&self) -> ffi::NativeWindowType {
|
||||||
|
self.ptr() as *const _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "backend_drm")]
|
#[cfg(feature = "backend_drm")]
|
||||||
unsafe impl<T: 'static> NativeSurface for GbmSurface<T> {
|
unsafe impl<T: 'static> NativeSurface for GbmSurface<T> {
|
||||||
fn ptr(&self) -> ffi::NativeWindowType { self.as_raw() as *const _ }
|
fn ptr(&self) -> ffi::NativeWindowType {
|
||||||
|
self.as_raw() as *const _
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ use super::{EGLContext, SwapBuffersError};
|
||||||
use super::error::*;
|
use super::error::*;
|
||||||
use super::ffi;
|
use super::ffi;
|
||||||
use super::native;
|
use super::native;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
|
|
||||||
|
@ -31,8 +30,7 @@ impl<N: native::NativeSurface> DerefMut for EGLSurface<N> {
|
||||||
|
|
||||||
impl<N: native::NativeSurface> EGLSurface<N> {
|
impl<N: native::NativeSurface> EGLSurface<N> {
|
||||||
pub(crate) fn new<B: native::Backend<Surface = N>, D: native::NativeDisplay<B>>(
|
pub(crate) fn new<B: native::Backend<Surface = N>, D: native::NativeDisplay<B>>(
|
||||||
context: &EGLContext<B, D>,
|
context: &EGLContext<B, D>, native: N
|
||||||
native: N,
|
|
||||||
) -> Result<EGLSurface<N>> {
|
) -> Result<EGLSurface<N>> {
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
ffi::egl::CreateWindowSurface(
|
ffi::egl::CreateWindowSurface(
|
||||||
|
@ -58,9 +56,7 @@ impl<N: native::NativeSurface> EGLSurface<N> {
|
||||||
/// Swaps buffers at the end of a frame.
|
/// Swaps buffers at the end of a frame.
|
||||||
pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> {
|
||||||
if let Some(display) = self.display.upgrade() {
|
if let Some(display) = self.display.upgrade() {
|
||||||
let ret = unsafe {
|
let ret = unsafe { ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _) };
|
||||||
ffi::egl::SwapBuffers((*display) as *const _, self.surface as *const _)
|
|
||||||
};
|
|
||||||
|
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
match unsafe { ffi::egl::GetError() } as u32 {
|
match unsafe { ffi::egl::GetError() } as u32 {
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
//! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer`
|
//! You may then use the resulting `EGLDisplay` to recieve `EGLImages` of an egl-based `WlBuffer`
|
||||||
//! for rendering.
|
//! for rendering.
|
||||||
|
|
||||||
use backend::graphics::egl::{EGLContext, EglExtensionNotSupportedError, ffi, native};
|
use backend::graphics::egl::{ffi, native, EGLContext, EglExtensionNotSupportedError};
|
||||||
use backend::graphics::egl::error::*;
|
use backend::graphics::egl::error::*;
|
||||||
use backend::graphics::egl::ffi::egl::types::EGLImage;
|
use backend::graphics::egl::ffi::egl::types::EGLImage;
|
||||||
use nix::libc::{c_uint};
|
use nix::libc::c_uint;
|
||||||
use std::rc::{Rc, Weak};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::rc::{Rc, Weak};
|
||||||
use wayland_server::{Display, Resource};
|
use wayland_server::{Display, Resource};
|
||||||
use wayland_server::protocol::wl_buffer::WlBuffer;
|
use wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
use wayland_sys::server::wl_display;
|
use wayland_sys::server::wl_display;
|
||||||
|
@ -37,7 +37,9 @@ impl fmt::Debug for BufferAccessError {
|
||||||
match *self {
|
match *self {
|
||||||
BufferAccessError::ContextLost => write!(formatter, "BufferAccessError::ContextLost"),
|
BufferAccessError::ContextLost => write!(formatter, "BufferAccessError::ContextLost"),
|
||||||
BufferAccessError::NotManaged(_) => write!(formatter, "BufferAccessError::NotManaged"),
|
BufferAccessError::NotManaged(_) => write!(formatter, "BufferAccessError::NotManaged"),
|
||||||
BufferAccessError::EGLImageCreationFailed => write!(formatter, "BufferAccessError::EGLImageCreationFailed"),
|
BufferAccessError::EGLImageCreationFailed => {
|
||||||
|
write!(formatter, "BufferAccessError::EGLImageCreationFailed")
|
||||||
|
}
|
||||||
BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err),
|
BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,9 +47,11 @@ impl fmt::Debug for BufferAccessError {
|
||||||
|
|
||||||
impl fmt::Display for BufferAccessError {
|
impl fmt::Display for BufferAccessError {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
use ::std::error::Error;
|
use std::error::Error;
|
||||||
match *self {
|
match *self {
|
||||||
BufferAccessError::ContextLost | BufferAccessError::NotManaged(_) | BufferAccessError::EGLImageCreationFailed => write!(formatter, "{}", self.description()),
|
BufferAccessError::ContextLost
|
||||||
|
| BufferAccessError::NotManaged(_)
|
||||||
|
| BufferAccessError::EGLImageCreationFailed => write!(formatter, "{}", self.description()),
|
||||||
BufferAccessError::EglExtensionNotSupported(ref err) => err.fmt(formatter),
|
BufferAccessError::EglExtensionNotSupported(ref err) => err.fmt(formatter),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,11 +106,16 @@ pub enum TextureCreationError {
|
||||||
|
|
||||||
impl fmt::Display for TextureCreationError {
|
impl fmt::Display for TextureCreationError {
|
||||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
use ::std::error::Error;
|
use std::error::Error;
|
||||||
match *self {
|
match *self {
|
||||||
TextureCreationError::ContextLost => write!(formatter, "{}", self.description()),
|
TextureCreationError::ContextLost => write!(formatter, "{}", self.description()),
|
||||||
TextureCreationError::PlaneIndexOutOfBounds => write!(formatter, "{}", self.description()),
|
TextureCreationError::PlaneIndexOutOfBounds => write!(formatter, "{}", self.description()),
|
||||||
TextureCreationError::TextureBindingFailed(code) => write!(formatter, "{}. Gl error code: {:?}", self.description(), code),
|
TextureCreationError::TextureBindingFailed(code) => write!(
|
||||||
|
formatter,
|
||||||
|
"{}. Gl error code: {:?}",
|
||||||
|
self.description(),
|
||||||
|
code
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,12 +191,19 @@ impl EGLImages {
|
||||||
/// # Unsafety
|
/// # Unsafety
|
||||||
///
|
///
|
||||||
/// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur.
|
/// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur.
|
||||||
pub unsafe fn bind_to_texture(&self, plane: usize, tex_id: c_uint) -> ::std::result::Result<(), TextureCreationError> {
|
pub unsafe fn bind_to_texture(
|
||||||
|
&self, plane: usize, tex_id: c_uint
|
||||||
|
) -> ::std::result::Result<(), TextureCreationError> {
|
||||||
if self.display.upgrade().is_some() {
|
if self.display.upgrade().is_some() {
|
||||||
let mut old_tex_id: i32 = 0;
|
let mut old_tex_id: i32 = 0;
|
||||||
ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_tex_id);
|
ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_tex_id);
|
||||||
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id);
|
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id);
|
||||||
ffi::gl::EGLImageTargetTexture2DOES(ffi::gl::TEXTURE_2D, *self.images.get(plane).ok_or(TextureCreationError::PlaneIndexOutOfBounds)?);
|
ffi::gl::EGLImageTargetTexture2DOES(
|
||||||
|
ffi::gl::TEXTURE_2D,
|
||||||
|
*self.images
|
||||||
|
.get(plane)
|
||||||
|
.ok_or(TextureCreationError::PlaneIndexOutOfBounds)?,
|
||||||
|
);
|
||||||
let res = match ffi::egl::GetError() as u32 {
|
let res = match ffi::egl::GetError() as u32 {
|
||||||
ffi::egl::SUCCESS => Ok(()),
|
ffi::egl::SUCCESS => Ok(()),
|
||||||
err => Err(TextureCreationError::TextureBindingFailed(err)),
|
err => Err(TextureCreationError::TextureBindingFailed(err)),
|
||||||
|
@ -204,7 +220,9 @@ impl Drop for EGLImages {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(display) = self.display.upgrade() {
|
if let Some(display) = self.display.upgrade() {
|
||||||
for image in self.images.drain(..) {
|
for image in self.images.drain(..) {
|
||||||
unsafe { ffi::egl::DestroyImageKHR(*display, image); }
|
unsafe {
|
||||||
|
ffi::egl::DestroyImageKHR(*display, image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.buffer.release();
|
self.buffer.release();
|
||||||
|
@ -236,7 +254,9 @@ pub trait EGLWaylandExtensions {
|
||||||
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
|
pub struct EGLDisplay(Weak<ffi::egl::types::EGLDisplay>, *mut wl_display);
|
||||||
|
|
||||||
impl EGLDisplay {
|
impl EGLDisplay {
|
||||||
fn new<B: native::Backend, N: native::NativeDisplay<B>>(context: &EGLContext<B, N>, display: *mut wl_display) -> EGLDisplay {
|
fn new<B: native::Backend, N: native::NativeDisplay<B>>(
|
||||||
|
context: &EGLContext<B, N>, display: *mut wl_display
|
||||||
|
) -> EGLDisplay {
|
||||||
EGLDisplay(Rc::downgrade(&context.display), display)
|
EGLDisplay(Rc::downgrade(&context.display), display)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,10 +265,19 @@ impl EGLDisplay {
|
||||||
/// In case the buffer is not managed by egl (but e.g. the wayland::shm module)
|
/// In case the buffer is not managed by egl (but e.g. the wayland::shm module)
|
||||||
/// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer
|
/// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer
|
||||||
/// to render it another way.
|
/// to render it another way.
|
||||||
pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
pub fn egl_buffer_contents(
|
||||||
|
&self, buffer: WlBuffer
|
||||||
|
) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
||||||
if let Some(display) = self.0.upgrade() {
|
if let Some(display) = self.0.upgrade() {
|
||||||
let mut format: i32 = 0;
|
let mut format: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } {
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.ptr() as *mut _,
|
||||||
|
ffi::egl::EGL_TEXTURE_FORMAT,
|
||||||
|
&mut format as *mut _,
|
||||||
|
) == 0
|
||||||
|
} {
|
||||||
return Err(BufferAccessError::NotManaged(buffer));
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
let format = match format {
|
let format = match format {
|
||||||
|
@ -262,17 +291,38 @@ impl EGLDisplay {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut width: i32 = 0;
|
let mut width: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } {
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.ptr() as *mut _,
|
||||||
|
ffi::egl::WIDTH as i32,
|
||||||
|
&mut width as *mut _,
|
||||||
|
) == 0
|
||||||
|
} {
|
||||||
return Err(BufferAccessError::NotManaged(buffer));
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut height: i32 = 0;
|
let mut height: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } {
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.ptr() as *mut _,
|
||||||
|
ffi::egl::HEIGHT as i32,
|
||||||
|
&mut height as *mut _,
|
||||||
|
) == 0
|
||||||
|
} {
|
||||||
return Err(BufferAccessError::NotManaged(buffer));
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inverted: i32 = 0;
|
let mut inverted: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) != 0 } {
|
if unsafe {
|
||||||
|
ffi::egl::QueryWaylandBufferWL(
|
||||||
|
*display,
|
||||||
|
buffer.ptr() as *mut _,
|
||||||
|
ffi::egl::WAYLAND_Y_INVERTED_WL,
|
||||||
|
&mut inverted as *mut _,
|
||||||
|
) != 0
|
||||||
|
} {
|
||||||
inverted = 1;
|
inverted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,14 +334,15 @@ impl EGLDisplay {
|
||||||
out.push(ffi::egl::NONE as i32);
|
out.push(ffi::egl::NONE as i32);
|
||||||
|
|
||||||
images.push({
|
images.push({
|
||||||
let image =
|
let image = unsafe {
|
||||||
unsafe { ffi::egl::CreateImageKHR(
|
ffi::egl::CreateImageKHR(
|
||||||
*display,
|
*display,
|
||||||
ffi::egl::NO_CONTEXT,
|
ffi::egl::NO_CONTEXT,
|
||||||
ffi::egl::WAYLAND_BUFFER_WL,
|
ffi::egl::WAYLAND_BUFFER_WL,
|
||||||
buffer.ptr() as *mut _,
|
buffer.ptr() as *mut _,
|
||||||
out.as_ptr(),
|
out.as_ptr(),
|
||||||
) };
|
)
|
||||||
|
};
|
||||||
if image == ffi::egl::NO_IMAGE_KHR {
|
if image == ffi::egl::NO_IMAGE_KHR {
|
||||||
return Err(BufferAccessError::EGLImageCreationFailed);
|
return Err(BufferAccessError::EGLImageCreationFailed);
|
||||||
} else {
|
} else {
|
||||||
|
@ -319,14 +370,15 @@ impl Drop for EGLDisplay {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Some(display) = self.0.upgrade() {
|
if let Some(display) = self.0.upgrade() {
|
||||||
if !self.1.is_null() {
|
if !self.1.is_null() {
|
||||||
unsafe { ffi::egl::UnbindWaylandDisplayWL(*display, self.1 as *mut _); }
|
unsafe {
|
||||||
|
ffi::egl::UnbindWaylandDisplayWL(*display, self.1 as *mut _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E>
|
impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E> {
|
||||||
{
|
|
||||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||||
(**self).bind_wl_display(display)
|
(**self).bind_wl_display(display)
|
||||||
}
|
}
|
||||||
|
@ -335,7 +387,9 @@ impl<E: EGLWaylandExtensions> EGLWaylandExtensions for Rc<E>
|
||||||
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLWaylandExtensions for EGLContext<B, N> {
|
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLWaylandExtensions for EGLContext<B, N> {
|
||||||
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
|
||||||
if !self.wl_drm_support {
|
if !self.wl_drm_support {
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["EGL_WL_bind_wayland_display"]));
|
bail!(ErrorKind::EglExtensionNotSupported(&[
|
||||||
|
"EGL_WL_bind_wayland_display"
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
if !self.egl_to_texture_support {
|
if !self.egl_to_texture_support {
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));
|
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! Glium compatibility module
|
//! Glium compatibility module
|
||||||
|
|
||||||
use backend::graphics::egl::{EGLGraphicsBackend, SwapBuffersError};
|
use backend::graphics::egl::{EGLGraphicsBackend, SwapBuffersError};
|
||||||
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
|
|
||||||
use backend::graphics::egl::error::Result as EGLResult;
|
use backend::graphics::egl::error::Result as EGLResult;
|
||||||
|
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
|
||||||
use glium::Frame;
|
use glium::Frame;
|
||||||
use glium::SwapBuffersError as GliumSwapBuffersError;
|
use glium::SwapBuffersError as GliumSwapBuffersError;
|
||||||
use glium::backend::{Backend, Context, Facade};
|
use glium::backend::{Backend, Context, Facade};
|
||||||
|
@ -76,13 +76,13 @@ impl<T: EGLGraphicsBackend + 'static> From<T> for GliumGraphicsBackend<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: EGLGraphicsBackend + EGLWaylandExtensions + 'static> EGLWaylandExtensions for GliumGraphicsBackend<T> {
|
impl<T: EGLGraphicsBackend + EGLWaylandExtensions + 'static> EGLWaylandExtensions
|
||||||
|
for GliumGraphicsBackend<T> {
|
||||||
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
fn bind_wl_display(&self, display: &Display) -> EGLResult<EGLDisplay> {
|
||||||
(*self.backend).0.bind_wl_display(display)
|
(*self.backend).0.bind_wl_display(display)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe impl<T: EGLGraphicsBackend> Backend for InternalBackend<T> {
|
unsafe impl<T: EGLGraphicsBackend> Backend for InternalBackend<T> {
|
||||||
fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> {
|
fn swap_buffers(&self) -> Result<(), GliumSwapBuffersError> {
|
||||||
self.0.swap_buffers().map_err(Into::into)
|
self.0.swap_buffers().map_err(Into::into)
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
//! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this
|
//! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this
|
||||||
//! backend.
|
//! backend.
|
||||||
|
|
||||||
use drm::Device as BasicDevice;
|
|
||||||
use drm::control::Device as ControlDevice;
|
|
||||||
use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
|
use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
|
||||||
use backend::session::{Session, SessionObserver};
|
use backend::session::{Session, SessionObserver};
|
||||||
|
use drm::Device as BasicDevice;
|
||||||
|
use drm::control::Device as ControlDevice;
|
||||||
use nix::fcntl;
|
use nix::fcntl;
|
||||||
use nix::sys::stat::dev_t;
|
use nix::sys::stat::dev_t;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -59,11 +59,8 @@ pub struct UdevBackend<
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevHandler<H> + 'static>
|
||||||
H: DrmHandler<SessionFdDrmDevice> + 'static,
|
UdevBackend<H, S, T> {
|
||||||
S: Session + 'static,
|
|
||||||
T: UdevHandler<H> + 'static,
|
|
||||||
> UdevBackend<H, S, T> {
|
|
||||||
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
|
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
|
||||||
///
|
///
|
||||||
/// ## Arguments
|
/// ## Arguments
|
||||||
|
@ -244,7 +241,12 @@ where
|
||||||
) {
|
) {
|
||||||
Ok(fd) => SessionFdDrmDevice(fd),
|
Ok(fd) => SessionFdDrmDevice(fd),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
warn!(
|
||||||
|
logger,
|
||||||
|
"Unable to open drm device {:?}, Error: {:?}. Skipping",
|
||||||
|
path,
|
||||||
|
err
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,16 +357,16 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime.
|
/// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime.
|
||||||
pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static>
|
pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> {
|
||||||
{
|
|
||||||
/// Called on initialization for every known device and when a new device is detected.
|
/// Called on initialization for every known device and when a new device is detected.
|
||||||
///
|
///
|
||||||
/// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device.
|
/// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device.
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
||||||
fn device_added<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>)
|
fn device_added<'a, S: Into<StateProxy<'a>>>(
|
||||||
-> Option<H>;
|
&mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>
|
||||||
|
) -> Option<H>;
|
||||||
/// Called when an open device is changed.
|
/// Called when an open device is changed.
|
||||||
///
|
///
|
||||||
/// This usually indicates that some connectors did become available or were unplugged. The handler
|
/// This usually indicates that some connectors did become available or were unplugged. The handler
|
||||||
|
@ -372,7 +374,9 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static>
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
||||||
fn device_changed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>);
|
fn device_changed<'a, S: Into<StateProxy<'a>>>(
|
||||||
|
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
|
||||||
|
);
|
||||||
/// Called when a device was removed.
|
/// Called when a device was removed.
|
||||||
///
|
///
|
||||||
/// The device will not accept any operations anymore and its file descriptor will be closed once
|
/// The device will not accept any operations anymore and its file descriptor will be closed once
|
||||||
|
@ -380,7 +384,9 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static>
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
|
||||||
fn device_removed<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>);
|
fn device_removed<'a, S: Into<StateProxy<'a>>>(
|
||||||
|
&mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
|
||||||
|
);
|
||||||
/// Called when the udev context has encountered and error.
|
/// Called when the udev context has encountered and error.
|
||||||
///
|
///
|
||||||
/// ## Panics
|
/// ## Panics
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
//! Implementation of backend traits for types provided by `winit`
|
//! Implementation of backend traits for types provided by `winit`
|
||||||
|
|
||||||
use backend::graphics::GraphicsBackend;
|
use backend::graphics::GraphicsBackend;
|
||||||
use backend::graphics::egl::{EGLGraphicsBackend, EGLContext, EGLSurface, PixelFormat, SwapBuffersError};
|
use backend::graphics::egl::{EGLContext, EGLGraphicsBackend, EGLSurface, PixelFormat, SwapBuffersError};
|
||||||
|
use backend::graphics::egl::context::GlAttributes;
|
||||||
use backend::graphics::egl::error as egl_error;
|
use backend::graphics::egl::error as egl_error;
|
||||||
use backend::graphics::egl::error::Result as EGLResult;
|
use backend::graphics::egl::error::Result as EGLResult;
|
||||||
use backend::graphics::egl::native;
|
use backend::graphics::egl::native;
|
||||||
use backend::graphics::egl::context::GlAttributes;
|
use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};
|
||||||
use backend::graphics::egl::wayland::{EGLWaylandExtensions, EGLDisplay};
|
|
||||||
use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
|
use backend::input::{Axis, AxisSource, Event as BackendEvent, InputBackend, InputHandler, KeyState,
|
||||||
KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
|
KeyboardKeyEvent, MouseButton, MouseButtonState, PointerAxisEvent, PointerButtonEvent,
|
||||||
PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
|
PointerMotionAbsoluteEvent, Seat, SeatCapabilities, TouchCancelEvent, TouchDownEvent,
|
||||||
|
@ -16,10 +16,10 @@ use std::cmp;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor,
|
|
||||||
MouseScrollDelta, Touch, TouchPhase, WindowBuilder, WindowEvent, Window as WinitWindow};
|
|
||||||
use wayland_client::egl as wegl;
|
use wayland_client::egl as wegl;
|
||||||
use wayland_server::Display;
|
use wayland_server::Display;
|
||||||
|
use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as WinitMouseButton, MouseCursor,
|
||||||
|
MouseScrollDelta, Touch, TouchPhase, Window as WinitWindow, WindowBuilder, WindowEvent};
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
errors {
|
errors {
|
||||||
|
@ -139,32 +139,18 @@ where
|
||||||
let reqs = Default::default();
|
let reqs = Default::default();
|
||||||
let window = Rc::new(
|
let window = Rc::new(
|
||||||
if native::NativeDisplay::<native::Wayland>::is_backend(&winit_window) {
|
if native::NativeDisplay::<native::Wayland>::is_backend(&winit_window) {
|
||||||
let context = EGLContext::<native::Wayland, WinitWindow>::new(
|
let context =
|
||||||
winit_window,
|
EGLContext::<native::Wayland, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
|
||||||
attributes,
|
|
||||||
reqs,
|
|
||||||
log.clone(),
|
|
||||||
)?;
|
|
||||||
let surface = context.create_surface(())?;
|
let surface = context.create_surface(())?;
|
||||||
Window::Wayland {
|
Window::Wayland { context, surface }
|
||||||
context,
|
|
||||||
surface
|
|
||||||
}
|
|
||||||
} else if native::NativeDisplay::<native::X11>::is_backend(&winit_window) {
|
} else if native::NativeDisplay::<native::X11>::is_backend(&winit_window) {
|
||||||
let context = EGLContext::<native::X11, WinitWindow>::new(
|
let context =
|
||||||
winit_window,
|
EGLContext::<native::X11, WinitWindow>::new(winit_window, attributes, reqs, log.clone())?;
|
||||||
attributes,
|
|
||||||
reqs,
|
|
||||||
log.clone(),
|
|
||||||
)?;
|
|
||||||
let surface = context.create_surface(())?;
|
let surface = context.create_surface(())?;
|
||||||
Window::X11 {
|
Window::X11 { context, surface }
|
||||||
context,
|
|
||||||
surface
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bail!(ErrorKind::NotSupported);
|
bail!(ErrorKind::NotSupported);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -237,8 +223,14 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
|
||||||
|
|
||||||
fn is_current(&self) -> bool {
|
fn is_current(&self) -> bool {
|
||||||
match *self.window {
|
match *self.window {
|
||||||
Window::Wayland { ref context, ref surface } => context.is_current() && surface.is_current(),
|
Window::Wayland {
|
||||||
Window::X11 { ref context, ref surface } => context.is_current() && surface.is_current(),
|
ref context,
|
||||||
|
ref surface,
|
||||||
|
} => context.is_current() && surface.is_current(),
|
||||||
|
Window::X11 {
|
||||||
|
ref context,
|
||||||
|
ref surface,
|
||||||
|
} => context.is_current() && surface.is_current(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,8 +641,10 @@ impl InputBackend for WinitInputBackend {
|
||||||
trace!(logger, "Resizing window to {:?}", (x, y));
|
trace!(logger, "Resizing window to {:?}", (x, y));
|
||||||
window.window().set_inner_size(x, y);
|
window.window().set_inner_size(x, y);
|
||||||
match **window {
|
match **window {
|
||||||
Window::Wayland { ref surface, .. } => surface.resize(x as i32, y as i32, 0, 0),
|
Window::Wayland { ref surface, .. } => {
|
||||||
_ => {},
|
surface.resize(x as i32, y as i32, 0, 0)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
|
@ -449,8 +449,7 @@ impl<SD> ShellClient<SD> {
|
||||||
}
|
}
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ShellClientKind::Wl(ref shell) => {
|
ShellClientKind::Wl(ref shell) => {
|
||||||
let mutex =
|
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
|
||||||
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
|
|
||||||
let mut guard = mutex.lock().unwrap();
|
let mut guard = mutex.lock().unwrap();
|
||||||
if guard.0.pending_ping == 0 {
|
if guard.0.pending_ping == 0 {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -487,8 +486,7 @@ impl<SD> ShellClient<SD> {
|
||||||
}
|
}
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ShellClientKind::Wl(ref shell) => {
|
ShellClientKind::Wl(ref shell) => {
|
||||||
let mutex =
|
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
|
||||||
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
|
|
||||||
let mut guard = mutex.lock().unwrap();
|
let mut guard = mutex.lock().unwrap();
|
||||||
Ok(f(&mut guard.0.data))
|
Ok(f(&mut guard.0.data))
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,8 +271,7 @@ where
|
||||||
{
|
{
|
||||||
wl_shell_surface::Implementation {
|
wl_shell_surface::Implementation {
|
||||||
pong: |evlh, idata, _, shell_surface, serial| {
|
pong: |evlh, idata, _, shell_surface, serial| {
|
||||||
let &(_, ref shell) =
|
let &(_, ref shell) = unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
|
||||||
unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
|
|
||||||
let valid = {
|
let valid = {
|
||||||
let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) };
|
let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) };
|
||||||
let mut guard = mutex.lock().unwrap();
|
let mut guard = mutex.lock().unwrap();
|
||||||
|
|
|
@ -230,9 +230,8 @@ fn destroy_surface(surface: &zxdg_surface_v6::ZxdgSurfaceV6) {
|
||||||
let ptr = surface.get_user_data();
|
let ptr = surface.get_user_data();
|
||||||
surface.set_user_data(::std::ptr::null_mut());
|
surface.set_user_data(::std::ptr::null_mut());
|
||||||
// drop the state
|
// drop the state
|
||||||
let data = unsafe {
|
let data =
|
||||||
Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6))
|
unsafe { Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6)) };
|
||||||
};
|
|
||||||
// explicit call to drop to not forget what we're doing here
|
// explicit call to drop to not forget what we're doing here
|
||||||
::std::mem::drop(data);
|
::std::mem::drop(data);
|
||||||
}
|
}
|
||||||
|
@ -544,9 +543,8 @@ where
|
||||||
with_surface_toplevel_data(idata, toplevel, |toplevel_data| {
|
with_surface_toplevel_data(idata, toplevel, |toplevel_data| {
|
||||||
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
|
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
|
||||||
let parent_ptr = toplevel_surface_parent.get_user_data();
|
let parent_ptr = toplevel_surface_parent.get_user_data();
|
||||||
let &(ref parent_surface, _) = unsafe {
|
let &(ref parent_surface, _) =
|
||||||
&*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6))
|
unsafe { &*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6)) };
|
||||||
};
|
|
||||||
unsafe { parent_surface.clone_unchecked() }
|
unsafe { parent_surface.clone_unchecked() }
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,6 +43,8 @@ containers:
|
||||||
- !Container base
|
- !Container base
|
||||||
- !Env HOME: /work/.vagga/nightly-home
|
- !Env HOME: /work/.vagga/nightly-home
|
||||||
- !Sh curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host x86_64-unknown-linux-gnu --default-toolchain nightly --no-modify-path
|
- !Sh curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host x86_64-unknown-linux-gnu --default-toolchain nightly --no-modify-path
|
||||||
|
- !Env PATH: /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/work/.vagga/nightly-home/.cargo/bin:/work/.vagga/nightly-home/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/
|
||||||
|
- !Sh rustup component add rustfmt-preview
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
update-stable: !Command
|
update-stable: !Command
|
||||||
|
|
Loading…
Reference in New Issue