anvil: Update to new renderer changes

This commit is contained in:
Victor Brekenfeld 2021-05-13 19:59:47 +02:00
parent f0e7ff3312
commit b4f216d7b8
7 changed files with 118 additions and 292 deletions

View File

@ -1,172 +0,0 @@
#[cfg(feature = "egl")]
use std::{cell::RefCell, rc::Rc};
use std::sync::mpsc::Sender;
#[cfg(feature = "udev")]
use smithay::backend::renderer::{Renderer, Texture};
#[cfg(feature = "udev")]
use smithay::reexports::nix::libc::dev_t;
#[cfg(feature = "udev")]
use std::collections::HashMap;
#[cfg(feature = "egl")]
use smithay::backend::egl::{display::EGLBufferReader, BufferAccessError as EGLBufferAccessError, EGLBuffer};
use smithay::{
reexports::wayland_server::protocol::wl_buffer::WlBuffer,
wayland::shm::{with_buffer_contents as shm_buffer_contents, BufferAccessError},
};
/// Utilities for working with `WlBuffer`s.
#[derive(Clone)]
pub struct BufferUtils {
#[cfg(feature = "egl")]
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
log: ::slog::Logger,
}
impl BufferUtils {
/// Creates a new `BufferUtils`.
#[cfg(feature = "egl")]
pub fn new(egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>, log: ::slog::Logger) -> Self {
Self {
egl_buffer_reader,
log,
}
}
/// Creates a new `BufferUtils`.
#[cfg(not(feature = "egl"))]
pub fn new(log: ::slog::Logger) -> Self {
Self { log }
}
/// Returns the dimensions of an image stored in the buffer.
#[cfg(feature = "egl")]
pub fn dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
// Try to retrieve the EGL dimensions of this buffer, and, if that fails, the shm dimensions.
self.egl_buffer_reader
.borrow()
.as_ref()
.and_then(|display| display.egl_buffer_dimensions(buffer))
.or_else(|| self.shm_buffer_dimensions(buffer).ok())
}
/// Returns the dimensions of an image stored in the buffer.
#[cfg(not(feature = "egl"))]
pub fn dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
self.shm_buffer_dimensions(buffer).ok()
}
/// Returns the dimensions of an image stored in the shm buffer.
fn shm_buffer_dimensions(&self, buffer: &WlBuffer) -> Result<(i32, i32), BufferAccessError> {
shm_buffer_contents(buffer, |_, data| (data.width, data.height)).map_err(|err| {
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
err
})
}
#[cfg(feature = "egl")]
pub fn load_buffer<T>(&self, buffer: WlBuffer) -> Result<BufferTextures<T>, WlBuffer> {
let egl_buffer = if let Some(reader) = &self.egl_buffer_reader.borrow().as_ref() {
match reader.egl_buffer_contents(&buffer) {
Ok(egl) => Some(egl),
Err(EGLBufferAccessError::NotManaged(_)) => None,
Err(err) => {
error!(self.log, "EGL error"; "err" => format!("{:?}", err));
return Err(buffer);
}
}
} else { None };
Ok(BufferTextures {
buffer,
textures: HashMap::new(),
callbacks: HashMap::new(),
egl: egl_buffer, // I guess we need to keep this alive ?
})
}
#[cfg(not(feature = "egl"))]
pub fn load_buffer<T>(&self, buffer: WlBuffer) -> Result<BufferTextures<T>, WlBuffer> {
Ok(BufferTextures {
buffer,
textures: HashMap::new(),
callbacks: HashMap::new(),
})
}
}
#[cfg(feature = "udev")]
pub struct BufferTextures<T> {
buffer: WlBuffer,
pub textures: HashMap<dev_t, T>,
callbacks: HashMap<dev_t, Sender<T>>,
#[cfg(feature = "egl")]
egl: Option<EGLBuffer>,
}
#[cfg(feature = "udev")]
impl<T: Texture> BufferTextures<T> {
#[cfg(feature = "egl")]
pub fn load_texture<'a, R: Renderer<TextureId = T>>(
&'a mut self,
id: u64,
renderer: &mut R,
texture_destruction_callback: &Sender<T>,
) -> Result<&'a T, R::Error> {
if self.textures.contains_key(&id) {
return Ok(&self.textures[&id]);
}
if let Some(buffer) = self.egl.as_ref() {
//EGL buffer
let texture = renderer.import_egl(&buffer)?;
if let Some(old_texture) = self.textures.insert(id, texture) {
let _ = renderer.destroy_texture(old_texture);
}
self.callbacks.insert(id, texture_destruction_callback.clone());
Ok(&self.textures[&id])
} else {
self.load_shm_texture(id, renderer, texture_destruction_callback)
}
}
#[cfg(not(feature = "egl"))]
pub fn load_texture<'a, R: Renderer<TextureId = T>>(
&'a mut self,
id: u64,
renderer: &mut R,
texture_destruction_callback: &Sender<T>,
) -> Result<&'a T, R::Error> {
if self.textures.contains_key(&id) {
return Ok(&self.textures[&id]);
}
self.load_shm_texture(id, renderer, texture_destruction_callback)
}
fn load_shm_texture<'a, R: Renderer<TextureId = T>>(
&'a mut self,
id: u64,
renderer: &mut R,
texture_destruction_callback: &Sender<T>,
) -> Result<&'a T, R::Error> {
let texture = renderer.import_shm(&self.buffer)?;
if let Some(old_texture) = self.textures.insert(id, texture) {
let _ = renderer.destroy_texture(old_texture)?;
}
self.callbacks.insert(id, texture_destruction_callback.clone());
Ok(&self.textures[&id])
}
}
#[cfg(feature = "udev")]
impl<T> Drop for BufferTextures<T> {
fn drop(&mut self) {
self.buffer.release();
for (id, texture) in self.textures.drain() {
self.callbacks.get(&id).unwrap().send(texture).unwrap();
}
}
}

