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]
|
||||
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_gbm = ["gbm"]
|
||||
backend_egl = ["gl_generator"]
|
||||
|
|
|
@ -5,8 +5,7 @@ use std::cell::RefCell;
|
|||
use slog::Logger;
|
||||
use smithay::{
|
||||
backend::{
|
||||
egl::display::EGLBufferReader,
|
||||
renderer::{Frame, Renderer, Texture, Transform},
|
||||
renderer::{Frame, Renderer, Texture, Transform, ImportShm, BufferType, buffer_type},
|
||||
SwapBuffersError,
|
||||
},
|
||||
reexports::wayland_server::protocol::{wl_buffer, wl_surface},
|
||||
|
@ -17,6 +16,16 @@ use smithay::{
|
|||
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};
|
||||
|
||||
|
@ -37,13 +46,14 @@ pub fn draw_cursor<R, E, F, T>(
|
|||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
surface: &wl_surface::WlSurface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
||||
(x, y): (i32, i32),
|
||||
token: MyCompositorToken,
|
||||
log: &Logger,
|
||||
) -> Result<(), SwapBuffersError>
|
||||
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>,
|
||||
E: std::error::Error + Into<SwapBuffersError>,
|
||||
T: Texture + 'static,
|
||||
|
@ -62,6 +72,7 @@ where
|
|||
renderer,
|
||||
frame,
|
||||
surface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader,
|
||||
(x - dx, y - dy),
|
||||
token,
|
||||
|
@ -73,13 +84,14 @@ fn draw_surface_tree<R, E, F, T>(
|
|||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
root: &wl_surface::WlSurface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
||||
location: (i32, i32),
|
||||
compositor_token: MyCompositorToken,
|
||||
log: &Logger,
|
||||
) -> Result<(), SwapBuffersError>
|
||||
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>,
|
||||
E: std::error::Error + Into<SwapBuffersError>,
|
||||
T: Texture + 'static,
|
||||
|
@ -95,37 +107,45 @@ where
|
|||
let mut data = data.borrow_mut();
|
||||
if data.texture.is_none() {
|
||||
if let Some(buffer) = data.current_state.buffer.take() {
|
||||
let damage = attributes
|
||||
.damage
|
||||
.iter()
|
||||
.map(|dmg| match dmg {
|
||||
Damage::Buffer(rect) => *rect,
|
||||
// TODO also apply transformations
|
||||
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
match renderer.import_buffer(&buffer, Some(&attributes), &damage, egl_buffer_reader) {
|
||||
Ok(m) => {
|
||||
let buffer = if smithay::wayland::shm::with_buffer_contents(
|
||||
&buffer,
|
||||
|_, _| (),
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
let texture = match buffer_type(
|
||||
&buffer,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader
|
||||
) {
|
||||
Some(BufferType::Shm) => {
|
||||
let damage = attributes
|
||||
.damage
|
||||
.iter()
|
||||
.map(|dmg| match dmg {
|
||||
Damage::Buffer(rect) => *rect,
|
||||
// TODO also apply transformations
|
||||
Damage::Surface(rect) => rect.scale(attributes.buffer_scale),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let result = renderer.import_shm_buffer(&buffer, Some(&attributes), &damage);
|
||||
if result.is_ok() {
|
||||
buffer.release();
|
||||
None
|
||||
} else {
|
||||
Some(buffer)
|
||||
};
|
||||
data.texture = Some(Box::new(BufferTextures { buffer, texture: m })
|
||||
}
|
||||
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
|
||||
}
|
||||
};
|
||||
match texture {
|
||||
Some(Ok(m)) => {
|
||||
data.texture = Some(Box::new(BufferTextures { buffer: Some(buffer), texture: m })
|
||||
as Box<dyn std::any::Any + 'static>)
|
||||
}
|
||||
// there was an error reading the buffer, release it, we
|
||||
// already logged the error
|
||||
Err(err) => {
|
||||
// there was an error reading the buffer, release it.
|
||||
Some(Err(err)) => {
|
||||
warn!(log, "Error loading buffer: {:?}", err);
|
||||
buffer.release();
|
||||
}
|
||||
},
|
||||
None => buffer.release(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -181,6 +201,7 @@ where
|
|||
pub fn draw_windows<R, E, F, T>(
|
||||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
||||
window_map: &MyWindowMap,
|
||||
output_rect: Option<Rectangle>,
|
||||
|
@ -188,7 +209,7 @@ pub fn draw_windows<R, E, F, T>(
|
|||
log: &::slog::Logger,
|
||||
) -> Result<(), SwapBuffersError>
|
||||
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>,
|
||||
E: std::error::Error + Into<SwapBuffersError>,
|
||||
T: Texture + 'static,
|
||||
|
@ -210,6 +231,7 @@ where
|
|||
renderer,
|
||||
frame,
|
||||
&wl_surface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader,
|
||||
initial_place,
|
||||
compositor_token,
|
||||
|
@ -227,13 +249,14 @@ pub fn draw_dnd_icon<R, E, F, T>(
|
|||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
surface: &wl_surface::WlSurface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader: Option<&EGLBufferReader>,
|
||||
(x, y): (i32, i32),
|
||||
token: MyCompositorToken,
|
||||
log: &::slog::Logger,
|
||||
) -> Result<(), SwapBuffersError>
|
||||
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>,
|
||||
E: std::error::Error + Into<SwapBuffersError>,
|
||||
T: Texture + 'static,
|
||||
|
@ -244,5 +267,14 @@ where
|
|||
"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 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::{
|
||||
backend::input::{
|
||||
|
|
|
@ -839,7 +839,7 @@ fn surface_commit(
|
|||
}
|
||||
#[cfg(not(feature = "egl"))]
|
||||
{
|
||||
next_state.dimensions = buffer_dimensions(&buffer, None);
|
||||
next_state.dimensions = buffer_dimensions(&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());
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
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
|
||||
.borrow_mut()
|
||||
|
|
|
@ -110,6 +110,7 @@ pub fn run_udev(
|
|||
* Initialize the compositor
|
||||
*/
|
||||
let pointer_bytes = include_bytes!("../resources/cursor2.rgba");
|
||||
#[cfg(feature = "egl")]
|
||||
let primary_gpu = primary_gpu(&session.seat()).unwrap_or_default();
|
||||
|
||||
// setup the timer
|
||||
|
@ -118,6 +119,7 @@ pub fn run_udev(
|
|||
let data = UdevData {
|
||||
session,
|
||||
output_map: Vec::new(),
|
||||
#[cfg(feature = "egl")]
|
||||
primary_gpu,
|
||||
backends: HashMap::new(),
|
||||
signaler: session_signal.clone(),
|
||||
|
@ -669,9 +671,6 @@ fn render_surface(
|
|||
cursor_status: &mut CursorImageStatus,
|
||||
logger: &slog::Logger,
|
||||
) -> Result<(), SwapBuffersError> {
|
||||
#[cfg(not(feature = "egl"))]
|
||||
let egl_buffer_reader = None;
|
||||
|
||||
surface.frame_submitted()?;
|
||||
|
||||
// get output coordinates
|
||||
|
@ -693,6 +692,7 @@ fn render_surface(
|
|||
draw_windows(
|
||||
renderer,
|
||||
frame,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader,
|
||||
window_map,
|
||||
Some(Rectangle {
|
||||
|
@ -720,6 +720,7 @@ fn render_surface(
|
|||
renderer,
|
||||
frame,
|
||||
wl_surface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader,
|
||||
(ptr_x, ptr_y),
|
||||
*compositor_token,
|
||||
|
@ -744,6 +745,7 @@ fn render_surface(
|
|||
renderer,
|
||||
frame,
|
||||
wl_surface,
|
||||
#[cfg(feature = "egl")]
|
||||
egl_buffer_reader,
|
||||
(ptr_x, ptr_y),
|
||||
*compositor_token,
|
||||
|
|
|
@ -37,9 +37,6 @@ pub fn run_winit(
|
|||
|
||||
#[cfg(feature = "egl")]
|
||||
let reader = renderer.borrow().bind_wl_display(&display.borrow()).ok();
|
||||
#[cfg(not(feature = "egl"))]
|
||||
let reader = None;
|
||||
|
||||
#[cfg(feature = "egl")]
|
||||
if reader.is_some() {
|
||||
info!(log, "EGL hardware-acceleration enabled");
|
||||
|
@ -114,6 +111,7 @@ pub fn run_winit(
|
|||
draw_windows(
|
||||
renderer,
|
||||
frame,
|
||||
#[cfg(feature = "egl")]
|
||||
state.egl_reader.as_ref(),
|
||||
&*state.window_map.borrow(),
|
||||
None,
|
||||
|
@ -131,6 +129,7 @@ pub fn run_winit(
|
|||
renderer,
|
||||
frame,
|
||||
surface,
|
||||
#[cfg(feature = "egl")]
|
||||
state.egl_reader.as_ref(),
|
||||
(x as i32, y as i32),
|
||||
state.ctoken,
|
||||
|
@ -158,6 +157,7 @@ pub fn run_winit(
|
|||
renderer,
|
||||
frame,
|
||||
surface,
|
||||
#[cfg(feature = "egl")]
|
||||
state.egl_reader.as_ref(),
|
||||
(x as i32, y as i32),
|
||||
state.ctoken,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Implementation of the rendering traits using OpenGL ES 2
|
||||
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CStr;
|
||||
|
@ -32,12 +30,17 @@ use crate::backend::SwapBuffersError;
|
|||
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
use crate::{
|
||||
backend::egl::display::EGLBufferReader, utils::Rectangle, wayland::compositor::SurfaceAttributes,
|
||||
utils::Rectangle,
|
||||
wayland::compositor::SurfaceAttributes,
|
||||
};
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
use wayland_commons::user_data::UserDataMap;
|
||||
#[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))]
|
||||
use crate::backend::egl::display::EGLBufferReader;
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
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)]
|
||||
pub mod ffi {
|
||||
|
@ -221,10 +224,6 @@ pub enum Gles2Error {
|
|||
#[error("Error accessing the buffer ({0:?})")]
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
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
|
||||
#[error("Call begin before doing any rendering operations")]
|
||||
UnconstraintRenderingOperation,
|
||||
|
@ -243,7 +242,6 @@ impl From<Gles2Error> for SwapBuffersError {
|
|||
x @ Gles2Error::FramebufferBindingError
|
||||
| x @ Gles2Error::BindBufferEGLError(_)
|
||||
| x @ Gles2Error::UnsupportedPixelFormat(_)
|
||||
| x @ Gles2Error::UnknownBufferType
|
||||
| x @ Gles2Error::BufferAccessError(_)
|
||||
| x @ Gles2Error::EGLBufferAccessError(_) => SwapBuffersError::TemporaryFailure(Box::new(x)),
|
||||
}
|
||||
|
@ -500,9 +498,9 @@ impl Gles2Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
impl Gles2Renderer {
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
fn import_shm(
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
impl ImportShm for Gles2Renderer {
|
||||
fn import_shm_buffer(
|
||||
&mut self,
|
||||
buffer: &wl_buffer::WlBuffer,
|
||||
surface: Option<&SurfaceAttributes>,
|
||||
|
@ -613,7 +611,19 @@ impl Gles2Renderer {
|
|||
}
|
||||
|
||||
#[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,
|
||||
buffer: &wl_buffer::WlBuffer,
|
||||
reader: &EGLBufferReader,
|
||||
|
@ -654,8 +664,10 @@ impl Gles2Renderer {
|
|||
|
||||
Ok(texture)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
#[cfg(feature = "wayland_frontend")]
|
||||
impl Gles2Renderer {
|
||||
fn existing_dmabuf_texture(
|
||||
&self,
|
||||
buffer: &wl_buffer::WlBuffer,
|
||||
|
@ -880,16 +892,6 @@ impl Renderer for Gles2Renderer {
|
|||
type TextureId = Gles2Texture;
|
||||
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")]
|
||||
fn import_bitmap<C: std::ops::Deref<Target = [u8]>>(
|
||||
&mut self,
|
||||
|
@ -935,40 +937,6 @@ impl Renderer for Gles2Renderer {
|
|||
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>(
|
||||
&mut self,
|
||||
width: u32,
|
||||
|
|
|
@ -18,7 +18,7 @@ use wayland_server::protocol::{wl_buffer, wl_shm};
|
|||
|
||||
#[cfg(feature = "renderer_gl")]
|
||||
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;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
|
@ -216,39 +216,6 @@ pub trait Renderer {
|
|||
image: &image::ImageBuffer<image::Rgba<u8>, C>,
|
||||
) -> 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.
|
||||
///
|
||||
/// This function *may* error, if:
|
||||
|
@ -267,6 +234,102 @@ pub trait Renderer {
|
|||
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")]
|
||||
#[non_exhaustive]
|
||||
/// 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 `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> {
|
||||
use crate::backend::allocator::Buffer;
|
||||
|
||||
|
@ -343,7 +406,7 @@ pub fn buffer_dimensions(
|
|||
/// 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(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)> {
|
||||
use crate::backend::allocator::Buffer;
|
||||
|
||||
|
|
|
@ -233,13 +233,13 @@ pub enum WinitEvent {
|
|||
Refresh,
|
||||
}
|
||||
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
impl WinitGraphicsBackend {
|
||||
/// Bind a `wl_display` to allow hardware-accelerated clients using `wl_drm`.
|
||||
///
|
||||
/// 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.
|
||||
#[cfg(feature = "use_system_lib")]
|
||||
pub fn bind_wl_display(&self, wl_display: &Display) -> Result<EGLBufferReader, EGLError> {
|
||||
self.display.bind_wl_display(wl_display)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue