Merge pull request #303 from Smithay/feature/import_egl_buffer_reader
Move `EGLBufferReader` management into `ImportEgl`
This commit is contained in:
commit
736e4e8bec
|
@ -3,11 +3,9 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
use smithay::backend::{egl::display::EGLBufferReader, renderer::ImportEgl};
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
renderer::{buffer_type, BufferType, Frame, ImportDma, ImportShm, Renderer, Texture, Transform},
|
renderer::{buffer_type, BufferType, Frame, ImportAll, Renderer, Texture, Transform},
|
||||||
SwapBuffersError,
|
SwapBuffersError,
|
||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
||||||
|
@ -18,11 +16,6 @@ use smithay::{
|
||||||
seat::CursorImageRole,
|
seat::CursorImageRole,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// hacky...
|
|
||||||
#[cfg(not(feature = "egl"))]
|
|
||||||
pub trait ImportEgl {}
|
|
||||||
#[cfg(not(feature = "egl"))]
|
|
||||||
impl<T> ImportEgl for T {}
|
|
||||||
|
|
||||||
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};
|
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};
|
||||||
|
|
||||||
|
@ -43,13 +36,12 @@ pub fn draw_cursor<R, E, F, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
frame: &mut F,
|
frame: &mut F,
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
#[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
(x, y): (i32, i32),
|
(x, y): (i32, i32),
|
||||||
token: MyCompositorToken,
|
token: MyCompositorToken,
|
||||||
log: &Logger,
|
log: &Logger,
|
||||||
) -> Result<(), SwapBuffersError>
|
) -> Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl + ImportDma,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
F: Frame<Error = E, TextureId = T>,
|
F: Frame<Error = E, TextureId = T>,
|
||||||
E: std::error::Error + Into<SwapBuffersError>,
|
E: std::error::Error + Into<SwapBuffersError>,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
|
@ -64,29 +56,19 @@ where
|
||||||
(0, 0)
|
(0, 0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
draw_surface_tree(
|
draw_surface_tree(renderer, frame, surface, (x - dx, y - dy), token, log)
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
surface,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
(x - dx, y - dy),
|
|
||||||
token,
|
|
||||||
log,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_surface_tree<R, E, F, T>(
|
fn draw_surface_tree<R, E, F, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
frame: &mut F,
|
frame: &mut F,
|
||||||
root: &wl_surface::WlSurface,
|
root: &wl_surface::WlSurface,
|
||||||
#[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
location: (i32, i32),
|
location: (i32, i32),
|
||||||
compositor_token: MyCompositorToken,
|
compositor_token: MyCompositorToken,
|
||||||
log: &Logger,
|
log: &Logger,
|
||||||
) -> Result<(), SwapBuffersError>
|
) -> Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl + ImportDma,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
F: Frame<Error = E, TextureId = T>,
|
F: Frame<Error = E, TextureId = T>,
|
||||||
E: std::error::Error + Into<SwapBuffersError>,
|
E: std::error::Error + Into<SwapBuffersError>,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
|
@ -102,54 +84,36 @@ 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() {
|
||||||
let texture = match buffer_type(
|
let damage = attributes
|
||||||
&buffer,
|
.damage
|
||||||
#[cfg(feature = "egl")]
|
.iter()
|
||||||
egl_buffer_reader,
|
.map(|dmg| match dmg {
|
||||||
) {
|
Damage::Buffer(rect) => *rect,
|
||||||
Some(BufferType::Shm) => {
|
// TODO also apply transformations
|
||||||
let damage = attributes
|
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
||||||
.damage
|
})
|
||||||
.iter()
|
.collect::<Vec<_>>();
|
||||||
.map(|dmg| match dmg {
|
|
||||||
Damage::Buffer(rect) => *rect,
|
match renderer.import_buffer(&buffer, Some(&attributes), &damage) {
|
||||||
// TODO also apply transformations
|
Some(Ok(m)) => {
|
||||||
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
if let Some(BufferType::Shm) = buffer_type(&buffer) {
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let result = renderer.import_shm_buffer(&buffer, Some(&attributes), &damage);
|
|
||||||
buffer.release();
|
|
||||||
// don't return the buffer as it is already released
|
|
||||||
Some((result, None))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
Some(BufferType::Egl) => Some((
|
|
||||||
renderer.import_egl_buffer(&buffer, egl_buffer_reader.unwrap()),
|
|
||||||
Some(buffer),
|
|
||||||
)),
|
|
||||||
Some(BufferType::Dma) => {
|
|
||||||
Some((renderer.import_dma_buffer(&buffer), Some(buffer)))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
error!(log, "Unknown buffer format for: {:?}", buffer);
|
|
||||||
buffer.release();
|
|
||||||
None
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match texture {
|
|
||||||
Some((Ok(m), buffer)) => {
|
|
||||||
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.
|
|
||||||
Some((Err(err), buffer)) => {
|
|
||||||
warn!(log, "Error loading buffer: {:?}", err);
|
|
||||||
if let Some(buffer) = buffer {
|
|
||||||
buffer.release();
|
buffer.release();
|
||||||
}
|
}
|
||||||
|
data.texture = Some(Box::new(BufferTextures {
|
||||||
|
buffer: Some(buffer),
|
||||||
|
texture: m,
|
||||||
|
})
|
||||||
|
as Box<dyn std::any::Any + 'static>)
|
||||||
}
|
}
|
||||||
None => {}
|
Some(Err(err)) => {
|
||||||
};
|
warn!(log, "Error loading buffer: {:?}", err);
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
error!(log, "Unknown buffer format for: {:?}", buffer);
|
||||||
|
buffer.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now, should we be drawn ?
|
// Now, should we be drawn ?
|
||||||
|
@ -204,14 +168,13 @@ where
|
||||||
pub fn draw_windows<R, E, F, T>(
|
pub fn draw_windows<R, E, F, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
frame: &mut F,
|
frame: &mut F,
|
||||||
#[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
window_map: &MyWindowMap,
|
window_map: &MyWindowMap,
|
||||||
output_rect: Option<Rectangle>,
|
output_rect: Option<Rectangle>,
|
||||||
compositor_token: MyCompositorToken,
|
compositor_token: MyCompositorToken,
|
||||||
log: &::slog::Logger,
|
log: &::slog::Logger,
|
||||||
) -> Result<(), SwapBuffersError>
|
) -> Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl + ImportDma,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
F: Frame<Error = E, TextureId = T>,
|
F: Frame<Error = E, TextureId = T>,
|
||||||
E: std::error::Error + Into<SwapBuffersError>,
|
E: std::error::Error + Into<SwapBuffersError>,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
|
@ -229,16 +192,9 @@ where
|
||||||
}
|
}
|
||||||
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
if let Some(wl_surface) = toplevel_surface.get_surface() {
|
||||||
// this surface is a root of a subsurface tree that needs to be drawn
|
// this surface is a root of a subsurface tree that needs to be drawn
|
||||||
if let Err(err) = draw_surface_tree(
|
if let Err(err) =
|
||||||
renderer,
|
draw_surface_tree(renderer, frame, &wl_surface, initial_place, compositor_token, log)
|
||||||
frame,
|
{
|
||||||
&wl_surface,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
initial_place,
|
|
||||||
compositor_token,
|
|
||||||
log,
|
|
||||||
) {
|
|
||||||
result = Err(err);
|
result = Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,13 +207,12 @@ pub fn draw_dnd_icon<R, E, F, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
frame: &mut F,
|
frame: &mut F,
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
#[cfg(feature = "egl")] egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
(x, y): (i32, i32),
|
(x, y): (i32, i32),
|
||||||
token: MyCompositorToken,
|
token: MyCompositorToken,
|
||||||
log: &::slog::Logger,
|
log: &::slog::Logger,
|
||||||
) -> Result<(), SwapBuffersError>
|
) -> Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl + ImportDma,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
F: Frame<Error = E, TextureId = T>,
|
F: Frame<Error = E, TextureId = T>,
|
||||||
E: std::error::Error + Into<SwapBuffersError>,
|
E: std::error::Error + Into<SwapBuffersError>,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
|
@ -268,14 +223,5 @@ where
|
||||||
"Trying to display as a dnd icon a surface that does not have the DndIcon role."
|
"Trying to display as a dnd icon a surface that does not have the DndIcon role."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
draw_surface_tree(
|
draw_surface_tree(renderer, frame, surface, (x, y), token, log)
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
surface,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
(x, y),
|
|
||||||
token,
|
|
||||||
log,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
use smithay::backend::egl::display::EGLBufferReader;
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::buffer_dimensions,
|
backend::renderer::buffer_dimensions,
|
||||||
reexports::{
|
reexports::{
|
||||||
|
@ -324,22 +322,15 @@ pub struct ShellHandles {
|
||||||
pub window_map: Rc<RefCell<MyWindowMap>>,
|
pub window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_shell<Backend: 'static>(display: &mut Display, log: ::slog::Logger) -> ShellHandles {
|
pub fn init_shell<BackendData: 'static>(display: &mut Display, log: ::slog::Logger) -> ShellHandles {
|
||||||
// Create the compositor
|
// Create the compositor
|
||||||
let (compositor_token, _, _) = compositor_init(
|
let (compositor_token, _, _) = compositor_init(
|
||||||
display,
|
display,
|
||||||
move |request, surface, ctoken, mut ddata| match request {
|
move |request, surface, ctoken, mut ddata| match request {
|
||||||
SurfaceEvent::Commit => {
|
SurfaceEvent::Commit => {
|
||||||
let anvil_state = ddata.get::<AnvilState<Backend>>().unwrap();
|
let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
|
||||||
let window_map = anvil_state.window_map.as_ref();
|
let window_map = anvil_state.window_map.as_ref();
|
||||||
#[cfg(feature = "egl")]
|
surface_commit(&surface, ctoken, &*window_map)
|
||||||
{
|
|
||||||
surface_commit(&surface, ctoken, anvil_state.egl_reader.as_ref(), &*window_map)
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "egl"))]
|
|
||||||
{
|
|
||||||
surface_commit(&surface, ctoken, &*window_map)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
log.clone(),
|
log.clone(),
|
||||||
|
@ -850,7 +841,6 @@ impl SurfaceData {
|
||||||
fn surface_commit(
|
fn surface_commit(
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
token: CompositorToken<Roles>,
|
token: CompositorToken<Roles>,
|
||||||
#[cfg(feature = "egl")] egl_reader: Option<&EGLBufferReader>,
|
|
||||||
window_map: &RefCell<MyWindowMap>,
|
window_map: &RefCell<MyWindowMap>,
|
||||||
) {
|
) {
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
|
@ -924,14 +914,7 @@ fn surface_commit(
|
||||||
match attributes.buffer.take() {
|
match attributes.buffer.take() {
|
||||||
Some(BufferAssignment::NewBuffer { buffer, .. }) => {
|
Some(BufferAssignment::NewBuffer { buffer, .. }) => {
|
||||||
// new contents
|
// new contents
|
||||||
#[cfg(feature = "egl")]
|
next_state.dimensions = buffer_dimensions(&buffer);
|
||||||
{
|
|
||||||
next_state.dimensions = buffer_dimensions(&buffer, egl_reader);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "egl"))]
|
|
||||||
{
|
|
||||||
next_state.dimensions = buffer_dimensions(&buffer);
|
|
||||||
}
|
|
||||||
next_state.buffer = Some(buffer);
|
next_state.buffer = Some(buffer);
|
||||||
}
|
}
|
||||||
Some(BufferAssignment::Removed) => {
|
Some(BufferAssignment::Removed) => {
|
||||||
|
|
|
@ -20,8 +20,6 @@ use smithay::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
use smithay::backend::egl::display::EGLBufferReader;
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
use smithay::xwayland::{XWayland, XWaylandEvent};
|
use smithay::xwayland::{XWayland, XWaylandEvent};
|
||||||
|
|
||||||
|
@ -45,8 +43,7 @@ pub struct AnvilState<BackendData> {
|
||||||
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
|
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
|
||||||
pub seat_name: String,
|
pub seat_name: String,
|
||||||
pub start_time: std::time::Instant,
|
pub start_time: std::time::Instant,
|
||||||
#[cfg(feature = "egl")]
|
// things we must keep alive
|
||||||
pub egl_reader: Option<EGLBufferReader>,
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
pub xwayland: XWayland<AnvilState<BackendData>>,
|
pub xwayland: XWayland<AnvilState<BackendData>>,
|
||||||
}
|
}
|
||||||
|
@ -56,7 +53,6 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
||||||
display: Rc<RefCell<Display>>,
|
display: Rc<RefCell<Display>>,
|
||||||
handle: LoopHandle<'static, AnvilState<BackendData>>,
|
handle: LoopHandle<'static, AnvilState<BackendData>>,
|
||||||
backend_data: BackendData,
|
backend_data: BackendData,
|
||||||
#[cfg(feature = "egl")] egl_reader: Option<EGLBufferReader>,
|
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
) -> AnvilState<BackendData> {
|
) -> AnvilState<BackendData> {
|
||||||
// init the wayland connection
|
// init the wayland connection
|
||||||
|
@ -170,8 +166,6 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
||||||
cursor_status,
|
cursor_status,
|
||||||
pointer_location: (0.0, 0.0),
|
pointer_location: (0.0, 0.0),
|
||||||
seat_name,
|
seat_name,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_reader,
|
|
||||||
start_time: std::time::Instant::now(),
|
start_time: std::time::Instant::now(),
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
xwayland,
|
xwayland,
|
||||||
|
|
|
@ -58,7 +58,11 @@ use smithay::{
|
||||||
};
|
};
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{drm::DevPath, egl::display::EGLBufferReader, renderer::ImportDma, udev::primary_gpu},
|
backend::{
|
||||||
|
drm::DevPath,
|
||||||
|
renderer::{ImportDma, ImportEgl},
|
||||||
|
udev::primary_gpu,
|
||||||
|
},
|
||||||
wayland::dmabuf::init_dmabuf_global,
|
wayland::dmabuf::init_dmabuf_global,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,14 +134,7 @@ pub fn run_udev(
|
||||||
pointer_image: ImageBuffer::from_raw(64, 64, pointer_bytes.to_vec()).unwrap(),
|
pointer_image: ImageBuffer::from_raw(64, 64, pointer_bytes.to_vec()).unwrap(),
|
||||||
render_timer: timer.handle(),
|
render_timer: timer.handle(),
|
||||||
};
|
};
|
||||||
let mut state = AnvilState::init(
|
let mut state = AnvilState::init(display.clone(), event_loop.handle(), data, log.clone());
|
||||||
display.clone(),
|
|
||||||
event_loop.handle(),
|
|
||||||
data,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
None,
|
|
||||||
log.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// re-render timer
|
// re-render timer
|
||||||
event_loop
|
event_loop
|
||||||
|
@ -460,17 +457,6 @@ impl AnvilState<UdevData> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
let is_primary = path.canonicalize().ok() == self.backend_data.primary_gpu;
|
|
||||||
// init hardware acceleration on the primary gpu.
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
{
|
|
||||||
if is_primary {
|
|
||||||
info!(self.log, "Initializing EGL Hardware Acceleration via {:?}", path);
|
|
||||||
self.egl_reader = egl.bind_wl_display(&*self.display.borrow()).ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let context = match EGLContext::new(&egl, self.log.clone()) {
|
let context = match EGLContext::new(&egl, self.log.clone()) {
|
||||||
Ok(context) => context,
|
Ok(context) => context,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -486,6 +472,15 @@ impl AnvilState<UdevData> {
|
||||||
Gles2Renderer::new(context, self.log.clone()).unwrap()
|
Gles2Renderer::new(context, self.log.clone()).unwrap()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
if path.canonicalize().ok() == self.backend_data.primary_gpu {
|
||||||
|
info!(self.log, "Initializing EGL Hardware Acceleration via {:?}", path);
|
||||||
|
renderer
|
||||||
|
.borrow_mut()
|
||||||
|
.bind_wl_display(&*self.display.borrow())
|
||||||
|
.expect("Unable to bind Wl Display?");
|
||||||
|
}
|
||||||
|
|
||||||
let backends = Rc::new(RefCell::new(scan_connectors(
|
let backends = Rc::new(RefCell::new(scan_connectors(
|
||||||
&mut device,
|
&mut device,
|
||||||
&gbm,
|
&gbm,
|
||||||
|
@ -597,12 +592,8 @@ impl AnvilState<UdevData> {
|
||||||
|
|
||||||
// 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.backend_data.primary_gpu {
|
||||||
if _device.dev_path().and_then(|path| path.canonicalize().ok())
|
backend_data.renderer.borrow_mut().unbind_wl_display();
|
||||||
== self.backend_data.primary_gpu
|
|
||||||
{
|
|
||||||
self.egl_reader = None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
debug!(self.log, "Dropping device");
|
debug!(self.log, "Dropping device");
|
||||||
}
|
}
|
||||||
|
@ -637,8 +628,6 @@ impl AnvilState<UdevData> {
|
||||||
let result = render_surface(
|
let result = render_surface(
|
||||||
&mut *surface.borrow_mut(),
|
&mut *surface.borrow_mut(),
|
||||||
&mut *device_backend.renderer.borrow_mut(),
|
&mut *device_backend.renderer.borrow_mut(),
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
self.egl_reader.as_ref(),
|
|
||||||
device_backend.dev_id,
|
device_backend.dev_id,
|
||||||
crtc,
|
crtc,
|
||||||
&mut *self.window_map.borrow_mut(),
|
&mut *self.window_map.borrow_mut(),
|
||||||
|
@ -687,7 +676,6 @@ impl AnvilState<UdevData> {
|
||||||
fn render_surface(
|
fn render_surface(
|
||||||
surface: &mut RenderSurface,
|
surface: &mut RenderSurface,
|
||||||
renderer: &mut Gles2Renderer,
|
renderer: &mut Gles2Renderer,
|
||||||
#[cfg(feature = "egl")] 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,
|
||||||
|
@ -726,8 +714,6 @@ fn render_surface(
|
||||||
draw_windows(
|
draw_windows(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
window_map,
|
window_map,
|
||||||
Some(Rectangle {
|
Some(Rectangle {
|
||||||
x: x as i32,
|
x: x as i32,
|
||||||
|
@ -754,8 +740,6 @@ fn render_surface(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
wl_surface,
|
wl_surface,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
(ptr_x, ptr_y),
|
(ptr_x, ptr_y),
|
||||||
*compositor_token,
|
*compositor_token,
|
||||||
logger,
|
logger,
|
||||||
|
@ -779,8 +763,6 @@ fn render_surface(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
wl_surface,
|
wl_surface,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
(ptr_x, ptr_y),
|
(ptr_x, ptr_y),
|
||||||
*compositor_token,
|
*compositor_token,
|
||||||
logger,
|
logger,
|
||||||
|
|
|
@ -38,9 +38,7 @@ pub fn run_winit(
|
||||||
let renderer = Rc::new(RefCell::new(renderer));
|
let renderer = Rc::new(RefCell::new(renderer));
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok();
|
if renderer.borrow().bind_wl_display(&display.borrow()).is_ok() {
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
if reader.is_some() {
|
|
||||||
info!(log, "EGL hardware-acceleration enabled");
|
info!(log, "EGL hardware-acceleration enabled");
|
||||||
let dmabuf_formats = renderer
|
let dmabuf_formats = renderer
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -67,8 +65,6 @@ pub fn run_winit(
|
||||||
display.clone(),
|
display.clone(),
|
||||||
event_loop.handle(),
|
event_loop.handle(),
|
||||||
WinitData,
|
WinitData,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
reader,
|
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -129,8 +125,6 @@ pub fn run_winit(
|
||||||
draw_windows(
|
draw_windows(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
state.egl_reader.as_ref(),
|
|
||||||
&*state.window_map.borrow(),
|
&*state.window_map.borrow(),
|
||||||
None,
|
None,
|
||||||
state.ctoken,
|
state.ctoken,
|
||||||
|
@ -147,8 +141,6 @@ pub fn run_winit(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
surface,
|
surface,
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
state.egl_reader.as_ref(),
|
|
||||||
(x as i32, y as i32),
|
(x as i32, y as i32),
|
||||||
state.ctoken,
|
state.ctoken,
|
||||||
&log,
|
&log,
|
||||||
|
@ -171,16 +163,7 @@ pub fn run_winit(
|
||||||
// draw as relevant
|
// draw as relevant
|
||||||
if let CursorImageStatus::Image(ref surface) = *guard {
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
cursor_visible = false;
|
cursor_visible = false;
|
||||||
draw_cursor(
|
draw_cursor(renderer, frame, surface, (x as i32, y as i32), state.ctoken, &log)?;
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
surface,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
state.egl_reader.as_ref(),
|
|
||||||
(x as i32, y as i32),
|
|
||||||
state.ctoken,
|
|
||||||
&log,
|
|
||||||
)?;
|
|
||||||
} else {
|
} else {
|
||||||
cursor_visible = true;
|
cursor_visible = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ use std::ffi::CStr;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
use std::sync::{Mutex, Weak};
|
||||||
|
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
use nix::libc::c_int;
|
use nix::libc::c_int;
|
||||||
|
@ -24,6 +26,11 @@ use crate::backend::egl::{
|
||||||
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
use crate::backend::egl::{BufferAccessError, EGLBuffer, Format};
|
use crate::backend::egl::{BufferAccessError, EGLBuffer, Format};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
lazy_static! {
|
||||||
|
pub(crate) static ref BUFFER_READER: Mutex<Option<WeakBufferReader>> = Mutex::new(None);
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around [`ffi::EGLDisplay`](ffi::egl::types::EGLDisplay) to ensure display is only destroyed
|
/// Wrapper around [`ffi::EGLDisplay`](ffi::egl::types::EGLDisplay) to ensure display is only destroyed
|
||||||
/// once all resources bound to it have been dropped.
|
/// once all resources bound to it have been dropped.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -535,7 +542,18 @@ impl EGLDisplay {
|
||||||
ffi::egl::BindWaylandDisplayWL(**self.display, display.c_ptr() as *mut _)
|
ffi::egl::BindWaylandDisplayWL(**self.display, display.c_ptr() as *mut _)
|
||||||
})
|
})
|
||||||
.map_err(Error::OtherEGLDisplayAlreadyBound)?;
|
.map_err(Error::OtherEGLDisplayAlreadyBound)?;
|
||||||
Ok(EGLBufferReader::new(self.display.clone(), display.c_ptr()))
|
let reader = EGLBufferReader::new(self.display.clone(), display.c_ptr());
|
||||||
|
let mut global = BUFFER_READER.lock().unwrap();
|
||||||
|
if global.as_ref().and_then(|x| x.upgrade()).is_some() {
|
||||||
|
warn!(
|
||||||
|
self.logger,
|
||||||
|
"Double bind_wl_display, smithay does not support this, please report"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*global = Some(WeakBufferReader {
|
||||||
|
display: Arc::downgrade(&self.display),
|
||||||
|
});
|
||||||
|
Ok(reader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,6 +681,24 @@ pub struct EGLBufferReader {
|
||||||
wayland: Option<Arc<*mut wl_display>>,
|
wayland: Option<Arc<*mut wl_display>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "use_system_lib")]
|
||||||
|
pub(crate) struct WeakBufferReader {
|
||||||
|
display: Weak<EGLDisplayHandle>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "use_system_lib")]
|
||||||
|
impl WeakBufferReader {
|
||||||
|
pub fn upgrade(&self) -> Option<EGLBufferReader> {
|
||||||
|
Some(EGLBufferReader {
|
||||||
|
display: self.display.upgrade()?,
|
||||||
|
wayland: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "use_system_lib")]
|
||||||
|
unsafe impl Send for EGLBufferReader {}
|
||||||
|
|
||||||
#[cfg(feature = "use_system_lib")]
|
#[cfg(feature = "use_system_lib")]
|
||||||
impl EGLBufferReader {
|
impl EGLBufferReader {
|
||||||
fn new(display: Arc<EGLDisplayHandle>, wayland: *mut wl_display) -> Self {
|
fn new(display: Arc<EGLDisplayHandle>, wayland: *mut wl_display) -> Self {
|
||||||
|
@ -825,7 +861,7 @@ impl EGLBufferReader {
|
||||||
#[cfg(feature = "use_system_lib")]
|
#[cfg(feature = "use_system_lib")]
|
||||||
impl Drop for EGLBufferReader {
|
impl Drop for EGLBufferReader {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Ok(wayland) = Arc::try_unwrap(self.wayland.take().unwrap()) {
|
if let Some(wayland) = self.wayland.take().and_then(|x| Arc::try_unwrap(x).ok()) {
|
||||||
if !wayland.is_null() {
|
if !wayland.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// ignore errors on drop
|
// ignore errors on drop
|
||||||
|
|
|
@ -152,6 +152,8 @@ pub struct Gles2Renderer {
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
dmabuf_cache: HashMap<WeakDmabuf, Gles2Texture>,
|
dmabuf_cache: HashMap<WeakDmabuf, Gles2Texture>,
|
||||||
egl: EGLContext,
|
egl: EGLContext,
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
egl_reader: Option<EGLBufferReader>,
|
||||||
gl: ffi::Gles2,
|
gl: ffi::Gles2,
|
||||||
destruction_callback: Receiver<CleanupResource>,
|
destruction_callback: Receiver<CleanupResource>,
|
||||||
destruction_callback_sender: Sender<CleanupResource>,
|
destruction_callback_sender: Sender<CleanupResource>,
|
||||||
|
@ -446,6 +448,8 @@ impl Gles2Renderer {
|
||||||
id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst),
|
id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst),
|
||||||
gl,
|
gl,
|
||||||
egl: context,
|
egl: context,
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
egl_reader: None,
|
||||||
extensions: exts,
|
extensions: exts,
|
||||||
programs,
|
programs,
|
||||||
target_buffer: None,
|
target_buffer: None,
|
||||||
|
@ -619,15 +623,33 @@ impl ImportShm for Gles2Renderer {
|
||||||
feature = "use_system_lib"
|
feature = "use_system_lib"
|
||||||
))]
|
))]
|
||||||
impl ImportEgl for Gles2Renderer {
|
impl ImportEgl for Gles2Renderer {
|
||||||
fn import_egl_buffer(
|
fn bind_wl_display(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
display: &wayland_server::Display,
|
||||||
reader: &EGLBufferReader,
|
) -> Result<(), crate::backend::egl::Error> {
|
||||||
) -> Result<Gles2Texture, Gles2Error> {
|
self.egl_reader = Some(self.egl.display.bind_wl_display(display)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unbind_wl_display(&mut self) {
|
||||||
|
self.egl_reader = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn egl_reader(&self) -> Option<&EGLBufferReader> {
|
||||||
|
self.egl_reader.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_egl_buffer(&mut self, buffer: &wl_buffer::WlBuffer) -> Result<Gles2Texture, Gles2Error> {
|
||||||
if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") {
|
if !self.extensions.iter().any(|ext| ext == "GL_OES_EGL_image") {
|
||||||
return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"]));
|
return Err(Gles2Error::GLExtensionNotSupported(&["GL_OES_EGL_image"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.egl_reader().is_none() {
|
||||||
|
return Err(Gles2Error::EGLBufferAccessError(
|
||||||
|
crate::backend::egl::BufferAccessError::NotManaged(crate::backend::egl::EGLError::BadDisplay),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// We can not use the caching logic for textures here as the
|
// We can not use the caching logic for textures here as the
|
||||||
// egl buffers a potentially managed external which will fail the
|
// egl buffers a potentially managed external which will fail the
|
||||||
// clean up check if the buffer is still alive. For wl_drm the
|
// clean up check if the buffer is still alive. For wl_drm the
|
||||||
|
@ -635,7 +657,10 @@ impl ImportEgl for Gles2Renderer {
|
||||||
// will never be cleaned up.
|
// will never be cleaned up.
|
||||||
self.make_current()?;
|
self.make_current()?;
|
||||||
|
|
||||||
let egl = reader
|
let egl = self
|
||||||
|
.egl_reader
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
.egl_buffer_contents(&buffer)
|
.egl_buffer_contents(&buffer)
|
||||||
.map_err(Gles2Error::EGLBufferAccessError)?;
|
.map_err(Gles2Error::EGLBufferAccessError)?;
|
||||||
|
|
||||||
|
@ -905,6 +930,8 @@ impl Drop for Gles2Renderer {
|
||||||
let _ = Box::from_raw(logger_ptr);
|
let _ = Box::from_raw(logger_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
let _ = self.egl_reader.take();
|
||||||
let _ = self.egl.unbind();
|
let _ = self.egl.unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,10 @@ use crate::backend::allocator::{dmabuf::Dmabuf, Format};
|
||||||
feature = "backend_egl",
|
feature = "backend_egl",
|
||||||
feature = "use_system_lib"
|
feature = "use_system_lib"
|
||||||
))]
|
))]
|
||||||
use crate::backend::egl::display::EGLBufferReader;
|
use crate::backend::egl::{
|
||||||
|
display::{EGLBufferReader, BUFFER_READER},
|
||||||
|
Error as EglError,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
/// Possible transformations to two-dimensional planes
|
/// Possible transformations to two-dimensional planes
|
||||||
|
@ -281,6 +284,34 @@ pub trait ImportShm: Renderer {
|
||||||
))]
|
))]
|
||||||
/// Trait for Renderers supporting importing wl_drm-based buffers.
|
/// Trait for Renderers supporting importing wl_drm-based buffers.
|
||||||
pub trait ImportEgl: Renderer {
|
pub trait ImportEgl: Renderer {
|
||||||
|
/// Binds the underlying EGL display to the given Wayland display.
|
||||||
|
///
|
||||||
|
/// This will allow clients to utilize EGL to create hardware-accelerated
|
||||||
|
/// surfaces. This renderer will thus be able to handle wl_drm-based buffers.
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// This might return [`EglExtensionNotSupported`](Error::EglExtensionNotSupported)
|
||||||
|
/// if binding is not supported by the EGL implementation.
|
||||||
|
///
|
||||||
|
/// This might return [`OtherEGLDisplayAlreadyBound`](Error::OtherEGLDisplayAlreadyBound)
|
||||||
|
/// if called for the same [`Display`] multiple times, as only one egl display may be bound at any given time.
|
||||||
|
fn bind_wl_display(&mut self, display: &wayland_server::Display) -> Result<(), EglError>;
|
||||||
|
|
||||||
|
/// Unbinds a previously bound egl display, if existing.
|
||||||
|
///
|
||||||
|
/// *Note*: As a result any previously created egl-based WlBuffers will not be readable anymore.
|
||||||
|
/// Your compositor will have to deal with existing buffers of *unknown* type.
|
||||||
|
fn unbind_wl_display(&mut self);
|
||||||
|
|
||||||
|
/// Returns the underlying [`EGLBufferReader`].
|
||||||
|
///
|
||||||
|
/// The primary use for this is calling [`buffer_dimensions`] or [`buffer_type`].
|
||||||
|
///
|
||||||
|
/// Returns `None` if no [`Display`] was previously bound to the underlying [`EGLDisplay`]
|
||||||
|
/// (see [`ImportEgl::bind_wl_display`]).
|
||||||
|
fn egl_reader(&self) -> Option<&EGLBufferReader>;
|
||||||
|
|
||||||
/// Import a given wl_drm-based buffer into the renderer (see [`buffer_type`]).
|
/// Import a given wl_drm-based buffer into the renderer (see [`buffer_type`]).
|
||||||
///
|
///
|
||||||
/// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`])
|
/// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`])
|
||||||
|
@ -295,7 +326,6 @@ pub trait ImportEgl: Renderer {
|
||||||
fn import_egl_buffer(
|
fn import_egl_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
egl: &EGLBufferReader,
|
|
||||||
) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>;
|
) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,12 +381,8 @@ pub trait ImportDma: Renderer {
|
||||||
// pub type ImportAll = Renderer + ImportShm + ImportEgl;
|
// pub type ImportAll = Renderer + ImportShm + ImportEgl;
|
||||||
|
|
||||||
/// Common trait for renderers of any wayland buffer type
|
/// Common trait for renderers of any wayland buffer type
|
||||||
#[cfg(all(
|
#[cfg(feature = "wayland_frontend")]
|
||||||
feature = "wayland_frontend",
|
pub trait ImportAll: Renderer {
|
||||||
feature = "backend_egl",
|
|
||||||
feature = "use_system_lib"
|
|
||||||
))]
|
|
||||||
pub trait ImportAll: Renderer + ImportShm + ImportEgl {
|
|
||||||
/// Import a given buffer into the renderer.
|
/// Import a given buffer into the renderer.
|
||||||
///
|
///
|
||||||
/// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`])
|
/// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`])
|
||||||
|
@ -380,21 +406,49 @@ pub trait ImportAll: Renderer + ImportShm + ImportEgl {
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
surface: Option<&SurfaceAttributes>,
|
surface: Option<&SurfaceAttributes>,
|
||||||
damage: &[Rectangle],
|
damage: &[Rectangle],
|
||||||
egl: Option<&EGLBufferReader>,
|
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>>;
|
||||||
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> {
|
|
||||||
match buffer_type(buffer, egl) {
|
|
||||||
Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)),
|
|
||||||
Some(BufferType::Egl) => Some(self.import_egl_buffer(buffer, egl.unwrap())),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Do this with specialization, when possible and do default implementations
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "wayland_frontend",
|
feature = "wayland_frontend",
|
||||||
feature = "backend_egl",
|
feature = "backend_egl",
|
||||||
feature = "use_system_lib"
|
feature = "use_system_lib"
|
||||||
))]
|
))]
|
||||||
impl<R: Renderer + ImportShm + ImportEgl> ImportAll for R {}
|
impl<R: Renderer + ImportShm + ImportEgl + ImportDma> ImportAll for R {
|
||||||
|
fn import_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
|
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> {
|
||||||
|
match buffer_type(buffer) {
|
||||||
|
Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)),
|
||||||
|
Some(BufferType::Egl) => Some(self.import_egl_buffer(buffer)),
|
||||||
|
Some(BufferType::Dma) => Some(self.import_dma_buffer(buffer)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(
|
||||||
|
feature = "wayland_frontend",
|
||||||
|
not(all(feature = "backend_egl", feature = "use_system_lib"))
|
||||||
|
))]
|
||||||
|
impl<R: Renderer + ImportShm + ImportDma> ImportAll for R {
|
||||||
|
fn import_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
|
) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> {
|
||||||
|
match buffer_type(buffer) {
|
||||||
|
Some(BufferType::Shm) => Some(self.import_shm_buffer(buffer, surface, damage)),
|
||||||
|
Some(BufferType::Dma) => Some(self.import_dma_buffer(buffer)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
|
@ -413,94 +467,58 @@ pub enum BufferType {
|
||||||
///
|
///
|
||||||
/// Returns `None` if the type is not known to smithay
|
/// Returns `None` if the type is not known to smithay
|
||||||
/// or otherwise not supported (e.g. not initialized using one of smithays [`crate::wayland`]-handlers).
|
/// or otherwise not supported (e.g. not initialized using one of smithays [`crate::wayland`]-handlers).
|
||||||
#[cfg(all(
|
#[cfg(feature = "wayland_frontend")]
|
||||||
feature = "wayland_frontend",
|
pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
|
||||||
feature = "backend_egl",
|
|
||||||
feature = "use_system_lib"
|
|
||||||
))]
|
|
||||||
pub fn buffer_type(
|
|
||||||
buffer: &wl_buffer::WlBuffer,
|
|
||||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
) -> Option<BufferType> {
|
|
||||||
if buffer.as_ref().user_data().get::<Dmabuf>().is_some() {
|
if buffer.as_ref().user_data().get::<Dmabuf>().is_some() {
|
||||||
Some(BufferType::Dma)
|
return Some(BufferType::Dma);
|
||||||
} else if egl_buffer_reader
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
if BUFFER_READER
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
.and_then(|x| x.upgrade())
|
||||||
.and_then(|x| x.egl_buffer_dimensions(&buffer))
|
.and_then(|x| x.egl_buffer_dimensions(&buffer))
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
Some(BufferType::Egl)
|
return Some(BufferType::Egl);
|
||||||
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
|
||||||
Some(BufferType::Shm)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the *type* of a wl_buffer
|
if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
||||||
///
|
return Some(BufferType::Shm);
|
||||||
/// Returns `None` if the type is not recognized by smithay or otherwise not supported.
|
|
||||||
#[cfg(all(
|
|
||||||
feature = "wayland_frontend",
|
|
||||||
not(all(feature = "backend_egl", feature = "use_system_lib"))
|
|
||||||
))]
|
|
||||||
pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
|
|
||||||
if buffer.as_ref().user_data().get::<Dmabuf>().is_some() {
|
|
||||||
Some(BufferType::Dma)
|
|
||||||
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
|
||||||
Some(BufferType::Shm)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the dimensions of a wl_buffer
|
/// Returns the dimensions of a wl_buffer
|
||||||
///
|
///
|
||||||
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
|
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
|
||||||
#[cfg(all(
|
#[cfg(feature = "wayland_frontend")]
|
||||||
feature = "wayland_frontend",
|
|
||||||
feature = "backend_egl",
|
|
||||||
feature = "use_system_lib"
|
|
||||||
))]
|
|
||||||
pub fn buffer_dimensions(
|
|
||||||
buffer: &wl_buffer::WlBuffer,
|
|
||||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
|
||||||
) -> Option<(i32, i32)> {
|
|
||||||
use crate::backend::allocator::Buffer;
|
|
||||||
|
|
||||||
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
|
|
||||||
Some((buf.width() as i32, buf.height() as i32))
|
|
||||||
} else if let Some((w, h)) = egl_buffer_reader
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|x| x.egl_buffer_dimensions(&buffer))
|
|
||||||
{
|
|
||||||
Some((w, h))
|
|
||||||
} else if let Ok((w, h)) =
|
|
||||||
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
|
|
||||||
{
|
|
||||||
Some((w, h))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the dimensions of a wl_buffer
|
|
||||||
///
|
|
||||||
/// *Note*: This will only return dimensions for buffer types known to smithay (see [`buffer_type`])
|
|
||||||
#[cfg(all(
|
|
||||||
feature = "wayland_frontend",
|
|
||||||
not(all(feature = "backend_egl", feature = "use_system_lib"))
|
|
||||||
))]
|
|
||||||
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> {
|
pub fn buffer_dimensions(buffer: &wl_buffer::WlBuffer) -> Option<(i32, i32)> {
|
||||||
use crate::backend::allocator::Buffer;
|
use crate::backend::allocator::Buffer;
|
||||||
|
|
||||||
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
|
if let Some(buf) = buffer.as_ref().user_data().get::<Dmabuf>() {
|
||||||
Some((buf.width() as i32, buf.height() as i32))
|
return Some((buf.width() as i32, buf.height() as i32));
|
||||||
} else if let Ok((w, h)) =
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
if let Some((w, h)) = BUFFER_READER
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|x| x.upgrade())
|
||||||
|
.and_then(|x| x.egl_buffer_dimensions(&buffer))
|
||||||
|
{
|
||||||
|
return Some((w, h));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok((w, h)) =
|
||||||
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
|
crate::wayland::shm::with_buffer_contents(&buffer, |_, data| (data.width, data.height))
|
||||||
{
|
{
|
||||||
Some((w, h))
|
return Some((w, h));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue