anvil: Introduce BufferTextures

This commit is contained in:
Victor Brekenfeld 2020-06-27 18:27:47 +02:00
parent d603a9ccfb
commit bf011e8071
8 changed files with 262 additions and 302 deletions

View File

@ -1,14 +1,27 @@
use std::{cell::RefCell, rc::Rc};
use std::collections::HashMap;
#[cfg(feature = "egl")]
use std::{
cell::RefCell,
rc::Rc,
};
use glium::texture::Texture2d;
#[cfg(feature = "egl")]
use glium::{
texture::{MipmapsOption, UncompressedFloatFormat},
GlObject,
};
use slog::Logger;
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use smithay::backend::egl::{display::EGLBufferReader, EGLImages, BufferAccessError as EGLBufferAccessError, Format};
use smithay::{
backend::graphics::gl::GLGraphicsBackend,
reexports::wayland_server::protocol::wl_buffer::WlBuffer,
wayland::shm::with_buffer_contents as shm_buffer_contents,
wayland::shm::{with_buffer_contents as shm_buffer_contents, BufferAccessError},
};
use crate::glium_drawer::GliumDrawer;
/// Utilities for working with `WlBuffer`s.
#[derive(Clone)]
pub struct BufferUtils {
@ -41,22 +54,172 @@ impl BufferUtils {
.borrow()
.as_ref()
.and_then(|display| display.egl_buffer_dimensions(buffer))
.or_else(|| self.shm_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)
self.shm_buffer_dimensions(buffer).ok()
}
/// Returns the dimensions of an image stored in the shm buffer.
fn shm_buffer_dimensions(&self, buffer: &WlBuffer) -> Option<(i32, i32)> {
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
})
.ok()
}
#[cfg(feature = "egl")]
pub fn load_buffer(&self, buffer: WlBuffer) -> Result<BufferTextures, WlBuffer> {
// try to retrieve the egl contents of this buffer
let images = if let Some(display) = &self.egl_buffer_reader.borrow().as_ref() {
display.egl_buffer_contents(&buffer)
} else {
return Err(buffer);
};
match images {
Ok(images) => {
// we have an EGL buffer
Ok(BufferTextures {
buffer,
textures: HashMap::new(),
fragment: crate::shaders::BUFFER_RGBA,
y_inverted: images.y_inverted,
dimensions: (images.width, images.height),
images: Some(images), // I guess we need to keep this alive ?
logger: self.log.clone(),
})
}
Err(EGLBufferAccessError::NotManaged(_)) => {
// this is not an EGL buffer, try SHM
self.load_shm_buffer(buffer)
}
Err(err) => {
error!(self.log, "EGL error"; "err" => format!("{:?}", err));
Err(buffer)
}
}
}
#[cfg(not(feature = "egl"))]
pub fn load_buffer(&self, buffer: WlBuffer) -> Result<BufferTextures, WlBuffer> {
self.load_shm_buffer(buffer)
}
fn load_shm_buffer(&self, buffer: WlBuffer) -> Result<BufferTextures, WlBuffer> {
let (width, height, format) = match shm_buffer_contents(&buffer, |_, data| (data.width, data.height, data.format)) {
Ok(x) => x,
Err(err) => {
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
return Err(buffer);
}
};
let shader = match crate::shm_load::load_format(format) {
Ok(x) => x.1,
Err(format) => {
warn!(self.log, "Unable to load buffer format: {:?}", format);
return Err(buffer);
}
};
Ok(BufferTextures {
buffer,
textures: HashMap::new(),
fragment: shader,
y_inverted: false,
dimensions: (width as u32, height as u32),
#[cfg(feature = "egl")]
images: None,
logger: self.log.clone(),
})
}
}
pub struct BufferTextures {
buffer: WlBuffer,
pub textures: HashMap<usize, Texture2d>,
pub fragment: usize,
pub y_inverted: bool,
pub dimensions: (u32, u32),
#[cfg(feature = "egl")]
images: Option<EGLImages>,
logger: slog::Logger,
}
impl BufferTextures {
#[cfg(feature = "egl")]
pub fn load_texture<'a, F: GLGraphicsBackend + 'static>(&'a mut self, drawer: &GliumDrawer<F>) -> Result<&'a Texture2d, ()> {
if self.textures.contains_key(&drawer.id) {
return Ok(&self.textures[&drawer.id]);
}
if let Some(images) = self.images.as_ref() { //EGL buffer
let format = match images.format {
Format::RGB => UncompressedFloatFormat::U8U8U8,
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
_ => {
warn!(self.logger, "Unsupported EGL buffer format"; "format" => format!("{:?}", images.format));
return Err(());
}
};
let opengl_texture = Texture2d::empty_with_format(
&drawer.display,
format,
MipmapsOption::NoMipmap,
images.width,
images.height,
)
.unwrap();
unsafe {
images
.bind_to_texture(0, opengl_texture.get_id(), &*drawer.display.borrow())
.expect("Failed to bind to texture");
}
self.textures.insert(drawer.id, opengl_texture);
Ok(&self.textures[&drawer.id])
} else {
self.load_shm_texture(drawer)
}
}
#[cfg(not(feature = "egl"))]
pub fn load_texture<'a, F: GLGraphicsBackend + 'static>(&'a mut self, drawer: &GliumDrawer<F>) -> Result<&'a Texture2d, ()> {
if self.textures.contains_key(&drawer.id) {
return Ok(&self.textures[&drawer.id]);
}
self.load_shm_texture(drawer)
}
fn load_shm_texture<'a, F: GLGraphicsBackend + 'static>(&'a mut self, drawer: &GliumDrawer<F>) -> Result<&'a Texture2d, ()> {
match shm_buffer_contents(&self.buffer, |slice, data| {
crate::shm_load::load_shm_buffer(data, slice)
.map(|(image, _kind)| Texture2d::new(&drawer.display, image).unwrap())
}) {
Ok(Ok(texture)) => {
self.textures.insert(drawer.id, texture);
Ok(&self.textures[&drawer.id])
},
Ok(Err(format)) => {
warn!(self.logger, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
Err(())
}
Err(err) => {
warn!(self.logger, "Unable to load buffer contents"; "err" => format!("{:?}", err));
Err(())
}
}
}
}
impl Drop for BufferTextures {
fn drop(&mut self) {
self.buffer.release()
}
}

View File

@ -7,35 +7,30 @@ use std::{
use glium::{
self,
index::PrimitiveType,
texture::{MipmapsOption, Texture2d, UncompressedFloatFormat},
GlObject, Surface,
texture::Texture2d,
Surface,
};
use slog::Logger;
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use smithay::{
backend::{
egl::{BufferAccessError, EGLImages, Format},
graphics::{
gl::GLGraphicsBackend,
glium::{Frame, GliumGraphicsBackend},
SwapBuffersError,
},
backend::graphics::{
gl::GLGraphicsBackend,
glium::{Frame, GliumGraphicsBackend},
SwapBuffersError,
},
reexports::{
calloop::LoopHandle,
wayland_server::protocol::{wl_buffer, wl_surface},
wayland_server::protocol::wl_surface,
},
utils::Rectangle,
wayland::{
compositor::{roles::Role, SubsurfaceRole, TraversalAction},
data_device::DnDIconRole,
seat::CursorImageRole,
shm::with_buffer_contents as shm_buffer_contents,
},
};
use crate::buffer_utils::BufferUtils;
use crate::shaders;
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};
@ -55,13 +50,12 @@ mod implement_vertex {
}
pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
id: usize,
display: GliumGraphicsBackend<F>,
pub id: usize,
pub display: GliumGraphicsBackend<F>,
vertex_buffer: glium::VertexBuffer<Vertex>,
index_buffer: glium::IndexBuffer<u16>,
programs: [glium::Program; shaders::FRAGMENT_COUNT],
#[cfg(feature = "egl")]
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
buffer_loader: BufferUtils,
log: Logger,
}
@ -72,10 +66,9 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
}
impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer<T> {
#[cfg(feature = "egl")]
pub fn init(
backend: T,
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
buffer_loader: BufferUtils,
log: Logger,
) -> GliumDrawer<T> {
let display = backend.into();
@ -116,140 +109,13 @@ impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer
vertex_buffer,
index_buffer,
programs,
egl_buffer_reader,
log,
}
}
#[cfg(not(feature = "egl"))]
pub fn init(backend: T, log: Logger) -> GliumDrawer<T> {
let display = backend.into();
// building the vertex buffer, which contains all the vertices that we will draw
let vertex_buffer = glium::VertexBuffer::new(
&display,
&[
Vertex {
position: [0.0, 0.0],
tex_coords: [0.0, 0.0],
},
Vertex {
position: [0.0, 1.0],
tex_coords: [0.0, 1.0],
},
Vertex {
position: [1.0, 1.0],
tex_coords: [1.0, 1.0],
},
Vertex {
position: [1.0, 0.0],
tex_coords: [1.0, 0.0],
},
],
)
.unwrap();
// building the index buffer
let index_buffer =
glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();
let programs = opengl_programs!(&display);
GliumDrawer {
id: BACKEND_COUNTER.fetch_add(1, Ordering::AcqRel),
display,
vertex_buffer,
index_buffer,
programs,
buffer_loader,
log,
}
}
}
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
#[cfg(feature = "egl")]
pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
// try to retrieve the egl contents of this buffer
let images = if let Some(display) = &self.egl_buffer_reader.borrow().as_ref() {
display.egl_buffer_contents(buffer)
} else {
Err(BufferAccessError::NotManaged(
buffer,
smithay::backend::egl::EGLError::BadDisplay,
))
};
match images {
Ok(images) => {
// we have an EGL buffer
let format = match images.format {
Format::RGB => UncompressedFloatFormat::U8U8U8,
Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
_ => {
warn!(self.log, "Unsupported EGL buffer format"; "format" => format!("{:?}", images.format));
return Err(());
}
};
let opengl_texture = Texture2d::empty_with_format(
&self.display,
format,
MipmapsOption::NoMipmap,
images.width,
images.height,
)
.unwrap();
unsafe {
images
.bind_to_texture(0, opengl_texture.get_id(), &*self.display.borrow())
.expect("Failed to bind to texture");
}
Ok(TextureMetadata {
texture: opengl_texture,
fragment: crate::shaders::BUFFER_RGBA,
y_inverted: images.y_inverted,
dimensions: (images.width, images.height),
images: Some(images), // I guess we need to keep this alive ?
})
}
Err(BufferAccessError::NotManaged(buffer, _)) => {
// this is not an EGL buffer, try SHM
self.texture_from_shm_buffer(buffer)
}
Err(err) => {
error!(self.log, "EGL error"; "err" => format!("{:?}", err));
Err(())
}
}
}
#[cfg(not(feature = "egl"))]
pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
self.texture_from_shm_buffer(buffer)
}
fn texture_from_shm_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
match shm_buffer_contents(&buffer, |slice, data| {
crate::shm_load::load_shm_buffer(data, slice)
.map(|(image, kind)| (Texture2d::new(&self.display, image).unwrap(), kind, data))
}) {
Ok(Ok((texture, kind, data))) => Ok(TextureMetadata {
texture,
fragment: kind,
y_inverted: false,
dimensions: (data.width as u32, data.height as u32),
#[cfg(feature = "egl")]
images: None,
}),
Ok(Err(format)) => {
warn!(self.log, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
Err(())
}
Err(err) => {
warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
Err(())
}
}
}
pub fn render_texture(&self, target: &mut Frame, spec: RenderTextureSpec<'_>) {
let xscale = 2.0 * (spec.surface_dimensions.0 as f32) / (spec.screen_size.0 as f32);
let mut yscale = -2.0 * (spec.surface_dimensions.1 as f32) / (spec.screen_size.1 as f32);
@ -302,15 +168,6 @@ pub struct RenderTextureSpec<'a> {
blending: glium::Blend,
}
pub struct TextureMetadata {
pub texture: Texture2d,
pub fragment: usize,
pub y_inverted: bool,
pub dimensions: (u32, u32),
#[cfg(feature = "egl")]
images: Option<EGLImages>,
}
impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
fn draw_surface_tree(
&self,
@ -327,30 +184,18 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
// Pull a new buffer if available
if let Some(data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
let mut data = data.borrow_mut();
if !data.texture.contains_key(&self.id) {
if data.texture.is_none() {
if let Some(buffer) = data.current_state.buffer.take() {
if let Ok(m) = self.texture_from_buffer(buffer.clone()) {
// release the buffer if it was an SHM buffer
#[cfg(feature = "egl")]
{
if m.images.is_none() {
buffer.release();
}
}
#[cfg(not(feature = "egl"))]
{
buffer.release();
}
data.texture.insert(self.id, m);
} else {
match self.buffer_loader.load_buffer(buffer) {
Ok(m) => data.texture = Some(m),
// there was an error reading the buffer, release it, we
// already logged the error
buffer.release();
}
Err(buffer) => buffer.release(),
};
}
}
// Now, should we be drawn ?
if data.texture.contains_key(&self.id) {
if data.texture.is_some() {
// if yes, also process the children
if Role::<SubsurfaceRole>::has(role) {
x += data.current_state.sub_location.0;
@ -368,36 +213,42 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
},
|_surface, attributes, role, &(mut x, mut y)| {
if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
let data = data.borrow();
if let Some(ref metadata) = data.texture.get(&self.id) {
// we need to re-extract the subsurface offset, as the previous closure
// only passes it to our children
if Role::<SubsurfaceRole>::has(role) {
x += data.current_state.sub_location.0;
y += data.current_state.sub_location.1;
}
self.render_texture(
frame,
RenderTextureSpec {
texture: &metadata.texture,
texture_kind: metadata.fragment,
y_inverted: metadata.y_inverted,
surface_dimensions: metadata.dimensions,
surface_location: (x, y),
screen_size: screen_dimensions,
blending: ::glium::Blend {
color: ::glium::BlendingFunction::Addition {
source: ::glium::LinearBlendingFactor::One,
destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
let mut data = data.borrow_mut();
let (sub_x, sub_y) = data.current_state.sub_location;
if let Some(buffer_textures) = data.texture.as_mut() {
let texture_kind = buffer_textures.fragment;
let y_inverted = buffer_textures.y_inverted;
let surface_dimensions = buffer_textures.dimensions;
if let Ok(ref texture) = buffer_textures.load_texture(&self) {
// we need to re-extract the subsurface offset, as the previous closure
// only passes it to our children
if Role::<SubsurfaceRole>::has(role) {
x += sub_x;
y += sub_y;
}
self.render_texture(
frame,
RenderTextureSpec {
texture: &texture,
texture_kind,
y_inverted,
surface_dimensions,
surface_location: (x, y),
screen_size: screen_dimensions,
blending: ::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()
},
alpha: ::glium::BlendingFunction::Addition {
source: ::glium::LinearBlendingFactor::One,
destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
},
..Default::default()
},
},
);
);
}
}
}
},

View File

@ -82,6 +82,7 @@ impl AnvilState {
);
}
},
#[cfg(feature = "udev")]
KeyAction::Screen(num) => {
let output_map = self.output_map
.as_ref().unwrap();

View File

@ -1,6 +1,5 @@
use std::{
cell::RefCell,
collections::HashMap,
rc::Rc,
sync::{Arc, Mutex},
};
@ -655,7 +654,7 @@ pub struct CommitedState {
#[derive(Default)]
pub struct SurfaceData {
pub texture: HashMap<usize, crate::glium_drawer::TextureMetadata>,
pub texture: Option<crate::buffer_utils::BufferTextures>,
pub geometry: Option<Rectangle>,
pub resize_state: ResizeState,
/// Minimum width and height, as requested by the surface.
@ -674,7 +673,7 @@ impl SurfaceData {
/// Apply a next state into the surface current state
pub fn apply_state(&mut self, next_state: CommitedState) {
if Self::merge_state(&mut self.current_state, next_state) {
self.texture.clear();
let _ = self.texture.take();
}
}

View File

@ -32,13 +32,7 @@ pub fn load_shm_buffer(data: BufferData, pool: &[u8]) -> Result<(RawImage2d<'_,
};
// sharders format need to be reversed to account for endianness
let (client_format, fragment) = match data.format {
Format::Argb8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_BGRA),
Format::Xrgb8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_BGRX),
Format::Rgba8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_ABGR),
Format::Rgbx8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_XBGR),
_ => return Err(data.format),
};
let (client_format, fragment) = load_format(data.format)?;
Ok((
RawImage2d {
data: slice,
@ -49,3 +43,13 @@ pub fn load_shm_buffer(data: BufferData, pool: &[u8]) -> Result<(RawImage2d<'_,
fragment,
))
}
pub fn load_format(format: Format) -> Result<(ClientFormat, usize), Format> {
Ok(match format {
Format::Argb8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_BGRA),
Format::Xrgb8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_BGRX),
Format::Rgba8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_ABGR),
Format::Rgbx8888 => (ClientFormat::U8U8U8U8, crate::shaders::BUFFER_XBGR),
_ => return Err(format),
})
}

View File

@ -8,7 +8,6 @@ use std::{
};
use smithay::{
backend::session::auto::AutoSession,
reexports::{
calloop::{
generic::{Fd, Generic},
@ -25,9 +24,14 @@ use smithay::{
};
#[cfg(feature = "udev")]
use smithay::backend::session::Session;
use smithay::backend::session::{
auto::AutoSession,
Session,
};
use crate::{buffer_utils::BufferUtils, shell::init_shell, udev::MyOutput};
use crate::{buffer_utils::BufferUtils, shell::init_shell};
#[cfg(feature = "udev")]
use crate::udev::MyOutput;
pub struct AnvilState {
pub socket_name: String,
@ -129,7 +133,7 @@ impl AnvilState {
"anvil".into()
};
#[cfg(not(feature = "udev"))]
let seat_name = "anvil".into();
let seat_name: String = "anvil".into();
let (mut seat, _) = Seat::new(
&mut display.borrow_mut(),

View File

@ -127,7 +127,7 @@ pub fn run_udev(
let mut state = AnvilState::init(
display.clone(),
event_loop.handle(),
buffer_utils,
buffer_utils.clone(),
Some(session),
Some(output_map.clone()),
log.clone(),
@ -143,6 +143,7 @@ pub fn run_udev(
let mut udev_handler = UdevHandlerImpl {
compositor_token: state.ctoken,
buffer_utils: buffer_utils,
#[cfg(feature = "egl")]
egl_buffer_reader,
session: state.session.clone().unwrap(),
@ -292,6 +293,7 @@ struct BackendData {
struct UdevHandlerImpl<Data: 'static> {
compositor_token: CompositorToken<Roles>,
buffer_utils: BufferUtils,
#[cfg(feature = "egl")]
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
session: AutoSession,
@ -310,10 +312,9 @@ struct UdevHandlerImpl<Data: 'static> {
}
impl<Data: 'static> UdevHandlerImpl<Data> {
#[cfg(feature = "egl")]
pub fn scan_connectors(
device: &mut RenderDevice,
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
buffer_utils: &BufferUtils,
display: &mut Display,
output_map: &mut Vec<MyOutput>,
logger: &::slog::Logger,
@ -347,7 +348,7 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
device
.create_surface(crtc, connector_info.modes()[0], &[connector_info.handle()])
.unwrap(),
egl_buffer_reader.clone(),
buffer_utils.clone(),
logger.clone(),
);
output_map.push(MyOutput::new(display, device.device_id(), crtc, connector_info, logger.clone()));
@ -361,52 +362,6 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
backends
}
#[cfg(not(feature = "egl"))]
pub fn scan_connectors(
device: &mut RenderDevice,
display: &mut Display,
output_map: &mut Vec<MyOutput>,
logger: &::slog::Logger,
) -> HashMap<crtc::Handle, Rc<GliumDrawer<RenderSurface>>> {
// Get a set of all modesetting resource handles (excluding planes):
let res_handles = device.resource_handles().unwrap();
// Use first connected connector
let connector_infos: Vec<ConnectorInfo> = res_handles
.connectors()
.iter()
.map(|conn| device.get_connector_info(*conn).unwrap())
.filter(|conn| conn.state() == ConnectorState::Connected)
.inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
.collect();
let mut backends = HashMap::new();
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
for connector_info in connector_infos {
let encoder_infos = connector_info
.encoders()
.iter()
.filter_map(|e| *e)
.flat_map(|encoder_handle| device.get_encoder_info(encoder_handle))
.collect::<Vec<EncoderInfo>>();
'outer: for encoder_info in encoder_infos {
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
if !backends.contains_key(&crtc) {
let renderer =
GliumDrawer::init(device.create_surface(crtc).unwrap(), logger.clone());
output_map.push(MyOutput::new(display, device.device_id(), crtc, connector_info, logger.clone()));
backends.insert(crtc, Rc::new(renderer));
break 'outer;
}
}
}
}
backends
}
}
impl<Data: 'static> UdevHandlerImpl<Data> {
@ -453,23 +408,15 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
#[cfg(feature = "egl")]
{
if path.canonicalize().ok() == self.primary_gpu {
info!(self.logger, "Initializing EGL Hardware Acceleration via {:?}", path);
*self.egl_buffer_reader.borrow_mut() =
device.bind_wl_display(&*self.display.borrow()).ok();
}
}
#[cfg(feature = "egl")]
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<Data>::scan_connectors(
&mut device,
self.egl_buffer_reader.clone(),
&mut *self.display.borrow_mut(),
&mut *self.output_map.borrow_mut(),
&self.logger,
)));
#[cfg(not(feature = "egl"))]
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<Data>::scan_connectors(
&mut device,
&self.buffer_utils,
&mut *self.display.borrow_mut(),
&mut *self.output_map.borrow_mut(),
&self.logger,
@ -528,9 +475,9 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
fn device_changed(&mut self, device: dev_t) {
//quick and dirty, just re-init all backends
let buffer_utils = &self.buffer_utils;
if let Some(ref mut backend_data) = self.backends.get_mut(&device) {
let logger = &self.logger;
let egl_buffer_reader = self.egl_buffer_reader.clone();
let loop_handle = self.loop_handle.clone();
let mut display = self.display.borrow_mut();
let mut output_map = self.output_map.borrow_mut();
@ -538,21 +485,13 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
self.loop_handle
.with_source(&backend_data.event_source, |source| {
let mut backends = backend_data.surfaces.borrow_mut();
#[cfg(feature = "egl")]
let new_backends =
*backends =
UdevHandlerImpl::<Data>::scan_connectors(
&mut source.file,
egl_buffer_reader,
buffer_utils,
&mut *display,
&mut *output_map,
logger);
#[cfg(not(feature = "egl"))]
let new_backends = UdevHandlerImpl::<Data>::scan_connectors(
&mut source.file,
&mut *display,
&mut *output_map,
logger);
*backends = new_backends;
for renderer in backends.values() {
// render first frame

View File

@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration};
use smithay::{
backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
backend::{graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
reexports::{
calloop::EventLoop,
wayland_server::{protocol::wl_output, Display},
@ -12,6 +12,8 @@ use smithay::{
SERIAL_COUNTER as SCOUNTER,
},
};
#[cfg(feature = "egl")]
use smithay::backend::egl::EGLGraphicsBackend;
use slog::Logger;
@ -38,17 +40,14 @@ pub fn run_winit(
},
));
let (w, h) = renderer.get_framebuffer_dimensions();
#[cfg(feature = "egl")]
let drawer = GliumDrawer::init(renderer, egl_buffer_reader.clone(), log.clone());
#[cfg(not(feature = "egl"))]
let drawer = GliumDrawer::init(renderer, log.clone());
#[cfg(feature = "egl")]
let buffer_utils = BufferUtils::new(egl_buffer_reader, log.clone());
#[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone());
let (w, h) = renderer.get_framebuffer_dimensions();
let drawer = GliumDrawer::init(renderer, buffer_utils.clone(), log.clone());
/*
* Initialize the globals
*/