renderer: Split Renderer trait into Import sub-traits
This commit is contained in:
parent
2661b86019
commit
969cdda85c
|
@ -48,7 +48,7 @@ pkg-config = { version = "0.3.17", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_winit", "renderer_gl", "xwayland", "wayland_frontend", "slog-stdlog"]
|
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_winit", "renderer_gl", "xwayland", "wayland_frontend", "slog-stdlog"]
|
||||||
backend_winit = ["winit", "wayland-server/dlopen", "backend_egl", "wayland-egl", "renderer_gl", "use_system_lib"]
|
backend_winit = ["winit", "wayland-server/dlopen", "backend_egl", "wayland-egl", "renderer_gl"]
|
||||||
backend_drm = ["drm", "drm-ffi"]
|
backend_drm = ["drm", "drm-ffi"]
|
||||||
backend_gbm = ["gbm"]
|
backend_gbm = ["gbm"]
|
||||||
backend_egl = ["gl_generator"]
|
backend_egl = ["gl_generator"]
|
||||||
|
|
|
@ -5,8 +5,7 @@ use std::cell::RefCell;
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
egl::display::EGLBufferReader,
|
renderer::{Frame, Renderer, Texture, Transform, ImportShm, BufferType, buffer_type},
|
||||||
renderer::{Frame, Renderer, Texture, Transform},
|
|
||||||
SwapBuffersError,
|
SwapBuffersError,
|
||||||
},
|
},
|
||||||
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
||||||
|
@ -17,6 +16,16 @@ use smithay::{
|
||||||
seat::CursorImageRole,
|
seat::CursorImageRole,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
use smithay::backend::{
|
||||||
|
egl::display::EGLBufferReader,
|
||||||
|
renderer::ImportEgl
|
||||||
|
};
|
||||||
|
// 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};
|
||||||
|
|
||||||
|
@ -37,13 +46,14 @@ 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>,
|
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>,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl,
|
||||||
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,
|
||||||
|
@ -62,6 +72,7 @@ where
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
surface,
|
surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader,
|
egl_buffer_reader,
|
||||||
(x - dx, y - dy),
|
(x - dx, y - dy),
|
||||||
token,
|
token,
|
||||||
|
@ -73,13 +84,14 @@ 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>,
|
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>,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl,
|
||||||
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,
|
||||||
|
@ -95,6 +107,12 @@ 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(
|
||||||
|
&buffer,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
egl_buffer_reader
|
||||||
|
) {
|
||||||
|
Some(BufferType::Shm) => {
|
||||||
let damage = attributes
|
let damage = attributes
|
||||||
.damage
|
.damage
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -104,28 +122,30 @@ where
|
||||||
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
match renderer.import_buffer(&buffer, Some(&attributes), &damage, egl_buffer_reader) {
|
let result = renderer.import_shm_buffer(&buffer, Some(&attributes), &damage);
|
||||||
Ok(m) => {
|
if result.is_ok() {
|
||||||
let buffer = if smithay::wayland::shm::with_buffer_contents(
|
|
||||||
&buffer,
|
|
||||||
|_, _| (),
|
|
||||||
)
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
buffer.release();
|
buffer.release();
|
||||||
|
}
|
||||||
|
Some(result)
|
||||||
|
},
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
Some(BufferType::Egl) => Some(renderer.import_egl_buffer(&buffer, egl_buffer_reader.unwrap())),
|
||||||
|
_ => {
|
||||||
|
error!(log, "Unknown buffer format for: {:?}", buffer);
|
||||||
None
|
None
|
||||||
} else {
|
}
|
||||||
Some(buffer)
|
|
||||||
};
|
};
|
||||||
data.texture = Some(Box::new(BufferTextures { buffer, texture: m })
|
match texture {
|
||||||
|
Some(Ok(m)) => {
|
||||||
|
data.texture = Some(Box::new(BufferTextures { buffer: Some(buffer), texture: m })
|
||||||
as Box<dyn std::any::Any + 'static>)
|
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.
|
||||||
// already logged the error
|
Some(Err(err)) => {
|
||||||
Err(err) => {
|
|
||||||
warn!(log, "Error loading buffer: {:?}", err);
|
warn!(log, "Error loading buffer: {:?}", err);
|
||||||
buffer.release();
|
buffer.release();
|
||||||
}
|
},
|
||||||
|
None => buffer.release(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,6 +201,7 @@ 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>,
|
egl_buffer_reader: Option<&EGLBufferReader>,
|
||||||
window_map: &MyWindowMap,
|
window_map: &MyWindowMap,
|
||||||
output_rect: Option<Rectangle>,
|
output_rect: Option<Rectangle>,
|
||||||
|
@ -188,7 +209,7 @@ pub fn draw_windows<R, E, F, T>(
|
||||||
log: &::slog::Logger,
|
log: &::slog::Logger,
|
||||||
) -> Result<(), SwapBuffersError>
|
) -> Result<(), SwapBuffersError>
|
||||||
where
|
where
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F>,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl,
|
||||||
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,
|
||||||
|
@ -210,6 +231,7 @@ where
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
&wl_surface,
|
&wl_surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader,
|
egl_buffer_reader,
|
||||||
initial_place,
|
initial_place,
|
||||||
compositor_token,
|
compositor_token,
|
||||||
|
@ -227,13 +249,14 @@ 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>,
|
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>,
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportShm + ImportEgl,
|
||||||
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,
|
||||||
|
@ -244,5 +267,14 @@ 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(renderer, frame, surface, egl_buffer_reader, (x, y), token, log)
|
draw_surface_tree(
|
||||||
|
renderer,
|
||||||
|
frame,
|
||||||
|
surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
egl_buffer_reader,
|
||||||
|
(x, y),
|
||||||
|
token,
|
||||||
|
log
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use std::{process::Command, sync::atomic::Ordering};
|
use std::{process::Command, sync::atomic::Ordering};
|
||||||
|
|
||||||
use crate::{udev::UdevData, winit::WinitData, AnvilState};
|
use crate::AnvilState;
|
||||||
|
#[cfg(feature = "udev")]
|
||||||
|
use crate::udev::UdevData;
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
|
use crate::winit::WinitData;
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{
|
backend::input::{
|
||||||
|
|
|
@ -839,7 +839,7 @@ fn surface_commit(
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "egl"))]
|
#[cfg(not(feature = "egl"))]
|
||||||
{
|
{
|
||||||
next_state.dimensions = buffer_dimensions(&buffer, None);
|
next_state.dimensions = buffer_dimensions(&buffer);
|
||||||
}
|
}
|
||||||
next_state.buffer = Some(buffer);
|
next_state.buffer = Some(buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,7 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
||||||
|
|
||||||
init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());
|
init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
let shell_handles = init_shell::<BackendData>(&mut display.borrow_mut(), log.clone());
|
let shell_handles = init_shell::<BackendData>(&mut display.borrow_mut(), 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()
|
||||||
|
|
|
@ -110,6 +110,7 @@ pub fn run_udev(
|
||||||
* Initialize the compositor
|
* Initialize the compositor
|
||||||
*/
|
*/
|
||||||
let pointer_bytes = include_bytes!("../resources/cursor2.rgba");
|
let pointer_bytes = include_bytes!("../resources/cursor2.rgba");
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
let primary_gpu = primary_gpu(&session.seat()).unwrap_or_default();
|
let primary_gpu = primary_gpu(&session.seat()).unwrap_or_default();
|
||||||
|
|
||||||
// setup the timer
|
// setup the timer
|
||||||
|
@ -118,6 +119,7 @@ pub fn run_udev(
|
||||||
let data = UdevData {
|
let data = UdevData {
|
||||||
session,
|
session,
|
||||||
output_map: Vec::new(),
|
output_map: Vec::new(),
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
primary_gpu,
|
primary_gpu,
|
||||||
backends: HashMap::new(),
|
backends: HashMap::new(),
|
||||||
signaler: session_signal.clone(),
|
signaler: session_signal.clone(),
|
||||||
|
@ -669,9 +671,6 @@ fn render_surface(
|
||||||
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
|
||||||
|
@ -693,6 +692,7 @@ fn render_surface(
|
||||||
draw_windows(
|
draw_windows(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader,
|
egl_buffer_reader,
|
||||||
window_map,
|
window_map,
|
||||||
Some(Rectangle {
|
Some(Rectangle {
|
||||||
|
@ -720,6 +720,7 @@ fn render_surface(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
wl_surface,
|
wl_surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader,
|
egl_buffer_reader,
|
||||||
(ptr_x, ptr_y),
|
(ptr_x, ptr_y),
|
||||||
*compositor_token,
|
*compositor_token,
|
||||||
|
@ -744,6 +745,7 @@ fn render_surface(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
wl_surface,
|
wl_surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader,
|
egl_buffer_reader,
|
||||||
(ptr_x, ptr_y),
|
(ptr_x, ptr_y),
|
||||||
*compositor_token,
|
*compositor_token,
|
||||||
|
|
|
@ -37,9 +37,6 @@ pub fn run_winit(
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok();
|
let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok();
|
||||||
#[cfg(not(feature = "egl"))]
|
|
||||||
let reader = None;
|
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
if reader.is_some() {
|
if reader.is_some() {
|
||||||
info!(log, "EGL hardware-acceleration enabled");
|
info!(log, "EGL hardware-acceleration enabled");
|
||||||
|
@ -114,6 +111,7 @@ pub fn run_winit(
|
||||||
draw_windows(
|
draw_windows(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
state.egl_reader.as_ref(),
|
state.egl_reader.as_ref(),
|
||||||
&*state.window_map.borrow(),
|
&*state.window_map.borrow(),
|
||||||
None,
|
None,
|
||||||
|
@ -131,6 +129,7 @@ pub fn run_winit(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
surface,
|
surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
state.egl_reader.as_ref(),
|
state.egl_reader.as_ref(),
|
||||||
(x as i32, y as i32),
|
(x as i32, y as i32),
|
||||||
state.ctoken,
|
state.ctoken,
|
||||||
|
@ -158,6 +157,7 @@ pub fn run_winit(
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
surface,
|
surface,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
state.egl_reader.as_ref(),
|
state.egl_reader.as_ref(),
|
||||||
(x as i32, y as i32),
|
(x as i32, y as i32),
|
||||||
state.ctoken,
|
state.ctoken,
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! Implementation of the rendering traits using OpenGL ES 2
|
//! Implementation of the rendering traits using OpenGL ES 2
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -32,12 +30,17 @@ use crate::backend::SwapBuffersError;
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::egl::display::EGLBufferReader, utils::Rectangle, wayland::compositor::SurfaceAttributes,
|
utils::Rectangle,
|
||||||
|
wayland::compositor::SurfaceAttributes,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
use wayland_commons::user_data::UserDataMap;
|
use crate::backend::egl::display::EGLBufferReader;
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
use super::ImportShm;
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||||
|
use super::ImportEgl;
|
||||||
|
|
||||||
#[allow(clippy::all, missing_docs)]
|
#[allow(clippy::all, missing_docs)]
|
||||||
pub mod ffi {
|
pub mod ffi {
|
||||||
|
@ -221,10 +224,6 @@ pub enum Gles2Error {
|
||||||
#[error("Error accessing the buffer ({0:?})")]
|
#[error("Error accessing the buffer ({0:?})")]
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
EGLBufferAccessError(crate::backend::egl::BufferAccessError),
|
EGLBufferAccessError(crate::backend::egl::BufferAccessError),
|
||||||
/// The buffer backend is unknown or unsupported
|
|
||||||
#[error("Error accessing the buffer")]
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
UnknownBufferType,
|
|
||||||
/// This rendering operation was called without a previous `begin`-call
|
/// This rendering operation was called without a previous `begin`-call
|
||||||
#[error("Call begin before doing any rendering operations")]
|
#[error("Call begin before doing any rendering operations")]
|
||||||
UnconstraintRenderingOperation,
|
UnconstraintRenderingOperation,
|
||||||
|
@ -243,7 +242,6 @@ impl From<Gles2Error> for SwapBuffersError {
|
||||||
x @ Gles2Error::FramebufferBindingError
|
x @ Gles2Error::FramebufferBindingError
|
||||||
| x @ Gles2Error::BindBufferEGLError(_)
|
| x @ Gles2Error::BindBufferEGLError(_)
|
||||||
| x @ Gles2Error::UnsupportedPixelFormat(_)
|
| x @ Gles2Error::UnsupportedPixelFormat(_)
|
||||||
| x @ Gles2Error::UnknownBufferType
|
|
||||||
| x @ Gles2Error::BufferAccessError(_)
|
| x @ Gles2Error::BufferAccessError(_)
|
||||||
| x @ Gles2Error::EGLBufferAccessError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)),
|
| x @ Gles2Error::EGLBufferAccessError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||||
}
|
}
|
||||||
|
@ -500,9 +498,9 @@ impl Gles2Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gles2Renderer {
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
fn import_shm(
|
impl ImportShm for Gles2Renderer {
|
||||||
|
fn import_shm_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
surface: Option<&SurfaceAttributes>,
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
@ -613,7 +611,19 @@ impl Gles2Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
fn import_egl(
|
fn shm_formats(&self) -> &[wl_shm::Format] {
|
||||||
|
&[
|
||||||
|
wl_shm::Format::Abgr8888,
|
||||||
|
wl_shm::Format::Xbgr8888,
|
||||||
|
wl_shm::Format::Argb8888,
|
||||||
|
wl_shm::Format::Xrgb8888,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
impl ImportEgl for Gles2Renderer {
|
||||||
|
fn import_egl_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
reader: &EGLBufferReader,
|
reader: &EGLBufferReader,
|
||||||
|
@ -654,8 +664,10 @@ impl Gles2Renderer {
|
||||||
|
|
||||||
Ok(texture)
|
Ok(texture)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
impl Gles2Renderer {
|
||||||
fn existing_dmabuf_texture(
|
fn existing_dmabuf_texture(
|
||||||
&self,
|
&self,
|
||||||
buffer: &wl_buffer::WlBuffer,
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
@ -880,16 +892,6 @@ impl Renderer for Gles2Renderer {
|
||||||
type TextureId = Gles2Texture;
|
type TextureId = Gles2Texture;
|
||||||
type Frame = Gles2Frame;
|
type Frame = Gles2Frame;
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
fn shm_formats(&self) -> &[wl_shm::Format] {
|
|
||||||
&[
|
|
||||||
wl_shm::Format::Abgr8888,
|
|
||||||
wl_shm::Format::Xbgr8888,
|
|
||||||
wl_shm::Format::Argb8888,
|
|
||||||
wl_shm::Format::Xrgb8888,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
fn import_bitmap<C: std::ops::Deref<Target = [u8]>>(
|
fn import_bitmap<C: std::ops::Deref<Target = [u8]>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -935,40 +937,6 @@ impl Renderer for Gles2Renderer {
|
||||||
Ok(texture)
|
Ok(texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
fn import_buffer(
|
|
||||||
&mut self,
|
|
||||||
buffer: &wl_buffer::WlBuffer,
|
|
||||||
surface: Option<&SurfaceAttributes>,
|
|
||||||
damage: &[Rectangle],
|
|
||||||
egl: Option<&EGLBufferReader>,
|
|
||||||
) -> Result<Self::TextureId, Self::Error> {
|
|
||||||
let texture = if egl.and_then(|egl| egl.egl_buffer_dimensions(&buffer)).is_some() {
|
|
||||||
self.import_egl(&buffer, egl.unwrap())
|
|
||||||
} else if crate::wayland::shm::with_buffer_contents(&buffer, |_, _| ()).is_ok() {
|
|
||||||
self.import_shm(&buffer, surface, damage)
|
|
||||||
} else {
|
|
||||||
Err(Gles2Error::UnknownBufferType)
|
|
||||||
}?;
|
|
||||||
|
|
||||||
// we want to keep the texture alive for as long as the buffer is alive.
|
|
||||||
// otherwise `existing_texture` will not work,
|
|
||||||
// if the user does not keep the texture alive long enough.
|
|
||||||
buffer.as_ref().user_data().set_threadsafe(|| UserDataMap::new());
|
|
||||||
if let Some(map) = buffer.as_ref().user_data().get::<UserDataMap>() {
|
|
||||||
map.insert_if_missing(|| Vec::<RefCell<Option<Gles2Texture>>>::new());
|
|
||||||
if let Some(vec) = map.get::<RefCell<Vec<Option<Gles2Texture>>>>() {
|
|
||||||
let mut vec = vec.borrow_mut();
|
|
||||||
while vec.len() < self.id {
|
|
||||||
vec.push(None);
|
|
||||||
}
|
|
||||||
vec[self.id] = Some(texture.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(texture)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<F, R>(
|
fn render<F, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
width: u32,
|
width: u32,
|
||||||
|
|
|
@ -18,7 +18,7 @@ use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
#[cfg(feature = "renderer_gl")]
|
#[cfg(feature = "renderer_gl")]
|
||||||
pub mod gles2;
|
pub mod gles2;
|
||||||
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))]
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
use crate::backend::egl::display::EGLBufferReader;
|
use crate::backend::egl::display::EGLBufferReader;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
@ -216,39 +216,6 @@ pub trait Renderer {
|
||||||
image: &image::ImageBuffer<image::Rgba<u8>, C>,
|
image: &image::ImageBuffer<image::Rgba<u8>, C>,
|
||||||
) -> Result<Self::TextureId, Self::Error>;
|
) -> Result<Self::TextureId, Self::Error>;
|
||||||
|
|
||||||
/// Returns supported formats for shared memory buffers.
|
|
||||||
///
|
|
||||||
/// Will always contain At least `Argb8888` and `Xrgb8888`.
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
fn shm_formats(&self) -> &[wl_shm::Format] {
|
|
||||||
// Mandatory
|
|
||||||
&[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Import a given buffer into the renderer.
|
|
||||||
///
|
|
||||||
/// Returns a texture_id, which can be used with `render_texture(_at)` or implementation-specific functions.
|
|
||||||
///
|
|
||||||
/// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it.
|
|
||||||
///
|
|
||||||
/// This operation needs no bound or default rendering target.
|
|
||||||
///
|
|
||||||
/// The implementation defines, if the id keeps being valid, if the buffer is released,
|
|
||||||
/// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again.
|
|
||||||
///
|
|
||||||
/// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended.
|
|
||||||
///
|
|
||||||
/// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided
|
|
||||||
/// with an empty list `&[]`, the renderer is allowed to not update the texture at all.
|
|
||||||
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl"))]
|
|
||||||
fn import_buffer(
|
|
||||||
&mut self,
|
|
||||||
buffer: &wl_buffer::WlBuffer,
|
|
||||||
surface: Option<&SurfaceAttributes>,
|
|
||||||
damage: &[Rectangle],
|
|
||||||
egl: Option<&EGLBufferReader>,
|
|
||||||
) -> Result<Self::TextureId, Self::Error>;
|
|
||||||
|
|
||||||
/// Initialize a rendering context on the current rendering target with given dimensions and transformation.
|
/// Initialize a rendering context on the current rendering target with given dimensions and transformation.
|
||||||
///
|
///
|
||||||
/// This function *may* error, if:
|
/// This function *may* error, if:
|
||||||
|
@ -267,6 +234,102 @@ pub trait Renderer {
|
||||||
F: FnOnce(&mut Self, &mut Self::Frame) -> R;
|
F: FnOnce(&mut Self, &mut Self::Frame) -> R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
/// Trait for Renderers supporting importing shm-based buffers.
|
||||||
|
pub trait ImportShm: Renderer {
|
||||||
|
/// Import a given shm-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`])
|
||||||
|
/// or implementation-specific functions.
|
||||||
|
///
|
||||||
|
/// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it.
|
||||||
|
/// This operation needs no bound or default rendering target.
|
||||||
|
///
|
||||||
|
/// The implementation defines, if the id keeps being valid, if the buffer is released,
|
||||||
|
/// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again.
|
||||||
|
///
|
||||||
|
/// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended.
|
||||||
|
///
|
||||||
|
/// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided
|
||||||
|
/// with an empty list `&[]`, the renderer is allowed to not update the texture at all.
|
||||||
|
fn import_shm_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
|
) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>;
|
||||||
|
|
||||||
|
/// Returns supported formats for shared memory buffers.
|
||||||
|
///
|
||||||
|
/// Will always contain At least `Argb8888` and `Xrgb8888`.
|
||||||
|
fn shm_formats(&self) -> &[wl_shm::Format] {
|
||||||
|
// Mandatory
|
||||||
|
&[wl_shm::Format::Argb8888, wl_shm::Format::Xrgb8888]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
/// Trait for Renderers supporting importing wl_drm-based buffers.
|
||||||
|
pub trait ImportEgl: Renderer {
|
||||||
|
/// 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`])
|
||||||
|
/// or implementation-specific functions.
|
||||||
|
///
|
||||||
|
/// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it.
|
||||||
|
///
|
||||||
|
/// This operation needs no bound or default rendering target.
|
||||||
|
///
|
||||||
|
/// The implementation defines, if the id keeps being valid, if the buffer is released,
|
||||||
|
/// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again.
|
||||||
|
fn import_egl_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
egl: &EGLBufferReader,
|
||||||
|
) -> Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace this with a trait_alias, once that is stabilized.
|
||||||
|
// pub type ImportAll = Renderer + ImportShm + ImportEgl;
|
||||||
|
|
||||||
|
/// Common trait for renderers of any wayland buffer type
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
pub trait ImportAll: Renderer + ImportShm + ImportEgl {
|
||||||
|
/// Import a given buffer into the renderer.
|
||||||
|
///
|
||||||
|
/// Returns a texture_id, which can be used with [`Frame::render_texture`] (or [`Frame::render_texture_at`])
|
||||||
|
/// or implementation-specific functions.
|
||||||
|
///
|
||||||
|
/// If not otherwise defined by the implementation, this texture id is only valid for the renderer, that created it.
|
||||||
|
///
|
||||||
|
/// This operation needs no bound or default rendering target.
|
||||||
|
///
|
||||||
|
/// The implementation defines, if the id keeps being valid, if the buffer is released,
|
||||||
|
/// to avoid relying on implementation details, keep the buffer alive, until you destroyed this texture again.
|
||||||
|
///
|
||||||
|
/// If provided the `SurfaceAttributes` can be used to do caching of rendering resources and is generally recommended.
|
||||||
|
///
|
||||||
|
/// The `damage` argument provides a list of rectangle locating parts of the buffer that need to be updated. When provided
|
||||||
|
/// with an empty list `&[]`, the renderer is allowed to not update the texture at all.
|
||||||
|
///
|
||||||
|
/// Returns `None`, if the buffer type cannot be determined.
|
||||||
|
fn import_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &wl_buffer::WlBuffer,
|
||||||
|
surface: Option<&SurfaceAttributes>,
|
||||||
|
damage: &[Rectangle],
|
||||||
|
egl: Option<&EGLBufferReader>,
|
||||||
|
) -> 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(all(feature = "wayland_frontend", feature = "backend_egl", feature = "use_system_lib"))]
|
||||||
|
impl<R: Renderer + ImportShm + ImportEgl> ImportAll for R {}
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
/// Buffer type of a given wl_buffer, if managed by smithay
|
/// Buffer type of a given wl_buffer, if managed by smithay
|
||||||
|
@ -306,7 +369,7 @@ pub fn buffer_type(
|
||||||
/// Returns the *type* of a wl_buffer
|
/// Returns the *type* of a wl_buffer
|
||||||
///
|
///
|
||||||
/// Returns `None` if the type is not recognized by smithay or otherwise not supported.
|
/// Returns `None` if the type is not recognized by smithay or otherwise not supported.
|
||||||
#[cfg(all(feature = "wayland_frontend", not(feature = "backend_egl"), not(feature = "use_system_lib")))]
|
#[cfg(all(feature = "wayland_frontend", not(all(feature = "backend_egl", feature = "use_system_lib"))))]
|
||||||
pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
|
pub fn buffer_type(buffer: &wl_buffer::WlBuffer) -> Option<BufferType> {
|
||||||
use crate::backend::allocator::Buffer;
|
use crate::backend::allocator::Buffer;
|
||||||
|
|
||||||
|
@ -343,7 +406,7 @@ pub fn buffer_dimensions(
|
||||||
/// 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(feature = "wayland_frontend", not(feature = "backend_egl"), not(feature = "use_system_lib")))]
|
#[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;
|
||||||
|
|
||||||
|
|
|
@ -233,13 +233,13 @@ pub enum WinitEvent {
|
||||||
Refresh,
|
Refresh,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "use_system_lib")]
|
|
||||||
impl WinitGraphicsBackend {
|
impl WinitGraphicsBackend {
|
||||||
/// Bind a `wl_display` to allow hardware-accelerated clients using `wl_drm`.
|
/// Bind a `wl_display` to allow hardware-accelerated clients using `wl_drm`.
|
||||||
///
|
///
|
||||||
/// Returns an `EGLBufferReader` used to access the contents of these buffers.
|
/// Returns an `EGLBufferReader` used to access the contents of these buffers.
|
||||||
///
|
///
|
||||||
/// *Note*: Only on implementation of `wl_drm` can be bound by a single wayland display.
|
/// *Note*: Only on implementation of `wl_drm` can be bound by a single wayland display.
|
||||||
|
#[cfg(feature = "use_system_lib")]
|
||||||
pub fn bind_wl_display(&self, wl_display: &Display) -> Result<EGLBufferReader, EGLError> {
|
pub fn bind_wl_display(&self, wl_display: &Display) -> Result<EGLBufferReader, EGLError> {
|
||||||
self.display.bind_wl_display(wl_display)
|
self.display.bind_wl_display(wl_display)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue