Skip to content

Commit

Permalink
Merge pull request #503 from Smithay/feature/multigpu
Browse files Browse the repository at this point in the history
Introduce MultiGPU renderer
  • Loading branch information
Drakulix authored Mar 14, 2022
2 parents 6260e46 + 2e0ae16 commit 1151eea
Show file tree
Hide file tree
Showing 41 changed files with 4,265 additions and 727 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ jobs:
- backend_x11
- desktop
- renderer_gl
- renderer_multi
- wayland_frontend
- xwayland
- default
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
- `EGLNativeSurface` implementations overriding `swap_buffers` now receive and additional `damage` attribute to be used with `eglSwapBuffersWithDamageEXT` if desired
- `EGLSurface::swap_buffers` now accepts an optional `damage` parameter
- `WinitGraphicsBackend` does no longer provide a `render`-method and exposes its `Renderer` directly instead including new functions `bind` and `submit` to handle swapping buffers.
- `ImportShm` was renamed to `ImportMem`
- `ImportMem` and `ImportDma` were split and do now have accompanying traits `ImportMemWl` and `ImportDmaWl` to import wayland buffers.

### Additions

Expand Down Expand Up @@ -71,6 +73,12 @@
- `backend::renderer` has a new `utils`-module that can take care of client buffer management for you.
- `EGLSurface::buffer_age` can be used to query the surface buffer age.
- `GbmBufferedSurface::reset_buffers` can now be used to reset underlying buffers.
- Added new `Offscreen` trait to create offscreen surfaces for `Renderer`s
- Added functions to `ImportMem` to upload bitmaps from memory
- Added `ExportDma` trait to export framebuffers and textures into dmabufs
- Added `ExportMem` trait to copy framebuffers and textures into memory
- Added `multigpu`-module to the renderer, which makes handling multi-gpu setups easier!
- Added `backend::renderer::utils::import_surface_tree` to be able to import buffers before rendering

#### Desktop

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ gl_generator = { version = "0.14", optional = true }
pkg-config = { version = "0.3.17", optional = true }

[features]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_winit", "desktop", "renderer_gl", "xwayland", "wayland_frontend", "slog-stdlog", "backend_x11"]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_logind", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_multi", "xwayland", "wayland_frontend", "slog-stdlog"]
backend_winit = ["winit", "wayland-server/dlopen", "backend_egl", "wayland-egl", "renderer_gl"]
backend_x11 = ["x11rb", "x11rb/dri3", "x11rb/xfixes", "x11rb/present", "x11rb_event_source", "backend_gbm", "backend_drm", "backend_egl"]
backend_drm = ["drm", "drm-ffi"]
Expand All @@ -75,6 +75,7 @@ backend_session_elogind = ["backend_session_logind"]
backend_session_libseat = ["backend_session", "libseat"]
desktop = ["indexmap", "wayland_frontend"]
renderer_gl = ["gl_generator", "backend_egl"]
renderer_multi = ["backend_drm"]
use_system_lib = ["wayland_frontend", "wayland-sys", "wayland-server/use_system_lib"]
wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols", "tempfile"]
x11rb_event_source = ["x11rb"]
Expand Down
2 changes: 1 addition & 1 deletion anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ gl_generator = "0.14"
default = [ "udev", "logind", "x11", "egl", "winit", "xwayland" ]
egl = [ "smithay/use_system_lib", "smithay/backend_egl" ]
winit = [ "smithay/backend_winit" ]
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm", "smithay/backend_gbm", "smithay/backend_egl", "smithay/backend_session", "input", "image", "smithay/renderer_gl", "xcursor" ]
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm", "smithay/backend_gbm", "smithay/backend_egl", "smithay/backend_session", "input", "image", "smithay/renderer_gl", "smithay/renderer_multi", "xcursor" ]
logind = [ "smithay/backend_session_logind" ]
elogind = ["logind", "smithay/backend_session_elogind" ]
libseat = ["smithay/backend_session_libseat" ]
Expand Down
107 changes: 28 additions & 79 deletions anvil/src/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@

use std::sync::Mutex;

