Get it to work...
This commit is contained in:
parent
726991367d
commit
6c6d54064d
|
@ -3,7 +3,8 @@ use glium::{Frame, Surface, GlObject};
|
||||||
use glium::backend::Facade;
|
use glium::backend::Facade;
|
||||||
use glium::index::PrimitiveType;
|
use glium::index::PrimitiveType;
|
||||||
use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d};
|
use glium::texture::{MipmapsOption, UncompressedFloatFormat, Texture2d};
|
||||||
use smithay::backend::graphics::egl::{EGLGraphicsBackend, EGLImage};
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
|
use smithay::backend::graphics::egl::wayland::{Format, EGLImages};
|
||||||
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;
|
||||||
|
@ -108,45 +109,52 @@ impl<T: Into<GliumGraphicsBackend<T>> + EGLGraphicsBackend + 'static> From<T> fo
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
pub fn texture_from_mem(&self, contents: &[u8], surface_dimensions: (u32, u32)) {
|
pub fn texture_from_mem(&self, contents: &[u8], surface_dimensions: (u32, u32)) -> Texture2d {
|
||||||
let image = glium::texture::RawImage2d {
|
let image = glium::texture::RawImage2d {
|
||||||
data: contents.into(),
|
data: contents.into(),
|
||||||
width: surface_dimensions.0,
|
width: surface_dimensions.0,
|
||||||
height: surface_dimensions.1,
|
height: surface_dimensions.1,
|
||||||
format: glium::texture::ClientFormat::U8U8U8U8,
|
format: glium::texture::ClientFormat::U8U8U8U8,
|
||||||
};
|
};
|
||||||
let opengl_texture = Texture2d::new(&self.display, image).unwrap();
|
Texture2d::new(&self.display, image).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texture_from_egl(&self, image: EGLImage, format: UncompressedFloatFormat,
|
pub fn texture_from_egl(&self, images: &EGLImages)
|
||||||
surface_dimensions: (u32, u32))
|
-> Option<Texture2d>
|
||||||
-> Texture2d
|
|
||||||
{
|
{
|
||||||
|
let format = match images.format {
|
||||||
|
Format::RGB => UncompressedFloatFormat::U8U8U8,
|
||||||
|
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
let opengl_texture = Texture2d::empty_with_format(
|
let opengl_texture = Texture2d::empty_with_format(
|
||||||
&self.display,
|
&self.display,
|
||||||
format,
|
format,
|
||||||
MipmapsOption::NoMipmap,
|
MipmapsOption::NoMipmap,
|
||||||
surface_dimensions.0,
|
images.width,
|
||||||
surface_dimensions.1,
|
images.height,
|
||||||
).unwrap();
|
).unwrap();
|
||||||
self.display.get_context().exec_in_context(|| {
|
if let Err(_) = unsafe { self.display.get_context().exec_in_context(|| {
|
||||||
self.display.borrow().egl_image_to_texture(image, opengl_texture.get_id());
|
images.bind_to_texture(0, opengl_texture.get_id())
|
||||||
});
|
}) } { return None };
|
||||||
opengl_texture
|
Some(opengl_texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_texture(&self, target: &mut glium::Frame, texture: Texture2d,
|
pub fn render_texture(&self, target: &mut glium::Frame, texture: &Texture2d,
|
||||||
y_inverted: bool, surface_dimensions: (u32, u32),
|
y_inverted: bool, surface_dimensions: (u32, u32),
|
||||||
surface_location: (i32, i32), screen_size: (u32, u32))
|
surface_location: (i32, i32), screen_size: (u32, u32))
|
||||||
{
|
{
|
||||||
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);
|
||||||
if y_inverted {
|
|
||||||
yscale = -yscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = 2.0 * (surface_location.0 as f32) / (screen_size.0 as f32) - 1.0;
|
let x = 2.0 * (surface_location.0 as f32) / (screen_size.0 as f32) - 1.0;
|
||||||
let y = 1.0 - 2.0 * (surface_location.1 as f32) / (screen_size.1 as f32);
|
let mut y = 1.0 - 2.0 * (surface_location.1 as f32) / (screen_size.1 as f32);
|
||||||
|
|
||||||
|
if y_inverted {
|
||||||
|
yscale = -yscale;
|
||||||
|
y -= surface_dimensions.1 as f32;
|
||||||
|
}
|
||||||
|
|
||||||
let uniforms = uniform! {
|
let uniforms = uniform! {
|
||||||
matrix: [
|
matrix: [
|
||||||
|
@ -155,7 +163,7 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
[ 0.0 , 0.0 , 1.0, 0.0],
|
[ 0.0 , 0.0 , 1.0, 0.0],
|
||||||
[ x , y , 0.0, 1.0]
|
[ x , y , 0.0, 1.0]
|
||||||
],
|
],
|
||||||
tex: &texture,
|
tex: texture,
|
||||||
};
|
};
|
||||||
|
|
||||||
target
|
target
|
||||||
|
@ -164,10 +172,28 @@ impl<F: EGLGraphicsBackend + 'static> GliumDrawer<F> {
|
||||||
&self.index_buffer,
|
&self.index_buffer,
|
||||||
&self.program,
|
&self.program,
|
||||||
&uniforms,
|
&uniforms,
|
||||||
&Default::default(),
|
&glium::DrawParameters {
|
||||||
|
blend: glium::Blend {
|
||||||
|
color: glium::BlendingFunction::Addition {
|
||||||
|
source: glium::LinearBlendingFactor::One,
|
||||||
|
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
|
},
|
||||||
|
alpha: glium::BlendingFunction::Addition {
|
||||||
|
source: glium::LinearBlendingFactor::One,
|
||||||
|
destination: glium::LinearBlendingFactor::OneMinusSourceAlpha,
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
depth: glium::Depth {
|
||||||
|
test: glium::DepthTest::IfLess,
|
||||||
|
write: false,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
.. Default::default()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn draw(&self) -> Frame {
|
pub fn draw(&self) -> Frame {
|
||||||
|
|
|
@ -1,78 +1,81 @@
|
||||||
use super::{GliumDrawer, WindowMap};
|
use super::{GliumDrawer, WindowMap};
|
||||||
use glium::texture::{Texture2d, UncompressedFloatFormat};
|
use smithay::backend::graphics::egl::wayland::{Format, BufferAccessError};
|
||||||
|
use glium::texture::Texture2d;
|
||||||
use rand;
|
use rand;
|
||||||
use smithay::backend::graphics::egl::{EGLGraphicsBackend, EGLImage};
|
use smithay::backend::graphics::egl::{EGLGraphicsBackend, EGLImages};
|
||||||
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
|
use smithay::wayland::compositor::{compositor_init, CompositorToken, SurfaceAttributes,
|
||||||
SurfaceUserImplementation};
|
SurfaceUserImplementation};
|
||||||
use smithay::wayland::shell::{shell_init, PopupConfigure, ShellState, ShellSurfaceRole,
|
use smithay::wayland::shell::{shell_init, PopupConfigure, ShellState, ShellSurfaceRole,
|
||||||
ShellSurfaceUserImplementation, ToplevelConfigure};
|
ShellSurfaceUserImplementation, ToplevelConfigure};
|
||||||
use smithay::wayland::shm::with_buffer_contents as shm_buffer_contents;
|
use smithay::wayland::shm::with_buffer_contents as shm_buffer_contents;
|
||||||
use smithay::wayland::drm::{with_buffer_contents as drm_buffer_contents, Attributes, Format};
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::borrow::Borrow;
|
||||||
use wayland_server::{EventLoop, StateToken};
|
use wayland_server::{EventLoop, StateToken};
|
||||||
|
|
||||||
define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );
|
define_roles!(Roles => [ ShellSurface, ShellSurfaceRole ] );
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SurfaceData {
|
pub struct SurfaceData {
|
||||||
pub texture: Option<Texture2d>,
|
|
||||||
pub buffer: Option<Buffer>,
|
pub buffer: Option<Buffer>,
|
||||||
|
pub texture: Option<Texture2d>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Buffer {
|
pub enum Buffer {
|
||||||
Egl { images: Vec<EGLImage>, attributes: Attributes },
|
Egl { images: EGLImages },
|
||||||
Shm { data: Vec<u8>, size: (u32, u32) },
|
Shm { data: Vec<u8>, size: (u32, u32) },
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Buffer {}
|
unsafe impl Send for Buffer {}
|
||||||
|
|
||||||
pub fn surface_implementation<G: EGLGraphicsBackend + 'static>() -> SurfaceUserImplementation<SurfaceData, Roles, GliumDrawer<G>> {
|
pub fn surface_implementation<G: EGLGraphicsBackend + 'static>() -> SurfaceUserImplementation<SurfaceData, Roles, Rc<GliumDrawer<G>>> {
|
||||||
SurfaceUserImplementation {
|
SurfaceUserImplementation {
|
||||||
commit: |_, drawer, surface, token| {
|
commit: |_, drawer, surface, token| {
|
||||||
// we retrieve the contents of the associated buffer and copy it
|
// we retrieve the contents of the associated buffer and copy it
|
||||||
token.with_surface_data(surface, |attributes| {
|
token.with_surface_data(surface, |attributes| {
|
||||||
match attributes.buffer() {
|
match attributes.buffer.take() {
|
||||||
Some(ref buffer) => {
|
Some(Some((buffer, (_x, _y)))) => {
|
||||||
// we ignore hotspot coordinates in this simple example (`attributes.buffer_coordinates()`)
|
// we ignore hotspot coordinates in this simple example
|
||||||
if drm_buffer_contents(&buffer, drawer.borrow(), |attributes, images| {
|
match <GliumDrawer<G> as Borrow<G>>::borrow(&**drawer).egl_buffer_contents(buffer) {
|
||||||
let format = match attributes.format {
|
Ok(images) => {
|
||||||
Format::RGB => UncompressedFloatFormat::U8U8U8,
|
let format = match images.format {
|
||||||
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
|
Format::RGB => {},
|
||||||
_ => {
|
Format::RGBA => {},
|
||||||
// we don't handle the more complex formats here.
|
_ => {
|
||||||
attributes.user_data.buffer = None;
|
// we don't handle the more complex formats here.
|
||||||
attributes.user_data.texture = None;
|
attributes.user_data.buffer = None;
|
||||||
return;
|
attributes.user_data.texture = None;
|
||||||
},
|
return;
|
||||||
};
|
},
|
||||||
attributes.user_data.texture = Some(drawer.texture_from_egl(
|
};
|
||||||
images[0] /*Both simple formats only have one plane*/,
|
attributes.user_data.texture = drawer.texture_from_egl(&images);
|
||||||
format,
|
attributes.user_data.buffer = Some(Buffer::Egl { images });
|
||||||
(attributes.width, attributes.height)
|
},
|
||||||
));
|
Err(BufferAccessError::NotManaged(buffer)) => {
|
||||||
attributes.user_data.buffer = Some(Buffer::Egl { images, attributes });
|
shm_buffer_contents(&buffer, |slice, data| {
|
||||||
}).is_err() {
|
let offset = data.offset as usize;
|
||||||
shm_buffer_contents(&buffer, |slice, data| {
|
let stride = data.stride as usize;
|
||||||
let offset = data.offset as usize;
|
let width = data.width as usize;
|
||||||
let stride = data.stride as usize;
|
let height = data.height as usize;
|
||||||
let width = data.width as usize;
|
let mut new_vec = Vec::with_capacity(width * height * 4);
|
||||||
let height = data.height as usize;
|
for i in 0..height {
|
||||||
let mut new_vec = Vec::with_capacity(width * height * 4);
|
new_vec
|
||||||
for i in 0..height {
|
.extend(&slice[(offset + i * stride)..(offset + i * stride + width * 4)]);
|
||||||
new_vec
|
}
|
||||||
.extend(&slice[(offset + i * stride)..(offset + i * stride + width * 4)]);
|
attributes.user_data.texture = Some(drawer.texture_from_mem(&new_vec, (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) });
|
||||||
attributes.user_data.texture = Some(drawer.texture_from_mem(&new_vec, data.width as u32, data.height as u32));
|
}).unwrap();
|
||||||
attributes.user_data.buffer =
|
buffer.release();
|
||||||
Some(Buffer::Shm { data: new_vec, position: (data.width as u32, data.height as u32) });
|
},
|
||||||
}).unwrap();
|
Err(err) => panic!("EGL error: {}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
Some(None) => {
|
||||||
// erase the contents
|
// erase the contents
|
||||||
attributes.user_data.buffer = None;
|
attributes.user_data.buffer = None;
|
||||||
|
attributes.user_data.texture = None;
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -82,14 +85,15 @@ pub fn surface_implementation<G: EGLGraphicsBackend + 'static>() -> SurfaceUserI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ShellIData<F> {
|
pub struct ShellIData<F, G: EGLGraphicsBackend + 'static> {
|
||||||
pub token: CompositorToken<SurfaceData, Roles, ()>,
|
pub token: CompositorToken<SurfaceData, Roles, Rc<GliumDrawer<G>>>,
|
||||||
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, (), (), F>>>,
|
pub window_map: Rc<RefCell<super::WindowMap<SurfaceData, Roles, Rc<GliumDrawer<G>>, (), F>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shell_implementation<F>() -> ShellSurfaceUserImplementation<SurfaceData, Roles, (), ShellIData<F>, ()>
|
pub fn shell_implementation<F, G>() -> ShellSurfaceUserImplementation<SurfaceData, Roles, Rc<GliumDrawer<G>>, ShellIData<F, G>, ()>
|
||||||
where
|
where
|
||||||
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
F: Fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
||||||
|
G: EGLGraphicsBackend + 'static,
|
||||||
{
|
{
|
||||||
ShellSurfaceUserImplementation {
|
ShellSurfaceUserImplementation {
|
||||||
new_client: |_, _, _| {},
|
new_client: |_, _, _| {},
|
||||||
|
@ -134,23 +138,27 @@ fn get_size(attrs: &SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)> {
|
||||||
.user_data
|
.user_data
|
||||||
.buffer
|
.buffer
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|&(_, (w, h))| (w as i32, h as i32))
|
.map(|ref buffer| match **buffer {
|
||||||
|
Buffer::Shm { ref size, .. } => *size,
|
||||||
|
Buffer::Egl { ref images } => (images.width, images.height),
|
||||||
|
})
|
||||||
|
.map(|(x, y)| (x as i32, y as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MyWindowMap = WindowMap<
|
pub type MyWindowMap<G: EGLGraphicsBackend + 'static> = WindowMap<
|
||||||
SurfaceData,
|
SurfaceData,
|
||||||
Roles,
|
Roles,
|
||||||
(),
|
Rc<GliumDrawer<G>>,
|
||||||
(),
|
(),
|
||||||
fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
fn(&SurfaceAttributes<SurfaceData>) -> Option<(i32, i32)>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
pub fn init_shell<ID: 'static>(
|
pub fn init_shell<G: EGLGraphicsBackend + 'static>(
|
||||||
evl: &mut EventLoop, log: ::slog::Logger, data: ID)
|
evl: &mut EventLoop, log: ::slog::Logger, data: Rc<GliumDrawer<G>>)
|
||||||
-> (
|
-> (
|
||||||
CompositorToken<SurfaceData, Roles, ID>,
|
CompositorToken<SurfaceData, Roles, Rc<GliumDrawer<G>>>,
|
||||||
StateToken<ShellState<SurfaceData, Roles, ID, ()>>,
|
StateToken<ShellState<SurfaceData, Roles, Rc<GliumDrawer<G>>, ()>>,
|
||||||
Rc<RefCell<MyWindowMap>>,
|
Rc<RefCell<MyWindowMap<G>>>,
|
||||||
) {
|
) {
|
||||||
let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone());
|
let (compositor_token, _, _) = compositor_init(evl, surface_implementation(), data, log.clone());
|
||||||
|
|
||||||
|
|
|
@ -27,23 +27,23 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wayland_server::protocol::{wl_output, wl_pointer};
|
use wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
|
|
||||||
struct WinitInputHandler {
|
struct WinitInputHandler<G: EGLGraphicsBackend + 'static> {
|
||||||
log: Logger,
|
log: Logger,
|
||||||
pointer: PointerHandle,
|
pointer: PointerHandle,
|
||||||
keyboard: KeyboardHandle,
|
keyboard: KeyboardHandle,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap<G>>>,
|
||||||
pointer_location: (f64, f64),
|
pointer_location: (f64, f64),
|
||||||
serial: u32,
|
serial: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitInputHandler {
|
impl<G: EGLGraphicsBackend + 'static> WinitInputHandler<G> {
|
||||||
fn next_serial(&mut self) -> u32 {
|
fn next_serial(&mut self) -> u32 {
|
||||||
self.serial += 1;
|
self.serial += 1;
|
||||||
self.serial
|
self.serial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputHandler<winit::WinitInputBackend> for WinitInputHandler {
|
impl<G: EGLGraphicsBackend + 'static> InputHandler<winit::WinitInputBackend> for WinitInputHandler<G> {
|
||||||
fn on_seat_created(&mut self, _: &input::Seat) {
|
fn on_seat_created(&mut self, _: &input::Seat) {
|
||||||
/* never happens with winit */
|
/* never happens with winit */
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,7 @@ fn main() {
|
||||||
info!(log, "EGL hardware-acceleration enabled");
|
info!(log, "EGL hardware-acceleration enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (w, h) = renderer.get_framebuffer_dimensions();
|
||||||
let drawer = Rc::new(GliumDrawer::from(renderer));
|
let drawer = Rc::new(GliumDrawer::from(renderer));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -172,7 +173,6 @@ fn main() {
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (w, h) = renderer.get_framebuffer_dimensions();
|
|
||||||
event_loop
|
event_loop
|
||||||
.state()
|
.state()
|
||||||
.get_mut(&output_token)
|
.get_mut(&output_token)
|
||||||
|
@ -194,10 +194,6 @@ fn main() {
|
||||||
refresh: 60_000,
|
refresh: 60_000,
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize glium
|
|
||||||
*/
|
|
||||||
|
|
||||||
input.set_handler(WinitInputHandler {
|
input.set_handler(WinitInputHandler {
|
||||||
log: log.clone(),
|
log: log.clone(),
|
||||||
pointer,
|
pointer,
|
||||||
|
@ -217,7 +213,7 @@ fn main() {
|
||||||
input.dispatch_new_events().unwrap();
|
input.dispatch_new_events().unwrap();
|
||||||
|
|
||||||
let mut frame = drawer.draw();
|
let mut frame = drawer.draw();
|
||||||
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, None, None);
|
frame.clear(None, Some((0.8, 0.8, 0.9, 1.0)), false, Some(1.0), None);
|
||||||
// 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();
|
||||||
|
@ -232,7 +228,7 @@ fn main() {
|
||||||
initial_place,
|
initial_place,
|
||||||
|_surface, attributes, role, &(mut x, mut y)| {
|
|_surface, attributes, role, &(mut x, mut y)| {
|
||||||
// there is actually something to draw !
|
// there is actually something to draw !
|
||||||
if let Some(texture) = attributes.user_data.texture {
|
if let Some(ref texture) = attributes.user_data.texture {
|
||||||
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
|
||||||
x += subdata.x;
|
x += subdata.x;
|
||||||
y += subdata.y;
|
y += subdata.y;
|
||||||
|
@ -241,11 +237,11 @@ fn main() {
|
||||||
&mut frame,
|
&mut frame,
|
||||||
texture,
|
texture,
|
||||||
match *attributes.user_data.buffer.as_ref().unwrap() {
|
match *attributes.user_data.buffer.as_ref().unwrap() {
|
||||||
Buffer::Egl { ref attributes, .. } => attributes.y_inverted,
|
Buffer::Egl { ref images } => images.y_inverted,
|
||||||
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 attributes, .. } => (attributes.width, attributes.height),
|
Buffer::Egl { ref images } => (images.width, images.height),
|
||||||
Buffer::Shm { ref size, .. } => *size,
|
Buffer::Shm { ref size, .. } => *size,
|
||||||
},
|
},
|
||||||
(x, y),
|
(x, y),
|
||||||
|
|
|
@ -132,6 +132,12 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
};
|
};
|
||||||
|
|
||||||
ffi::egl::LOAD.call_once(|| {
|
ffi::egl::LOAD.call_once(|| {
|
||||||
|
fn constrain<F>(f: F) -> F
|
||||||
|
where
|
||||||
|
F: for<'a> Fn(&'a str) -> *const ::std::os::raw::c_void,
|
||||||
|
{
|
||||||
|
f
|
||||||
|
};
|
||||||
ffi::egl::load_with(|sym| {
|
ffi::egl::load_with(|sym| {
|
||||||
let name = CString::new(sym).unwrap();
|
let name = CString::new(sym).unwrap();
|
||||||
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
||||||
|
@ -140,14 +146,16 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
Err(_) => ptr::null(),
|
Err(_) => ptr::null(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ffi::gl::load_with(|sym| {
|
let procAddress = constrain(|sym| {
|
||||||
let name = CString::new(sym).unwrap();
|
let addr = CString::new(sym).unwrap();
|
||||||
let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes());
|
let addr = addr.as_ptr();
|
||||||
match symbol {
|
ffi::egl::GetProcAddress(addr) as *const _
|
||||||
Ok(x) => *x as *const _,
|
|
||||||
Err(_) => ptr::null(),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
ffi::egl::load_with(&procAddress);
|
||||||
|
ffi::egl::BindWaylandDisplayWL::load_with(&procAddress);
|
||||||
|
ffi::egl::UnbindWaylandDisplayWL::load_with(&procAddress);
|
||||||
|
ffi::egl::QueryWaylandBufferWL::load_with(&procAddress);
|
||||||
|
ffi::gl::load_with(&procAddress);
|
||||||
});
|
});
|
||||||
|
|
||||||
// the first step is to query the list of extensions without any display, if supported
|
// the first step is to query the list of extensions without any display, if supported
|
||||||
|
@ -434,6 +442,23 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
|
|
||||||
info!(log, "EGL context created");
|
info!(log, "EGL context created");
|
||||||
|
|
||||||
|
// make current and get list of gl extensions
|
||||||
|
ffi::egl::MakeCurrent(
|
||||||
|
display as *const _,
|
||||||
|
ptr::null(),
|
||||||
|
ptr::null(),
|
||||||
|
context as *const _,
|
||||||
|
);
|
||||||
|
|
||||||
|
// the list of gl extensions supported by the context
|
||||||
|
let gl_extensions = {
|
||||||
|
let data = CStr::from_ptr(ffi::gl::GetString(ffi::gl::EXTENSIONS) as *const _).to_bytes().to_vec();
|
||||||
|
let list = String::from_utf8(data).unwrap();
|
||||||
|
list.split(' ').map(|e| e.to_string()).collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
info!(log, "GL Extensions: {:?}", gl_extensions);
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
Rc::new(context as *const _),
|
Rc::new(context as *const _),
|
||||||
Rc::new(display as *const _),
|
Rc::new(display as *const _),
|
||||||
|
@ -441,7 +466,7 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
surface_attributes,
|
surface_attributes,
|
||||||
desc,
|
desc,
|
||||||
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"),
|
extensions.iter().any(|s| *s == "EGL_WL_bind_wayland_display"),
|
||||||
extensions.iter().any(|s| *s == "EGL_OES_image" || *s == "EGL_OES_image_base"),
|
gl_extensions.iter().any(|s| *s == "GL_OES_EGL_image" || *s == "GL_OES_EGL_image_base"),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +555,7 @@ pub enum GlProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes how the backend should choose a pixel format.
|
/// Describes how the backend should choose a pixel format.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct PixelFormatRequirements {
|
pub struct PixelFormatRequirements {
|
||||||
/// If `true`, only hardware-accelerated formats will be conisdered. If `false`, only software renderers.
|
/// If `true`, only hardware-accelerated formats will be conisdered. If `false`, only software renderers.
|
||||||
/// `None` means "don't care". Default is `None`.
|
/// `None` means "don't care". Default is `None`.
|
||||||
|
@ -557,3 +582,19 @@ pub struct PixelFormatRequirements {
|
||||||
/// The default is `false`.
|
/// The default is `false`.
|
||||||
pub stereoscopy: bool,
|
pub stereoscopy: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PixelFormatRequirements {
|
||||||
|
fn default() -> Self {
|
||||||
|
PixelFormatRequirements {
|
||||||
|
hardware_accelerated: Some(true),
|
||||||
|
color_bits: Some(24),
|
||||||
|
float_color_buffer: false,
|
||||||
|
alpha_bits: Some(8),
|
||||||
|
depth_bits: Some(24),
|
||||||
|
stencil_bits: Some(8),
|
||||||
|
double_buffer: Some(true),
|
||||||
|
multisampling: None,
|
||||||
|
stereoscopy: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,11 +47,6 @@ error_chain! {
|
||||||
description("Failed to create a new EGLSurface")
|
description("Failed to create a new EGLSurface")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "The OpenGL context has been lost and needs to be recreated"]
|
|
||||||
ContextLost {
|
|
||||||
description("The OpenGL context has been lost and needs to be recreated")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "The required EGL extension is not supported by the underlying EGL implementation"]
|
#[doc = "The required EGL extension is not supported by the underlying EGL implementation"]
|
||||||
EglExtensionNotSupported(extensions: &'static [&'static str]) {
|
EglExtensionNotSupported(extensions: &'static [&'static str]) {
|
||||||
description("The required EGL extension is not supported by the underlying EGL implementation"),
|
description("The required EGL extension is not supported by the underlying EGL implementation"),
|
||||||
|
@ -74,11 +69,6 @@ error_chain! {
|
||||||
description("Index of plane is out of bounds for EGLImages")
|
description("Index of plane is out of bounds for EGLImages")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "This buffer is not mananged by EGL"]
|
|
||||||
BufferNotManaged {
|
|
||||||
description("This buffer is not mananged by EGL")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc = "Failed to create EGLImages from the buffer"]
|
#[doc = "Failed to create EGLImages from the buffer"]
|
||||||
EGLImageCreationFailed {
|
EGLImageCreationFailed {
|
||||||
description("Failed to create EGLImages from the buffer")
|
description("Failed to create EGLImages from the buffer")
|
||||||
|
|
|
@ -9,8 +9,8 @@ use super::GraphicsBackend;
|
||||||
use nix::libc::c_void;
|
use nix::libc::c_void;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use wayland_server::Display;
|
use wayland_server::Display;
|
||||||
|
use wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
|
|
||||||
pub use self::ffi::egl::types::EGLImage;
|
|
||||||
pub mod context;
|
pub mod context;
|
||||||
pub use self::context::EGLContext;
|
pub use self::context::EGLContext;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -20,6 +20,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::{EGLImages, BufferAccessError};
|
||||||
|
|
||||||
/// Error that can happen when swapping buffers.
|
/// Error that can happen when swapping buffers.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -182,5 +183,5 @@ pub trait EGLGraphicsBackend: GraphicsBackend {
|
||||||
/// `Display` multiple times, as only one context may be bound at any given time.
|
/// `Display` multiple times, as only one context may be bound at any given time.
|
||||||
fn unbind_wl_display(&self, display: &Display) -> ::std::result::Result<(), EglExtensionNotSupportedError>;
|
fn unbind_wl_display(&self, display: &Display) -> ::std::result::Result<(), EglExtensionNotSupportedError>;
|
||||||
|
|
||||||
// unsafe fn egl_image_to_texture(&self, image: ffi::egl::types::EGLImage, tex_id: c_uint) -> ::std::result::Result<(), EglExtensionNotSupportedError>;
|
fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, wayland::BufferAccessError>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,114 @@
|
||||||
use backend::graphics::egl::{EGLContext, EGLImage, ffi, native};
|
use backend::graphics::egl::{EGLContext, EglExtensionNotSupportedError, ffi, native};
|
||||||
use backend::graphics::egl::error::*;
|
use backend::graphics::egl::error::*;
|
||||||
|
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::rc::{Rc, Weak};
|
||||||
|
use std::fmt;
|
||||||
use wayland_server::{Display, Resource};
|
use wayland_server::{Display, Resource};
|
||||||
use wayland_server::protocol::wl_buffer::WlBuffer;
|
use wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
|
|
||||||
|
/// Error that can occur when accessing an EGL buffer
|
||||||
|
pub enum BufferAccessError {
|
||||||
|
/// This buffer is not managed by the EGL buffer
|
||||||
|
NotManaged(WlBuffer),
|
||||||
|
/// Failed to create EGLImages from the buffer
|
||||||
|
EGLImageCreationFailed,
|
||||||
|
/// The required EGL extension is not supported by the underlying EGL implementation
|
||||||
|
EglExtensionNotSupported(EglExtensionNotSupportedError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for BufferAccessError {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
|
match *self {
|
||||||
|
BufferAccessError::NotManaged(_) => write!(formatter, "BufferAccessError::NotManaged"),
|
||||||
|
BufferAccessError::EGLImageCreationFailed => write!(formatter, "BufferAccessError::EGLImageCreationFailed"),
|
||||||
|
BufferAccessError::EglExtensionNotSupported(ref err) => write!(formatter, "{:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for BufferAccessError {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
|
use ::std::error::Error;
|
||||||
|
match *self {
|
||||||
|
BufferAccessError::NotManaged(_) => write!(formatter, "{}", self.description()),
|
||||||
|
BufferAccessError::EGLImageCreationFailed => write!(formatter, "{}", self.description()),
|
||||||
|
BufferAccessError::EglExtensionNotSupported(ref err) => err.fmt(formatter),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::error::Error for BufferAccessError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
BufferAccessError::NotManaged(_) => "This buffer is not mananged by EGL",
|
||||||
|
BufferAccessError::EGLImageCreationFailed => "Failed to create EGLImages from the buffer",
|
||||||
|
BufferAccessError::EglExtensionNotSupported(ref err) => err.description(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&::std::error::Error> {
|
||||||
|
match *self {
|
||||||
|
BufferAccessError::EglExtensionNotSupported(ref err) => Some(err),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<EglExtensionNotSupportedError> for BufferAccessError {
|
||||||
|
fn from(error: EglExtensionNotSupportedError) -> Self {
|
||||||
|
BufferAccessError::EglExtensionNotSupported(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error that might happen when binding an EGLImage to a gl texture
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum TextureCreationError {
|
||||||
|
/// The given plane index is out of bounds
|
||||||
|
PlaneIndexOutOfBounds,
|
||||||
|
/// The OpenGL context has been lost and needs to be recreated.
|
||||||
|
///
|
||||||
|
/// All the objects associated to it (textures, buffers, programs, etc.)
|
||||||
|
/// need to be recreated from scratch.
|
||||||
|
///
|
||||||
|
/// Operations will have no effect. Functions that read textures, buffers, etc.
|
||||||
|
/// from OpenGL will return uninitialized data instead.
|
||||||
|
///
|
||||||
|
/// A context loss usually happens on mobile devices when the user puts the
|
||||||
|
/// application on sleep and wakes it up later. However any OpenGL implementation
|
||||||
|
/// can theoretically lose the context at any time.
|
||||||
|
ContextLost,
|
||||||
|
/// Failed to bind the EGLImage to the given texture
|
||||||
|
///
|
||||||
|
/// The given argument is the gl error code
|
||||||
|
TextureBindingFailed(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TextureCreationError {
|
||||||
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
|
||||||
|
use ::std::error::Error;
|
||||||
|
match *self {
|
||||||
|
TextureCreationError::ContextLost => write!(formatter, "{}", self.description()),
|
||||||
|
TextureCreationError::PlaneIndexOutOfBounds => write!(formatter, "{}", self.description()),
|
||||||
|
TextureCreationError::TextureBindingFailed(code) => write!(formatter, "{}. Gl error code: {:?}", self.description(), code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::error::Error for TextureCreationError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
TextureCreationError::ContextLost => "The context has been lost, it needs to be recreated",
|
||||||
|
TextureCreationError::PlaneIndexOutOfBounds => "This buffer is not mananged by EGL",
|
||||||
|
TextureCreationError::TextureBindingFailed(_) => "Failed to create EGLImages from the buffer",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&::std::error::Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
RGB = ffi::egl::TEXTURE_RGB as i32,
|
RGB = ffi::egl::TEXTURE_RGB as i32,
|
||||||
|
@ -40,15 +144,20 @@ impl EGLImages {
|
||||||
self.format.num_planes()
|
self.format.num_planes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn bind_to_tex(&self, plane: usize, tex_id: c_uint) -> Result<()> {
|
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() {
|
||||||
ffi::gl::EGLImageTargetTexture2DOES(tex_id, *self.images.get(plane).chain_err(|| ErrorKind::PlaneIndexOutOfBounds)?);
|
let mut old_tex_id: i32 = 0;
|
||||||
match ffi::egl::GetError() as u32 {
|
ffi::gl::GetIntegerv(ffi::gl::TEXTURE_BINDING_2D, &mut old_tex_id);
|
||||||
ffi::gl::NO_ERROR => Ok(()),
|
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, tex_id);
|
||||||
err => bail!(ErrorKind::Unknown(err)),
|
ffi::gl::EGLImageTargetTexture2DOES(ffi::gl::TEXTURE_2D, *self.images.get(plane).ok_or(TextureCreationError::PlaneIndexOutOfBounds)?);
|
||||||
}
|
let res = match ffi::egl::GetError() as u32 {
|
||||||
|
ffi::egl::SUCCESS => Ok(()),
|
||||||
|
err => Err(TextureCreationError::TextureBindingFailed(err)),
|
||||||
|
};
|
||||||
|
ffi::gl::BindTexture(ffi::gl::TEXTURE_2D, old_tex_id as u32);
|
||||||
|
res
|
||||||
} else {
|
} else {
|
||||||
bail!(ErrorKind::ContextLost)
|
Err(TextureCreationError::ContextLost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,6 +169,7 @@ impl Drop for EGLImages {
|
||||||
unsafe { ffi::egl::DestroyImageKHR(*display, image); }
|
unsafe { ffi::egl::DestroyImageKHR(*display, image); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.buffer.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,14 +221,17 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn egl_buffer_contents<T: native::NativeSurface>(&self, buffer: WlBuffer) -> Result<EGLImages> {
|
pub fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
||||||
|
if !self.wl_drm_support {
|
||||||
|
return Err(EglExtensionNotSupportedError(&["EGL_WL_bind_wayland_display"]).into());
|
||||||
|
}
|
||||||
if !self.egl_to_texture_support {
|
if !self.egl_to_texture_support {
|
||||||
bail!(ErrorKind::EglExtensionNotSupported(&["GL_OES_EGL_image"]));
|
return Err(EglExtensionNotSupportedError(&["GL_OES_EGL_image"]).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut format: i32 = 0;
|
let mut format: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } {
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::EGL_TEXTURE_FORMAT, &mut format as *mut _) == 0 } {
|
||||||
bail!(ErrorKind::BufferNotManaged);
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
let format = match format {
|
let format = match format {
|
||||||
x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB,
|
x if x == ffi::egl::TEXTURE_RGB as i32 => Format::RGB,
|
||||||
|
@ -132,16 +245,16 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
|
|
||||||
let mut width: i32 = 0;
|
let mut width: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } {
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WIDTH as i32, &mut width as *mut _) == 0 } {
|
||||||
bail!(ErrorKind::BufferNotManaged);
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut height: i32 = 0;
|
let mut height: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } {
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::HEIGHT as i32, &mut height as *mut _) == 0 } {
|
||||||
bail!(ErrorKind::BufferNotManaged);
|
return Err(BufferAccessError::NotManaged(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inverted: i32 = 0;
|
let mut inverted: i32 = 0;
|
||||||
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) == 0 } {
|
if unsafe { ffi::egl::QueryWaylandBufferWL(*self.display, buffer.ptr() as *mut _, ffi::egl::WAYLAND_Y_INVERTED_WL, &mut inverted as *mut _) != 0 } {
|
||||||
inverted = 1;
|
inverted = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,12 +270,12 @@ impl<B: native::Backend, N: native::NativeDisplay<B>> EGLContext<B, N> {
|
||||||
unsafe { ffi::egl::CreateImageKHR(
|
unsafe { ffi::egl::CreateImageKHR(
|
||||||
*self.display,
|
*self.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 {
|
||||||
bail!(ErrorKind::EGLImageCreationFailed);
|
return Err(BufferAccessError::EGLImageCreationFailed);
|
||||||
} else {
|
} else {
|
||||||
image
|
image
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! 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, EglExtensionNotSupportedError};
|
use backend::graphics::egl::{EGLGraphicsBackend, EGLContext, EGLSurface, BufferAccessError, PixelFormat, SwapBuffersError, EglExtensionNotSupportedError, EGLImages};
|
||||||
use backend::graphics::egl::error as egl_error;
|
use backend::graphics::egl::error as egl_error;
|
||||||
use backend::graphics::egl::native;
|
use backend::graphics::egl::native;
|
||||||
use backend::graphics::egl::context::{GlAttributes, PixelFormatRequirements};
|
use backend::graphics::egl::context::{GlAttributes, PixelFormatRequirements};
|
||||||
|
@ -18,6 +18,7 @@ use winit::{ElementState, Event, EventsLoop, KeyboardInput, MouseButton as Winit
|
||||||
MouseScrollDelta, Touch, TouchPhase, WindowBuilder, WindowEvent, Window as WinitWindow};
|
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 wayland_server::protocol::wl_buffer::WlBuffer;
|
||||||
|
|
||||||
error_chain! {
|
error_chain! {
|
||||||
errors {
|
errors {
|
||||||
|
@ -134,13 +135,7 @@ where
|
||||||
.chain_err(|| ErrorKind::InitFailed)?;
|
.chain_err(|| ErrorKind::InitFailed)?;
|
||||||
debug!(log, "Window created");
|
debug!(log, "Window created");
|
||||||
|
|
||||||
let reqs = PixelFormatRequirements {
|
let reqs = Default::default();
|
||||||
hardware_accelerated: Some(true),
|
|
||||||
color_bits: Some(24),
|
|
||||||
alpha_bits: Some(8),
|
|
||||||
..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 = EGLContext::<native::Wayland, WinitWindow>::new(
|
||||||
|
@ -277,12 +272,12 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fn egl_buffer_contents(&self, buffer: WlBuffer) -> ::std::result::Result<EGLImages, BufferAccessError> {
|
||||||
unsafe fn egl_image_to_texture(&self, image: EGLImage, tex_id: c_uint) -> ::std::result::Result<(), EglExtensionNotSupportedError> {
|
match *self.window {
|
||||||
self.window.rent(|egl| egl.head().egl_image_to_texture(image, tex_id))?;
|
Window::Wayland { ref context, .. } => context.egl_buffer_contents(buffer),
|
||||||
Ok(())
|
Window::X11 { ref context, .. } => context.egl_buffer_contents(buffer),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors that may happen when driving the event loop of `WinitInputBackend`
|
/// Errors that may happen when driving the event loop of `WinitInputBackend`
|
||||||
|
|
|
@ -72,9 +72,7 @@
|
||||||
//!
|
//!
|
||||||
//! As you can see in the previous example, in the end we are retrieving a token from
|
//! As you can see in the previous example, in the end we are retrieving a token from
|
||||||
//! the init function. This token is necessary to retrieve the metadata associated with
|
//! the init function. This token is necessary to retrieve the metadata associated with
|
||||||
//! a surface. It can be cloned, and is sendable accross threads (as long as your
|
//! a surface. It can be cloned. See `CompositorToken` for the details of what it enables you.
|
||||||
//! `Mydata` and `MyRoles` are `Send` too). See `CompositorToken` for
|
|
||||||
//! the details of what it enables you.
|
|
||||||
//!
|
//!
|
||||||
//! The surface metadata is held in the `SurfaceAttributes` struct. In contains double-buffered
|
//! The surface metadata is held in the `SurfaceAttributes` struct. In contains double-buffered
|
||||||
//! state pending from the client as defined by the protocol for `wl_surface`, as well as your
|
//! state pending from the client as defined by the protocol for `wl_surface`, as well as your
|
||||||
|
@ -248,9 +246,6 @@ pub struct CompositorToken<U, R, ID> {
|
||||||
_idata: ::std::marker::PhantomData<*mut ID>,
|
_idata: ::std::marker::PhantomData<*mut ID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<U: Send, R: Send, ID> Send for CompositorToken<U, R, ID> {}
|
|
||||||
unsafe impl<U: Send, R: Send, ID> Sync for CompositorToken<U, R, ID> {}
|
|
||||||
|
|
||||||
// we implement them manually because #[derive(..)] would require
|
// we implement them manually because #[derive(..)] would require
|
||||||
// U: Clone and R: Clone
|
// U: Clone and R: Clone
|
||||||
impl<U, R, ID> Copy for CompositorToken<U, R, ID> {}
|
impl<U, R, ID> Copy for CompositorToken<U, R, ID> {}
|
||||||
|
@ -270,7 +265,7 @@ impl<U, R, ID> CompositorToken<U, R, ID> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<U: Send + 'static, R: Send + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
impl<U: 'static, R: 'static, ID: 'static> CompositorToken<U, R, ID> {
|
||||||
/// Access the data of a surface
|
/// Access the data of a surface
|
||||||
///
|
///
|
||||||
/// The closure will be called with the contents of the data associated with this surface.
|
/// The closure will be called with the contents of the data associated with this surface.
|
||||||
|
|
Loading…
Reference in New Issue