View File

@ -1,12 +1,15 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use std::{cell::RefCell, rc::Rc, sync::mpsc::Sender}; use std::{cell::RefCell, rc::Rc};
use slog::Logger; use slog::Logger;
use smithay::{ use smithay::{
backend::renderer::{Renderer, Texture, Transform}, backend::{
backend::SwapBuffersError, egl::display::EGLBufferReader,
reexports::{calloop::LoopHandle, wayland_server::protocol::wl_surface}, renderer::{Renderer, Texture, Transform},
SwapBuffersError,
},
reexports::{calloop::LoopHandle, wayland_server::protocol::{wl_buffer,wl_surface}},
utils::Rectangle, utils::Rectangle,
wayland::{ wayland::{
compositor::{roles::Role, SubsurfaceRole, TraversalAction}, compositor::{roles::Role, SubsurfaceRole, TraversalAction},
@ -15,15 +18,23 @@ use smithay::{
}, },
}; };
use crate::buffer_utils::{BufferTextures, BufferUtils};
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData}; use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};
struct BufferTextures<T> {
buffer: wl_buffer::WlBuffer,
texture: T,
}
impl<T> Drop for BufferTextures<T> {
fn drop(&mut self) {
self.buffer.release();
}
}
pub fn draw_cursor<R, E, T>( pub fn draw_cursor<R, E, T>(
renderer: &mut R, renderer: &mut R,
renderer_id: u64,
texture_destruction_callback: &Sender<T>,
buffer_utils: &BufferUtils,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
egl_buffer_reader: Option<&EGLBufferReader>,
(x, y): (i32, i32), (x, y): (i32, i32),
token: MyCompositorToken, token: MyCompositorToken,
log: &Logger, log: &Logger,
@ -45,10 +56,8 @@ where
}; };
draw_surface_tree( draw_surface_tree(
renderer, renderer,
renderer_id,
texture_destruction_callback,
buffer_utils,
surface, surface,
egl_buffer_reader,
(x - dx, y - dy), (x - dx, y - dy),
token, token,
log, log,
@ -57,10 +66,8 @@ where
fn draw_surface_tree<R, E, T>( fn draw_surface_tree<R, E, T>(
renderer: &mut R, renderer: &mut R,
renderer_id: u64,
texture_destruction_callback: &Sender<T>,
buffer_utils: &BufferUtils,
root: &wl_surface::WlSurface, root: &wl_surface::WlSurface,
egl_buffer_reader: Option<&EGLBufferReader>,
location: (i32, i32), location: (i32, i32),
compositor_token: MyCompositorToken, compositor_token: MyCompositorToken,
log: &Logger, log: &Logger,
@ -81,12 +88,13 @@ where
let mut data = data.borrow_mut(); let mut data = data.borrow_mut();
if data.texture.is_none() { if data.texture.is_none() {
if let Some(buffer) = data.current_state.buffer.take() { if let Some(buffer) = data.current_state.buffer.take() {
match buffer_utils.load_buffer::<R::TextureId>(buffer) { match renderer.import_buffer(&buffer, egl_buffer_reader) {
Ok(m) => data.texture = Some(Box::new(m) as Box<dyn std::any::Any + 'static>), Ok(m) => data.texture = Some(Box::new(BufferTextures { buffer, texture: m }) as Box<dyn std::any::Any + 'static>),
// there was an error reading the buffer, release it, we // there was an error reading the buffer, release it, we
// already logged the error // already logged the error
Err(err) => { Err(err) => {
warn!(log, "Error loading buffer: {:?}", err); warn!(log, "Error loading buffer: {:?}", err);
buffer.release();
} }
}; };
} }
@ -135,7 +143,7 @@ where
if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() { if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
let mut data = data.borrow_mut(); let mut data = data.borrow_mut();
let (sub_x, sub_y) = data.current_state.sub_location; let (sub_x, sub_y) = data.current_state.sub_location;
if let Some(buffer_textures) = data if let Some(texture) = data
.texture .texture
.as_mut() .as_mut()
.and_then(|x| x.downcast_mut::<BufferTextures<T>>()) .and_then(|x| x.downcast_mut::<BufferTextures<T>>())
@ -146,11 +154,8 @@ where
x += sub_x; x += sub_x;
y += sub_y; y += sub_y;
} }
let texture = buffer_textures
.load_texture(renderer_id, renderer, texture_destruction_callback)
.unwrap();
if let Err(err) = if let Err(err) =
renderer.render_texture_at(texture, (x, y), Transform::Normal /* TODO */, 1.0) renderer.render_texture_at(&texture.texture, (x, y), Transform::Normal /* TODO */, 1.0)
{ {
result = Err(err.into()); result = Err(err.into());
} }
@ -165,9 +170,7 @@ where
pub fn draw_windows<R, E, T>( pub fn draw_windows<R, E, T>(
renderer: &mut R, renderer: &mut R,
renderer_id: u64, egl_buffer_reader: Option<&EGLBufferReader>,
texture_destruction_callback: &Sender<T>,
buffer_utils: &BufferUtils,
window_map: &MyWindowMap, window_map: &MyWindowMap,
output_rect: Option<Rectangle>, output_rect: Option<Rectangle>,
compositor_token: MyCompositorToken, compositor_token: MyCompositorToken,
@ -193,10 +196,8 @@ where
// 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
if let Err(err) = draw_surface_tree( if let Err(err) = draw_surface_tree(
renderer, renderer,
renderer_id,
texture_destruction_callback,
buffer_utils,
&wl_surface, &wl_surface,
egl_buffer_reader,
initial_place, initial_place,
compositor_token, compositor_token,
log, log,
@ -211,10 +212,8 @@ where
pub fn draw_dnd_icon<R, E, T>( pub fn draw_dnd_icon<R, E, T>(
renderer: &mut R, renderer: &mut R,
renderer_id: u64,
texture_destruction_callback: &Sender<T>,
buffer_utils: &BufferUtils,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
egl_buffer_reader: Option<&EGLBufferReader>,
(x, y): (i32, i32), (x, y): (i32, i32),
token: MyCompositorToken, token: MyCompositorToken,
log: &::slog::Logger, log: &::slog::Logger,
@ -232,10 +231,8 @@ where
} }
draw_surface_tree( draw_surface_tree(
renderer, renderer,
renderer_id,
texture_destruction_callback,
buffer_utils,
surface, surface,
egl_buffer_reader,
(x, y), (x, y),
token, token,
log, log,

View File

@ -10,7 +10,6 @@ use std::{cell::RefCell, rc::Rc};
use slog::Drain; use slog::Drain;
use smithay::reexports::{calloop::EventLoop, wayland_server::Display}; use smithay::reexports::{calloop::EventLoop, wayland_server::Display};
mod buffer_utils;
mod drawing; mod drawing;
mod input_handler; mod input_handler;
mod shell; mod shell;

View File

@ -5,6 +5,7 @@ use std::{
}; };
use smithay::{ use smithay::{
backend::renderer::buffer_dimensions,
reexports::{ reexports::{
wayland_protocols::xdg_shell::server::xdg_toplevel, wayland_protocols::xdg_shell::server::xdg_toplevel,
wayland_server::{ wayland_server::{
@ -32,11 +33,10 @@ use smithay::{
Serial, Serial,
}, },
}; };
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use crate::{ use crate::window_map::{Kind as SurfaceKind, WindowMap};
buffer_utils::BufferUtils,
window_map::{Kind as SurfaceKind, WindowMap},
};
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
use crate::xwayland::X11SurfaceRole; use crate::xwayland::X11SurfaceRole;
@ -308,7 +308,12 @@ pub struct ShellHandles {
pub window_map: Rc<RefCell<MyWindowMap>>, pub window_map: Rc<RefCell<MyWindowMap>>,
} }
pub fn init_shell(display: &mut Display, buffer_utils: BufferUtils, log: ::slog::Logger) -> ShellHandles { pub fn init_shell(
display: &mut Display,
#[cfg(feature = "egl")]
egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
log: ::slog::Logger
) -> ShellHandles {
// TODO: this is awkward... // TODO: this is awkward...
let almost_window_map = Rc::new(RefCell::new(None::<Rc<RefCell<MyWindowMap>>>)); let almost_window_map = Rc::new(RefCell::new(None::<Rc<RefCell<MyWindowMap>>>));
let almost_window_map_compositor = almost_window_map.clone(); let almost_window_map_compositor = almost_window_map.clone();
@ -320,7 +325,14 @@ pub fn init_shell(display: &mut Display, buffer_utils: BufferUtils, log: ::slog:
SurfaceEvent::Commit => { SurfaceEvent::Commit => {
let window_map = almost_window_map_compositor.borrow(); let window_map = almost_window_map_compositor.borrow();
let window_map = window_map.as_ref().unwrap(); let window_map = window_map.as_ref().unwrap();
surface_commit(&surface, ctoken, &buffer_utils, &*window_map) #[cfg(feature = "egl")]
{
surface_commit(&surface, ctoken, egl_reader.borrow().as_ref(), &*window_map)
}
#[cfg(not(feature = "egl"))]
{
surface_commit(&surface, ctoken, &*window_map)
}
} }
}, },
log.clone(), log.clone(),
@ -782,7 +794,8 @@ impl SurfaceData {
fn surface_commit( fn surface_commit(
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
token: CompositorToken<Roles>, token: CompositorToken<Roles>,
buffer_utils: &BufferUtils, #[cfg(feature = "egl")]
egl_reader: Option<&EGLBufferReader>,
window_map: &RefCell<MyWindowMap>, window_map: &RefCell<MyWindowMap>,
) { ) {
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
@ -834,7 +847,14 @@ fn surface_commit(
match attributes.buffer.take() { match attributes.buffer.take() {
Some(BufferAssignment::NewBuffer { buffer, .. }) => { Some(BufferAssignment::NewBuffer { buffer, .. }) => {
// new contents // new contents
next_state.dimensions = buffer_utils.dimensions(&buffer); #[cfg(feature = "egl")]
{
next_state.dimensions = buffer_dimensions(&buffer, egl_reader);
}
#[cfg(not(feature = "egl"))]
{
next_state.dimensions = buffer_dimensions(&buffer, None);
}
next_state.buffer = Some(buffer); next_state.buffer = Some(buffer);
} }
Some(BufferAssignment::Removed) => { Some(BufferAssignment::Removed) => {

View File

@ -27,12 +27,14 @@ use smithay::{
use smithay::backend::session::{auto::AutoSession, Session}; use smithay::backend::session::{auto::AutoSession, Session};
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
use smithay::xwayland::XWayland; use smithay::xwayland::XWayland;
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
#[cfg(feature = "udev")] #[cfg(feature = "udev")]
use crate::udev::MyOutput; use crate::udev::MyOutput;
#[cfg(feature = "xwayland")] #[cfg(feature = "xwayland")]
use crate::xwayland::XWm; use crate::xwayland::XWm;
use crate::{buffer_utils::BufferUtils, shell::init_shell}; use crate::shell::init_shell;
pub struct AnvilState { pub struct AnvilState {
pub socket_name: String, pub socket_name: String,
@ -63,7 +65,7 @@ impl AnvilState {
pub fn init( pub fn init(
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
handle: LoopHandle<AnvilState>, handle: LoopHandle<AnvilState>,
buffer_utils: BufferUtils, #[cfg(feature = "egl")] egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
#[cfg(feature = "udev")] session: Option<AutoSession>, #[cfg(feature = "udev")] session: Option<AutoSession>,
#[cfg(not(feature = "udev"))] _session: Option<()>, #[cfg(not(feature = "udev"))] _session: Option<()>,
#[cfg(feature = "udev")] output_map: Option<Rc<RefCell<Vec<MyOutput>>>>, #[cfg(feature = "udev")] output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
@ -96,7 +98,10 @@ impl AnvilState {
init_shm_global(&mut display.borrow_mut(), vec![], log.clone()); init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
let shell_handles = init_shell(&mut display.borrow_mut(), buffer_utils, log.clone()); #[cfg(feature = "egl")]
let shell_handles = init_shell(&mut display.borrow_mut(), egl_reader, log.clone());
#[cfg(not(feature = "egl"))]
let shell_handles = init_shell(&mut display.borrow_mut(), log.clone());
let socket_name = display let socket_name = display
.borrow_mut() .borrow_mut()

View File

@ -5,7 +5,7 @@ use std::{
os::unix::io::{AsRawFd, RawFd}, os::unix::io::{AsRawFd, RawFd},
path::PathBuf, path::PathBuf,
rc::Rc, rc::Rc,
sync::{atomic::Ordering, mpsc, Arc, Mutex}, sync::{atomic::Ordering, Arc, Mutex},
time::Duration, time::Duration,
}; };
@ -14,15 +14,15 @@ use slog::Logger;
use smithay::{ use smithay::{
backend::{ backend::{
drm::{device_bind, DevPath, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface}, drm::{device_bind, DeviceHandler, DrmDevice, DrmError, DrmRenderSurface},
egl::{display::EGLBufferReader, EGLContext, EGLDisplay}, egl::{EGLContext, EGLDisplay},
libinput::{LibinputInputBackend, LibinputSessionInterface}, libinput::{LibinputInputBackend, LibinputSessionInterface},
renderer::{ renderer::{
gles2::{Gles2Renderer, Gles2Texture}, gles2::{Gles2Renderer, Gles2Texture},
Renderer, Transform, Renderer, Transform,
}, },
session::{auto::AutoSession, Session, Signal as SessionSignal}, session::{auto::AutoSession, Session, Signal as SessionSignal},
udev::{primary_gpu, UdevBackend, UdevEvent}, udev::{UdevBackend, UdevEvent},
SwapBuffersError, SwapBuffersError,
}, },
reexports::{ reexports::{
@ -56,8 +56,11 @@ use smithay::{
seat::CursorImageStatus, seat::CursorImageStatus,
}, },
}; };
#[cfg(feature = "egl")]
use smithay::{
backend::{drm::DevPath, egl::display::EGLBufferReader, udev::primary_gpu},
};
use crate::buffer_utils::BufferUtils;
use crate::drawing::*; use crate::drawing::*;
use crate::shell::{MyWindowMap, Roles}; use crate::shell::{MyWindowMap, Roles};
use crate::state::AnvilState; use crate::state::AnvilState;
@ -87,11 +90,6 @@ pub fn run_udev(
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
let egl_buffer_reader = Rc::new(RefCell::new(None)); let egl_buffer_reader = Rc::new(RefCell::new(None));
#[cfg(feature = "egl")]
let buffer_utils = BufferUtils::new(egl_buffer_reader.clone(), log.clone());
#[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone());
let output_map = Rc::new(RefCell::new(Vec::new())); let output_map = Rc::new(RefCell::new(Vec::new()));
/* /*
@ -106,7 +104,8 @@ pub fn run_udev(
let mut state = AnvilState::init( let mut state = AnvilState::init(
display.clone(), display.clone(),
event_loop.handle(), event_loop.handle(),
buffer_utils.clone(), #[cfg(feature = "egl")]
egl_buffer_reader.clone(),
Some(session), Some(session),
Some(output_map.clone()), Some(output_map.clone()),
log.clone(), log.clone(),
@ -115,21 +114,19 @@ pub fn run_udev(
/* /*
* Initialize the udev backend * Initialize the udev backend
*/ */
let primary_gpu = primary_gpu(&state.seat_name).unwrap_or_default();
let bytes = include_bytes!("../resources/cursor2.rgba"); let bytes = include_bytes!("../resources/cursor2.rgba");
let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?; let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?;
let mut udev_handler = UdevHandlerImpl { let mut udev_handler = UdevHandlerImpl {
compositor_token: state.ctoken, compositor_token: state.ctoken,
buffer_utils,
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
egl_buffer_reader, egl_buffer_reader,
session: state.session.clone().unwrap(), session: state.session.clone().unwrap(),
backends: HashMap::new(), backends: HashMap::new(),
output_map, output_map,
display: display.clone(), display: display.clone(),
primary_gpu, #[cfg(feature = "egl")]
primary_gpu: primary_gpu(&state.seat_name).unwrap_or_default(),
window_map: state.window_map.clone(), window_map: state.window_map.clone(),
pointer_location: state.pointer_location.clone(), pointer_location: state.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(),
@ -282,12 +279,12 @@ struct BackendData {
struct UdevHandlerImpl<Data: 'static> { struct UdevHandlerImpl<Data: 'static> {
compositor_token: CompositorToken<Roles>, compositor_token: CompositorToken<Roles>,
buffer_utils: BufferUtils,
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>, egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
session: AutoSession, session: AutoSession,
backends: HashMap<dev_t, BackendData>, backends: HashMap<dev_t, BackendData>,
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
#[cfg(feature = "egl")]
primary_gpu: Option<PathBuf>, primary_gpu: Option<PathBuf>,
window_map: Rc<RefCell<MyWindowMap>>, window_map: Rc<RefCell<MyWindowMap>>,
output_map: Rc<RefCell<Vec<MyOutput>>>, output_map: Rc<RefCell<Vec<MyOutput>>>,
@ -453,10 +450,12 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
} }
}; };
#[cfg(feature = "egl")]
let is_primary = path.canonicalize().ok() == self.primary_gpu;
// init hardware acceleration on the primary gpu. // init hardware acceleration on the primary gpu.
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
{ {
if path.canonicalize().ok() == self.primary_gpu { if is_primary {
info!( info!(
self.logger, self.logger,
"Initializing EGL Hardware Acceleration via {:?}", path "Initializing EGL Hardware Acceleration via {:?}", path
@ -501,10 +500,10 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
// to introduce reference cycles with Rc. Be sure about your drop order // to introduce reference cycles with Rc. Be sure about your drop order
let renderer = Rc::new(DrmRenderer { let renderer = Rc::new(DrmRenderer {
device_id, device_id,
buffer_utils: self.buffer_utils.clone(), #[cfg(feature = "egl")]
egl_buffer_reader: if is_primary { self.egl_buffer_reader.borrow().clone() } else { None },
compositor_token: self.compositor_token, compositor_token: self.compositor_token,
backends: backends.clone(), backends: backends.clone(),
texture_destruction_callback: mpsc::channel(),
window_map: self.window_map.clone(), window_map: self.window_map.clone(),
output_map: self.output_map.clone(), output_map: self.output_map.clone(),
pointer_location: self.pointer_location.clone(), pointer_location: self.pointer_location.clone(),
@ -595,12 +594,12 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
.borrow_mut() .borrow_mut()
.retain(|output| output.device_id != device); .retain(|output| output.device_id != device);
let device = self.loop_handle.remove(backend_data.event_source).unwrap(); let _device = self.loop_handle.remove(backend_data.event_source).unwrap();
// don't use hardware acceleration anymore, if this was the primary gpu // don't use hardware acceleration anymore, if this was the primary gpu
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
{ {
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.egl_buffer_reader.borrow_mut() = None; *self.egl_buffer_reader.borrow_mut() = None;
} }
} }
@ -641,10 +640,10 @@ impl<Data: 'static> DrmRendererSessionListener<Data> {
pub struct DrmRenderer { pub struct DrmRenderer {
device_id: dev_t, device_id: dev_t,
buffer_utils: BufferUtils, #[cfg(feature = "egl")]
egl_buffer_reader: Option<EGLBufferReader>,
compositor_token: CompositorToken<Roles>, compositor_token: CompositorToken<Roles>,
backends: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>, backends: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>,
texture_destruction_callback: (mpsc::Sender<Gles2Texture>, mpsc::Receiver<Gles2Texture>),
window_map: Rc<RefCell<MyWindowMap>>, window_map: Rc<RefCell<MyWindowMap>>,
output_map: Rc<RefCell<Vec<MyOutput>>>, output_map: Rc<RefCell<Vec<MyOutput>>>,
pointer_location: Rc<RefCell<(f64, f64)>>, pointer_location: Rc<RefCell<(f64, f64)>>,
@ -670,8 +669,8 @@ impl DrmRenderer {
if let Some(surface) = self.backends.borrow().get(&crtc) { if let Some(surface) = self.backends.borrow().get(&crtc) {
let result = DrmRenderer::render_surface( let result = DrmRenderer::render_surface(
&mut *surface.borrow_mut(), &mut *surface.borrow_mut(),
&self.texture_destruction_callback.0, #[cfg(feature = "egl")]
&self.buffer_utils, self.egl_buffer_reader.as_ref(),
self.device_id, self.device_id,
crtc, crtc,
&mut *self.window_map.borrow_mut(), &mut *self.window_map.borrow_mut(),
@ -735,10 +734,6 @@ impl DrmRenderer {
self.window_map self.window_map
.borrow() .borrow()
.send_frames(self.start_time.elapsed().as_millis() as u32); .send_frames(self.start_time.elapsed().as_millis() as u32);
while let Ok(texture) = self.texture_destruction_callback.1.try_recv() {
let _ = surface.borrow_mut().destroy_texture(texture);
}
} }
} }
} }
@ -746,8 +741,8 @@ impl DrmRenderer {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn render_surface( fn render_surface(
surface: &mut RenderSurface, surface: &mut RenderSurface,
texture_destruction_callback: &mpsc::Sender<Gles2Texture>, #[cfg(feature = "egl")]
buffer_utils: &BufferUtils, egl_buffer_reader: Option<&EGLBufferReader>,
device_id: dev_t, device_id: dev_t,
crtc: crtc::Handle, crtc: crtc::Handle,
window_map: &mut MyWindowMap, window_map: &mut MyWindowMap,
@ -759,6 +754,9 @@ impl DrmRenderer {
cursor_status: &mut CursorImageStatus, cursor_status: &mut CursorImageStatus,
logger: &slog::Logger, logger: &slog::Logger,
) -> Result<(), SwapBuffersError> { ) -> Result<(), SwapBuffersError> {
#[cfg(not(feature = "egl"))]
let egl_buffer_reader = None;
surface.frame_submitted()?; surface.frame_submitted()?;
// get output coordinates // get output coordinates
@ -778,9 +776,7 @@ impl DrmRenderer {
// draw the surfaces // draw the surfaces
draw_windows( draw_windows(
surface, surface,
device_id, egl_buffer_reader,
texture_destruction_callback,
buffer_utils,
window_map, window_map,
Some(Rectangle { Some(Rectangle {
x: x as i32, x: x as i32,
@ -805,10 +801,8 @@ impl DrmRenderer {
if wl_surface.as_ref().is_alive() { if wl_surface.as_ref().is_alive() {
draw_dnd_icon( draw_dnd_icon(
surface, surface,
device_id,
texture_destruction_callback,
buffer_utils,
wl_surface, wl_surface,
egl_buffer_reader,
(ptr_x, ptr_y), (ptr_x, ptr_y),
*compositor_token, *compositor_token,
logger, logger,
@ -830,10 +824,8 @@ impl DrmRenderer {
if let CursorImageStatus::Image(ref wl_surface) = *cursor_status { if let CursorImageStatus::Image(ref wl_surface) = *cursor_status {
draw_cursor( draw_cursor(
surface, surface,
device_id,
texture_destruction_callback,
buffer_utils,
wl_surface, wl_surface,
egl_buffer_reader,
(ptr_x, ptr_y), (ptr_x, ptr_y),
*compositor_token, *compositor_token,
logger, logger,

View File

@ -1,7 +1,5 @@
use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration}; use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration};
//#[cfg(feature = "egl")]
//use smithay::backend::egl::EGLGraphicsBackend;
use smithay::{ use smithay::{
backend::{input::InputBackend, renderer::Renderer, winit, SwapBuffersError}, backend::{input::InputBackend, renderer::Renderer, winit, SwapBuffersError},
reexports::{ reexports::{
@ -16,7 +14,6 @@ use smithay::{
use slog::Logger; use slog::Logger;
use crate::buffer_utils::BufferUtils;
use crate::drawing::*; use crate::drawing::*;
use crate::state::AnvilState; use crate::state::AnvilState;
@ -25,26 +22,22 @@ pub fn run_winit(
event_loop: &mut EventLoop<AnvilState>, event_loop: &mut EventLoop<AnvilState>,
log: Logger, log: Logger,
) -> Result<(), ()> { ) -> Result<(), ()> {
let (mut renderer, mut input) = winit::init(log.clone()).map_err(|err| { let (renderer, mut input) = winit::init(log.clone()).map_err(|err| {
slog::crit!(log, "Failed to initialize Winit backend: {}", err); slog::crit!(log, "Failed to initialize Winit backend: {}", err);
})?; })?;
let renderer = Rc::new(RefCell::new(renderer));
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
let egl_buffer_reader = Rc::new(RefCell::new( let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok();
if let Ok(egl_buffer_reader) = renderer.bind_wl_display(&display.borrow()) {
info!(log, "EGL hardware-acceleration enabled");
Some(egl_buffer_reader)
} else {
None
},
));
#[cfg(feature = "egl")]
let buffer_utils = BufferUtils::new(egl_buffer_reader, log.clone());
#[cfg(not(feature = "egl"))] #[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone()); let reader = None;
let (w, h): (u32, u32) = renderer.window_size().physical_size.into(); #[cfg(feature = "egl")]
if reader.is_some() {
info!(log, "EGL hardware-acceleration enabled");
};
let (w, h): (u32, u32) = renderer.borrow().window_size().physical_size.into();
/* /*
* Initialize the globals * Initialize the globals
@ -53,7 +46,8 @@ pub fn run_winit(
let mut state = AnvilState::init( let mut state = AnvilState::init(
display.clone(), display.clone(),
event_loop.handle(), event_loop.handle(),
buffer_utils.clone(), #[cfg(feature = "egl")]
Rc::new(RefCell::new(reader.clone())),
None, None,
None, None,
log.clone(), log.clone(),
@ -91,7 +85,6 @@ pub fn run_winit(
info!(log, "Initialization completed, starting the main loop."); info!(log, "Initialization completed, starting the main loop.");
let (texture_send, texture_receive) = std::sync::mpsc::channel();
while state.running.load(Ordering::SeqCst) { while state.running.load(Ordering::SeqCst) {
if input if input
.dispatch_new_events(|event, _| state.process_input_event(event)) .dispatch_new_events(|event, _| state.process_input_event(event))
@ -110,6 +103,8 @@ pub fn run_winit(
// drawing logic // drawing logic
{ {
let mut renderer = renderer.borrow_mut();
renderer.begin().expect("Failed to render frame"); renderer.begin().expect("Failed to render frame");
renderer renderer
.clear([0.8, 0.8, 0.9, 1.0]) .clear([0.8, 0.8, 0.9, 1.0])
@ -117,10 +112,8 @@ pub fn run_winit(
// draw the windows // draw the windows
draw_windows( draw_windows(
&mut renderer, &mut *renderer,
0, reader.as_ref(),
&texture_send,
&buffer_utils,
&*state.window_map.borrow(), &*state.window_map.borrow(),
None, None,
state.ctoken, state.ctoken,
@ -135,11 +128,9 @@ pub fn run_winit(
if let Some(ref surface) = *guard { if let Some(ref surface) = *guard {
if surface.as_ref().is_alive() { if surface.as_ref().is_alive() {
draw_dnd_icon( draw_dnd_icon(
&mut renderer, &mut *renderer,
0,
&texture_send,
&buffer_utils,
surface, surface,
reader.as_ref(),
(x as i32, y as i32), (x as i32, y as i32),
state.ctoken, state.ctoken,
&log, &log,
@ -164,11 +155,9 @@ pub fn run_winit(
if let CursorImageStatus::Image(ref surface) = *guard { if let CursorImageStatus::Image(ref surface) = *guard {
renderer.window().set_cursor_visible(false); renderer.window().set_cursor_visible(false);
draw_cursor( draw_cursor(
&mut renderer, &mut *renderer,
0,
&texture_send,
&buffer_utils,
surface, surface,
reader.as_ref(),
(x as i32, y as i32), (x as i32, y as i32),
state.ctoken, state.ctoken,
&log, &log,
@ -194,10 +183,6 @@ pub fn run_winit(
display.borrow_mut().flush_clients(&mut state); display.borrow_mut().flush_clients(&mut state);
state.window_map.borrow_mut().refresh(); state.window_map.borrow_mut().refresh();
} }
while let Ok(texture) = texture_receive.try_recv() {
let _ = renderer.destroy_texture(texture);
}
} }
// Cleanup stuff // Cleanup stuff