diff --git a/anvil/src/glium_drawer.rs b/anvil/src/glium_drawer.rs index 201ff8d..30c5e3c 100644 --- a/anvil/src/glium_drawer.rs +++ b/anvil/src/glium_drawer.rs @@ -6,10 +6,16 @@ use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::error::Result as EGLResult; use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLImages, EGLWaylandExtensions, Format}; use smithay::backend::graphics::glium::GliumGraphicsBackend; +use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; +use smithay::wayland::compositor::roles::Role; use smithay::wayland_server::Display; use std::cell::Ref; +use slog::Logger; + +use shell::{Buffer, MyCompositorToken, MyWindowMap}; + #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], @@ -190,3 +196,95 @@ impl EGLWaylandExtension self.display.bind_wl_display(display) } } + +impl GliumDrawer { + pub fn draw_windows(&self, window_map: &MyWindowMap, compositor_token: MyCompositorToken, log: &Logger) { + let mut frame = self.draw(); + 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 + { + let screen_dimensions = self.borrow().get_framebuffer_dimensions(); + window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { + if let Some(wl_surface) = toplevel_surface.get_surface() { + // this surface is a root of a subsurface tree that needs to be drawn + compositor_token + .with_surface_tree_upward( + wl_surface, + initial_place, + |_surface, attributes, role, &(mut x, mut y)| { + // there is actually something to draw ! + if attributes.user_data.texture.is_none() { + let mut remove = false; + match attributes.user_data.buffer { + Some(Buffer::Egl { ref images }) => { + match images.format { + Format::RGB | Format::RGBA => { + attributes.user_data.texture = + self.texture_from_egl(&images); + } + _ => { + // we don't handle the more complex formats here. + attributes.user_data.texture = None; + remove = true; + } + }; + } + Some(Buffer::Shm { ref data, ref size }) => { + attributes.user_data.texture = + Some(self.texture_from_mem(data, *size)); + } + _ => {} + } + if remove { + attributes.user_data.buffer = None; + } + } + + if let Some(ref texture) = attributes.user_data.texture { + if let Ok(subdata) = Role::::data(role) { + x += subdata.location.0; + y += subdata.location.1; + } + self.render_texture( + &mut frame, + texture, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => images.y_inverted, + Buffer::Shm { .. } => false, + }, + match *attributes.user_data.buffer.as_ref().unwrap() { + Buffer::Egl { ref images } => (images.width, images.height), + Buffer::Shm { ref size, .. } => *size, + }, + (x, y), + screen_dimensions, + ::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() + }, + ); + TraversalAction::DoChildren((x, y)) + } else { + // we are not display, so our children are neither + TraversalAction::SkipChildren + } + }, + ) + .unwrap(); + } + }); + } + if let Err(err) = frame.finish() { + error!(log, "Error during rendering: {:?}", err); + } + } +} diff --git a/anvil/src/raw_drm.rs b/anvil/src/raw_drm.rs index 2b96312..e282a1d 100644 --- a/anvil/src/raw_drm.rs +++ b/anvil/src/raw_drm.rs @@ -12,18 +12,16 @@ use smithay::drm::control::crtc; use smithay::drm::control::encoder::Info as EncoderInfo; use smithay::drm::result::Error as DrmError; use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler}; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; -use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; +use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; +use smithay::wayland::compositor::CompositorToken; use smithay::wayland::shm::init_shm_global; use smithay::wayland_server::{Display, EventLoop}; -use glium::{Blend, Surface}; +use glium::Surface; use slog::Logger; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; +use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; #[derive(Debug)] pub struct Card(File); @@ -153,82 +151,11 @@ impl DrmHandler for DrmHandlerImpl { _frame: u32, _duration: Duration, ) { - let mut frame = self.drawer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = self.drawer.borrow().get_framebuffer_dimensions(); - self.window_map - .borrow() - .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - self.compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - self.drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(self.drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - info!(self.logger, "Render window"); - self.drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => (images.width, images.height), - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - Blend::alpha_blending(), - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }); - } - frame.finish().unwrap(); + self.drawer.draw_windows( + &*self.window_map.borrow(), + self.compositor_token, + &self.logger, + ); } fn error(&mut self, _device: &mut DrmDevice, error: DrmError) { diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 811f297..ad5940e 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -24,6 +24,8 @@ define_roles!(Roles => [ XdgSurface, XdgSurfaceRole ] [ ShellSurface, ShellSurfa pub type MyWindowMap = WindowMap) -> Option<(i32, i32)>>; +pub type MyCompositorToken = CompositorToken; + pub fn init_shell( display: &mut Display, looptoken: LoopToken, diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 7122e5e..1dc710e 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use glium::{Blend, Surface}; +use glium::Surface; use smithay::image::{ImageBuffer, Rgba}; @@ -20,15 +20,13 @@ use smithay::drm::control::encoder::Info as EncoderInfo; use smithay::drm::result::Error as DrmError; use smithay::backend::drm::{DevPath, DrmBackend, DrmDevice, DrmHandler}; use smithay::backend::graphics::GraphicsBackend; -use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions, Format}; +use smithay::backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions}; use smithay::backend::input::InputBackend; use smithay::backend::libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface}; use smithay::backend::session::{Session, SessionNotifier}; use smithay::backend::session::auto::{auto_session_bind, AutoSession}; use smithay::backend::udev::{primary_gpu, udev_backend_bind, SessionFdDrmDevice, UdevBackend, UdevHandler}; -use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; +use smithay::wayland::compositor::CompositorToken; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::wayland::seat::Seat; use smithay::wayland::shm::init_shm_global; @@ -38,7 +36,7 @@ use smithay::wayland_server::protocol::wl_output; use smithay::input::Libinput; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer, MyWindowMap, Roles, SurfaceData}; +use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; use input_handler::AnvilInputHandler; pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(), ()> { @@ -337,86 +335,12 @@ impl DrmHandler for DrmHandlerImpl { .borrow() .set_cursor_position(x.trunc().abs() as u32, y.trunc().abs() as u32); } - let mut frame = drawer.draw(); - frame.clear_color(0.8, 0.8, 0.9, 1.0); - // redraw the frame, in a simple but inneficient way - { - let screen_dimensions = drawer.borrow().get_framebuffer_dimensions(); - self.window_map.borrow().with_windows_from_bottom_to_top( - |toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - self.compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - info!(self.logger, "Render window"); - drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => { - (images.width, images.height) - } - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - Blend::alpha_blending(), - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }, - ); - } - if let Err(err) = frame.finish() { - error!(self.logger, "Error during rendering: {:?}", err); - } + drawer.draw_windows( + &*self.window_map.borrow(), + self.compositor_token, + &self.logger, + ); } } diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 2c7540e..b737bf3 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -5,22 +5,18 @@ use std::sync::atomic::AtomicBool; use smithay::wayland::shm::init_shm_global; use smithay::wayland::seat::Seat; -use smithay::wayland::compositor::{SubsurfaceRole, TraversalAction}; -use smithay::wayland::compositor::roles::Role; use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::backend::input::InputBackend; use smithay::backend::winit; use smithay::backend::graphics::egl::EGLGraphicsBackend; -use smithay::backend::graphics::egl::wayland::{EGLWaylandExtensions, Format}; +use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::protocol::wl_output; -use glium::Surface; - use slog::Logger; use glium_drawer::GliumDrawer; -use shell::{init_shell, Buffer}; +use shell::init_shell; use input_handler::AnvilInputHandler; pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) -> Result<(), ()> { @@ -103,93 +99,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger) loop { input.dispatch_new_events().unwrap(); - let mut frame = drawer.draw(); - 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 - { - let screen_dimensions = drawer.borrow().get_framebuffer_dimensions(); - window_map - .borrow() - .with_windows_from_bottom_to_top(|toplevel_surface, initial_place| { - if let Some(wl_surface) = toplevel_surface.get_surface() { - // this surface is a root of a subsurface tree that needs to be drawn - compositor_token - .with_surface_tree_upward( - wl_surface, - initial_place, - |_surface, attributes, role, &(mut x, mut y)| { - // there is actually something to draw ! - if attributes.user_data.texture.is_none() { - let mut remove = false; - match attributes.user_data.buffer { - Some(Buffer::Egl { ref images }) => { - match images.format { - Format::RGB | Format::RGBA => { - attributes.user_data.texture = - drawer.texture_from_egl(&images); - } - _ => { - // we don't handle the more complex formats here. - attributes.user_data.texture = None; - remove = true; - } - }; - } - Some(Buffer::Shm { ref data, ref size }) => { - attributes.user_data.texture = - Some(drawer.texture_from_mem(data, *size)); - } - _ => {} - } - if remove { - attributes.user_data.buffer = None; - } - } - - if let Some(ref texture) = attributes.user_data.texture { - if let Ok(subdata) = Role::::data(role) { - x += subdata.location.0; - y += subdata.location.1; - } - drawer.render_texture( - &mut frame, - texture, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => images.y_inverted, - Buffer::Shm { .. } => false, - }, - match *attributes.user_data.buffer.as_ref().unwrap() { - Buffer::Egl { ref images } => (images.width, images.height), - Buffer::Shm { ref size, .. } => *size, - }, - (x, y), - screen_dimensions, - ::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() - }, - ); - TraversalAction::DoChildren((x, y)) - } else { - // we are not display, so our children are neither - TraversalAction::SkipChildren - } - }, - ) - .unwrap(); - } - }); - } - frame.finish().unwrap(); + drawer.draw_windows(&*window_map.borrow(), compositor_token, &log); event_loop.dispatch(Some(16)).unwrap(); display.flush_clients();