#[cfg(feature = "image")]
use image::{ImageBuffer, Rgba};
use slog::Logger;
#[cfg(feature = "image")]
use smithay::backend::renderer::gles2::{Gles2Error, Gles2Renderer, Gles2Texture};
use smithay::{
backend::{
renderer::{Frame, ImportAll, Renderer, Texture},
SwapBuffersError,
},
backend::renderer::{Frame, ImportAll, Renderer, Texture},
desktop::space::{RenderElement, SpaceOutputTuple, SurfaceTree},
reexports::wayland_server::protocol::wl_surface,
utils::{Logical, Point, Rectangle, Size, Transform},
Expand All @@ -23,17 +16,19 @@ use smithay::{

pub static CLEAR_COLOR: [f32; 4] = [0.8, 0.8, 0.9, 1.0];

pub fn draw_cursor<R, F, E, T>(
smithay::custom_elements! {
pub CustomElem<R>;
SurfaceTree=SurfaceTree,
PointerElement=PointerElement::<<R as Renderer>::TextureId>,
#[cfg(feature = "debug")]
FpsElement=FpsElement::<<R as Renderer>::TextureId>,
}

pub fn draw_cursor(
surface: wl_surface::WlSurface,
location: impl Into<Point<i32, Logical>>,
log: &Logger,
) -> impl RenderElement<R, F, E, T>
where
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
F: Frame<Error = E, TextureId = T> + 'static,
E: std::error::Error + Into<SwapBuffersError> + 'static,
T: Texture + 'static,
{
) -> SurfaceTree {
let mut position = location.into();
let ret = with_states(&surface, |states| {
Some(
Expand All @@ -60,17 +55,11 @@ where
SurfaceTree { surface, position }
}

pub fn draw_dnd_icon<R, F, E, T>(
pub fn draw_dnd_icon(
surface: wl_surface::WlSurface,
location: impl Into<Point<i32, Logical>>,
log: &Logger,
) -> impl RenderElement<R, F, E, T>
where
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
F: Frame<Error = E, TextureId = T> + 'static,
E: std::error::Error + Into<SwapBuffersError> + 'static,
T: Texture + 'static,
{
) -> SurfaceTree {
if get_role(&surface) != Some("dnd_icon") {
warn!(
log,
Expand All @@ -90,22 +79,20 @@ pub struct PointerElement<T: Texture> {
}

impl<T: Texture> PointerElement<T> {
pub fn new(texture: T, relative_pointer_pos: Point<i32, Logical>) -> PointerElement<T> {
pub fn new(texture: T, pointer_pos: Point<i32, Logical>) -> PointerElement<T> {
let size = texture.size().to_logical(1, Transform::Normal);
PointerElement {
texture,
position: relative_pointer_pos,
position: pointer_pos,
size,
}
}
}

impl<R, F, E, T> RenderElement<R, F, E, T> for PointerElement<T>
impl<R> RenderElement<R> for PointerElement<<R as Renderer>::TextureId>
where
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
F: Frame<Error = E, TextureId = T> + 'static,
E: std::error::Error + Into<SwapBuffersError> + 'static,
T: Texture + 'static,
R: Renderer + ImportAll,
<R as Renderer>::TextureId: 'static,
{
fn id(&self) -> usize {
0
Expand All @@ -122,12 +109,12 @@ where
fn draw(
&self,
_renderer: &mut R,
frame: &mut F,
frame: &mut <R as Renderer>::Frame,
scale: f64,
location: Point<i32, Logical>,
damage: &[Rectangle<i32, Logical>],
_log: &Logger,
) -> Result<(), R::Error> {
) -> Result<(), <R as Renderer>::Error> {
frame.render_texture_at(
&self.texture,
location.to_f64().to_physical(scale).to_i32_round(),
Expand All @@ -154,12 +141,10 @@ pub struct FpsElement<T: Texture> {
}

#[cfg(feature = "debug")]
impl<R, F, E, T> RenderElement<R, F, E, T> for FpsElement<T>
impl<R> RenderElement<R> for FpsElement<<R as Renderer>::TextureId>
where
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
F: Frame<Error = E, TextureId = T> + 'static,
E: std::error::Error + Into<SwapBuffersError> + 'static,
T: Texture + 'static,
R: Renderer + ImportAll,
<R as Renderer>::TextureId: 'static,
{
fn id(&self) -> usize {
0
Expand All @@ -183,12 +168,12 @@ where
fn draw(
&self,
_renderer: &mut R,
frame: &mut F,
frame: &mut <R as Renderer>::Frame,
scale: f64,
location: Point<i32, Logical>,
damage: &[Rectangle<i32, Logical>],
_log: &Logger,
) -> Result<(), R::Error> {
) -> Result<(), <R as Renderer>::Error> {
let value_str = std::cmp::min(self.value, 999).to_string();
let location = location.to_f64().to_physical(scale);
let mut offset_x = location.x;
Expand Down Expand Up @@ -237,49 +222,13 @@ where
}

#[cfg(feature = "debug")]
pub fn draw_fps<R, F, E, T>(texture: &T, value: u32) -> impl RenderElement<R, F, E, T>
pub fn draw_fps<R>(texture: &<R as Renderer>::TextureId, value: u32) -> FpsElement<<R as Renderer>::TextureId>
where
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
F: Frame<Error = E, TextureId = T> + 'static,
E: std::error::Error + Into<SwapBuffersError> + 'static,
T: Texture + Clone + 'static,
R: Renderer + ImportAll,
<R as Renderer>::TextureId: Clone,
{
FpsElement {
value,
texture: texture.clone(),
}
}

#[cfg(feature = "image")]
pub fn import_bitmap<C: std::ops::Deref<Target = [u8]>>(
renderer: &mut Gles2Renderer,
image: &ImageBuffer<Rgba<u8>, C>,
) -> Result<Gles2Texture, Gles2Error> {
use smithay::backend::renderer::gles2::ffi;

renderer.with_context(|renderer, gl| unsafe {
let mut tex = 0;
gl.GenTextures(1, &mut tex);
gl.BindTexture(ffi::TEXTURE_2D, tex);
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_S, ffi::CLAMP_TO_EDGE as i32);
gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_WRAP_T, ffi::CLAMP_TO_EDGE as i32);
gl.TexImage2D(
ffi::TEXTURE_2D,
0,
ffi::RGBA as i32,
image.width() as i32,
image.height() as i32,
0,
ffi::RGBA,
ffi::UNSIGNED_BYTE as u32,
image.as_ptr() as *const _,
);
gl.BindTexture(ffi::TEXTURE_2D, 0);

Gles2Texture::from_raw(
renderer,
tex,
(image.width() as i32, image.height() as i32).into(),
)
})
}
11 changes: 5 additions & 6 deletions anvil/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,26 @@ use smithay::{
backend::renderer::{Frame, ImportAll, Renderer},
desktop::{
draw_window,
space::{DynamicRenderElements, RenderError, Space},
space::{RenderElement, RenderError, Space},
},
utils::{Logical, Rectangle},
wayland::output::Output,
};

use crate::{drawing::*, shell::FullscreenSurface};

pub fn render_output<R>(
pub fn render_output<R, E>(
output: &Output,
space: &mut Space,
renderer: &mut R,
age: usize,
elements: &[DynamicRenderElements<R>],
elements: &[E],
log: &slog::Logger,
) -> Result<Option<Vec<Rectangle<i32, Logical>>>, RenderError<R>>
where
R: Renderer + ImportAll + 'static,
R::Frame: 'static,
R: Renderer + ImportAll,
R::TextureId: 'static,
R::Error: 'static,
E: RenderElement<R>,
{
if let Some(window) = output
.user_data()
Expand Down
1 change: 1 addition & 0 deletions anvil/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ pub fn init_shell<BackendData: Backend + 'static>(
move |surface, mut ddata| {
on_commit_buffer_handler(&surface);
let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
anvil_state.backend_data.early_import(&surface);
let mut popups = anvil_state.popups.borrow_mut();
let space = anvil_state.space.as_ref();
space.borrow_mut().commit(&surface);
Expand Down
1 change: 1 addition & 0 deletions anvil/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,5 @@ impl<BackendData: Backend + 'static> AnvilState<BackendData> {
pub trait Backend {
fn seat_name(&self) -> String;
fn reset_buffers(&mut self, output: &Output);
fn early_import(&mut self, surface: &WlSurface);
}
Loading

0 comments on commit 1151eea

Please sign in to comment.