Skip to content

Commit

Permalink
renderer: Introduce explicit framebuffers
Browse files Browse the repository at this point in the history
  • Loading branch information
Drakulix committed Jan 14, 2025
1 parent a5fbc0e commit 66f198f
Show file tree
Hide file tree
Showing 40 changed files with 1,222 additions and 2,002 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ encoding_rs = { version = "0.8.33", optional = true }
profiling = "1.0.13"
smallvec = "1.11"
pixman = { version = "0.2.1", features = ["drm-fourcc", "sync"], optional = true }
aliasable = "0.1.3"


[dev-dependencies]
Expand Down
6 changes: 3 additions & 3 deletions anvil/src/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,14 @@ where
}

#[cfg(feature = "debug")]
impl<R> RenderElement<R> for FpsElement<<R as Renderer>::TextureId>
impl<R> RenderElement<R> for FpsElement<R::TextureId>
where
R: Renderer + ImportAll,
<R as Renderer>::TextureId: 'static,
R::TextureId: 'static,
{
fn draw(
&self,
frame: &mut <R as Renderer>::Frame<'_>,
frame: &mut R::Frame<'_, '_>,
_src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
Expand Down
5 changes: 3 additions & 2 deletions anvil/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ smithay::backend::renderer::element::render_elements! {
// a feature-dependent lifetime, which introduces a lot more feature bounds
// as the whole type changes and we can't have an unused lifetime (for when "debug" is disabled)
// in the declaration.
Fps=FpsElement<<R as Renderer>::TextureId>,
Fps=FpsElement<R::TextureId>,
}

impl<R: Renderer> std::fmt::Debug for CustomRenderElements<R> {
Expand Down Expand Up @@ -195,6 +195,7 @@ pub fn render_output<'a, 'd, R>(
space: &'a Space<WindowElement>,
custom_elements: impl IntoIterator<Item = CustomRenderElements<R>>,
renderer: &'a mut R,
framebuffer: &'a mut R::Framebuffer<'_>,
damage_tracker: &'d mut OutputDamageTracker,
age: usize,
show_window_preview: bool,
Expand All @@ -205,5 +206,5 @@ where
{
let (elements, clear_color) =
output_elements(output, space, custom_elements, renderer, show_window_preview);
damage_tracker.render_output(renderer, age, &elements, clear_color)
damage_tracker.render_output(renderer, framebuffer, age, &elements, clear_color)
}
2 changes: 1 addition & 1 deletion anvil/src/shell/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ impl<R: Renderer> std::fmt::Debug for WindowRenderElement<R> {
impl<R> AsRenderElements<R> for WindowElement
where
R: Renderer + ImportAll + ImportMem,
<R as Renderer>::TextureId: Clone + Texture + 'static,
R::TextureId: Clone + Texture + 'static,
{
type RenderElement = WindowRenderElement<R>;

Expand Down
2 changes: 1 addition & 1 deletion anvil/src/udev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ impl AnvilState<UdevData> {
!has_rendered
}
Err(err) => {
warn!("Error during rendering: {:?}", err);
warn!("Error during rendering: {:#?}", err);
match err {
SwapBuffersError::AlreadySwapped => false,
SwapBuffersError::TemporaryFailure(err) => match err.downcast_ref::<DrmError>() {
Expand Down
49 changes: 25 additions & 24 deletions anvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,31 +291,29 @@ pub fn run_winit() {

#[cfg(feature = "debug")]
let mut renderdoc = state.renderdoc.as_mut();
let render_res = backend.bind().and_then(|_| {

let age = if *full_redraw > 0 {
0
} else {
backend.buffer_age().unwrap_or(0)
};
#[cfg(feature = "debug")]
let window_handle = backend
.window()
.window_handle()
.map(|handle| {
if let RawWindowHandle::Wayland(handle) = handle.as_raw() {
handle.surface.as_ptr()
} else {
std::ptr::null_mut()
}
})
.unwrap_or_else(|_| std::ptr::null_mut());
let render_res = backend.bind().and_then(|(renderer, mut fb)| {
#[cfg(feature = "debug")]
if let Some(renderdoc) = renderdoc.as_mut() {
renderdoc.start_frame_capture(
backend.renderer().egl_context().get_context_handle(),
backend
.window()
.window_handle()
.map(|handle| {
if let RawWindowHandle::Wayland(handle) = handle.as_raw() {
handle.surface.as_ptr()
} else {
std::ptr::null_mut()
}
})
.unwrap_or_else(|_| std::ptr::null_mut()),
);
renderdoc.start_frame_capture(renderer.egl_context().get_context_handle(), window_handle);
}
let age = if *full_redraw > 0 {
0
} else {
backend.buffer_age().unwrap_or(0)
};

let renderer = backend.renderer();

let mut elements = Vec::<CustomRenderElements<GlesRenderer>>::new();

Expand Down Expand Up @@ -349,19 +347,22 @@ pub fn run_winit() {
#[cfg(feature = "debug")]
elements.push(CustomRenderElements::Fps(fps_element.clone()));

render_output(
let res = render_output(
&output,
space,
elements,
renderer,
&mut fb,
damage_tracker,
age,
show_window_preview,
)
.map_err(|err| match err {
OutputDamageTrackerError::Rendering(err) => err.into(),
_ => unreachable!(),
})
});

res
});

match render_res {
Expand Down
16 changes: 10 additions & 6 deletions anvil/src/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,12 +314,15 @@ pub fn run_x11() {
#[cfg(feature = "debug")]
fps_element.update_fps(fps);

let (buffer, age) = backend_data.surface.buffer().expect("gbm device was destroyed");
if let Err(err) = backend_data.renderer.bind(buffer) {
error!("Error while binding buffer: {}", err);
profiling::finish_frame!();
continue;
}
let (mut buffer, age) = backend_data.surface.buffer().expect("gbm device was destroyed");
let mut fb = match backend_data.renderer.bind(&mut buffer) {
Ok(fb) => fb,
Err(err) => {
error!("Error while binding buffer: {}", err);
profiling::finish_frame!();
continue;
}
};

#[cfg(feature = "debug")]
if let Some(renderdoc) = state.renderdoc.as_mut() {
Expand Down Expand Up @@ -394,6 +397,7 @@ pub fn run_x11() {
&state.space,
elements,
&mut backend_data.renderer,
&mut fb,
&mut backend_data.damage_tracker,
age.into(),
state.show_window_preview,
Expand Down
29 changes: 15 additions & 14 deletions examples/buffer_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ fn buffer_test(args: TestArgs) {
};

// 2. alloc buffer
let buffer = allocator
let mut buffer = allocator
.create_buffer(args.width, args.height, args.fourcc, &[args.modifier])
.expect("Failed to allocate buffer");

Expand All @@ -223,12 +223,7 @@ fn buffer_test(args: TestArgs) {
let context = EGLContext::new(&display).expect("Failed to create EGL context");
let mut renderer = unsafe { GlesRenderer::new(context).expect("Failed to init GL ES renderer") };

render_into(
&mut renderer,
buffer.clone(),
args.width as i32,
args.height as i32,
);
render_into(&mut renderer, &mut buffer, args.width as i32, args.height as i32);
}
}

Expand Down Expand Up @@ -274,15 +269,15 @@ fn buffer_test(args: TestArgs) {
}
}

fn render_into<R, T>(renderer: &mut R, buffer: T, w: i32, h: i32)
fn render_into<R, T>(renderer: &mut R, buffer: &mut T, w: i32, h: i32)
where
R: Renderer + Bind<T>,
{
// Bind it as a framebuffer
renderer.bind(buffer).expect("Failed to bind dmabuf");
let mut framebuffer = renderer.bind(buffer).expect("Failed to bind dmabuf");

let mut frame = renderer
.render((w, h).into(), Transform::Normal)
.render(&mut framebuffer, (w, h).into(), Transform::Normal)
.expect("Failed to create render frame");
frame
.clear(
Expand Down Expand Up @@ -322,11 +317,13 @@ where
let texture = renderer
.import_dmabuf(&buffer, None)
.expect("Failed to import dmabuf");
let offscreen = Offscreen::<T>::create_buffer(renderer, Fourcc::Abgr8888, (w, h).into())
let mut offscreen = Offscreen::<T>::create_buffer(renderer, Fourcc::Abgr8888, (w, h).into())
.expect("Failed to create offscreen buffer");
renderer.bind(offscreen).expect("Failed to bind offscreen buffer");
let mut framebuffer = renderer
.bind(&mut offscreen)
.expect("Failed to bind offscreen buffer");
let mut frame = renderer
.render((w, h).into(), Transform::Normal)
.render(&mut framebuffer, (w, h).into(), Transform::Normal)
.expect("Failed to create render frame");
frame
.render_texture_at(
Expand All @@ -348,7 +345,11 @@ where

if let Some(path) = dump {
let mapping = renderer
.copy_framebuffer(Rectangle::from_size((w, h).into()), Fourcc::Abgr8888)
.copy_framebuffer(
&framebuffer,
Rectangle::from_size((w, h).into()),
Fourcc::Abgr8888,
)
.expect("Failed to map framebuffer");
let copy = renderer.map_texture(&mapping).expect("Failed to read mapping");
image::save_buffer(path, copy, w as u32, h as u32, image::ColorType::Rgba8)
Expand Down
76 changes: 39 additions & 37 deletions examples/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,49 +205,51 @@ pub fn run_winit() -> Result<(), Box<dyn std::error::Error>> {
PumpStatus::Exit(_) => return Ok(()),
};

backend.bind().unwrap();

let size = backend.window_size();
let damage = Rectangle::from_size(size);
{
let (renderer, mut framebuffer) = backend.bind().unwrap();
let elements = state
.xdg_shell_state
.toplevel_surfaces()
.iter()
.flat_map(|surface| {
render_elements_from_surface_tree(
renderer,
surface.wl_surface(),
(0, 0),
1.0,
1.0,
Kind::Unspecified,
)
})
.collect::<Vec<WaylandSurfaceRenderElement<GlesRenderer>>>();

let mut frame = renderer
.render(&mut framebuffer, size, Transform::Flipped180)
.unwrap();
frame.clear(Color32F::new(0.1, 0.0, 0.0, 1.0), &[damage]).unwrap();
draw_render_elements(&mut frame, 1.0, &elements, &[damage]).unwrap();
// We rely on the nested compositor to do the sync for us
let _ = frame.finish().unwrap();

let elements = state
.xdg_shell_state
.toplevel_surfaces()
.iter()
.flat_map(|surface| {
render_elements_from_surface_tree(
backend.renderer(),
surface.wl_surface(),
(0, 0),
1.0,
1.0,
Kind::Unspecified,
)
})
.collect::<Vec<WaylandSurfaceRenderElement<GlesRenderer>>>();

let mut frame = backend.renderer().render(size, Transform::Flipped180).unwrap();
frame.clear(Color32F::new(0.1, 0.0, 0.0, 1.0), &[damage]).unwrap();
draw_render_elements(&mut frame, 1.0, &elements, &[damage]).unwrap();
// We rely on the nested compositor to do the sync for us
let _ = frame.finish().unwrap();

for surface in state.xdg_shell_state.toplevel_surfaces() {
send_frames_surface_tree(surface.wl_surface(), start_time.elapsed().as_millis() as u32);
}
for surface in state.xdg_shell_state.toplevel_surfaces() {
send_frames_surface_tree(surface.wl_surface(), start_time.elapsed().as_millis() as u32);
}

if let Some(stream) = listener.accept()? {
println!("Got a client: {:?}", stream);
if let Some(stream) = listener.accept()? {
println!("Got a client: {:?}", stream);

let client = display
.handle()
.insert_client(stream, Arc::new(ClientState::default()))
.unwrap();
clients.push(client);
}
let client = display
.handle()
.insert_client(stream, Arc::new(ClientState::default()))
.unwrap();
clients.push(client);
}

display.dispatch_clients(&mut state)?;
display.flush_clients()?;
display.dispatch_clients(&mut state)?;
display.flush_clients()?;
}

// It is important that all events on the display have been dispatched and flushed to clients before
// swapping buffers because this operation may block.
Expand Down
32 changes: 20 additions & 12 deletions smallvil/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,26 @@ pub fn init_winit(
let size = backend.window_size();
let damage = Rectangle::from_size(size);

backend.bind().unwrap();
smithay::desktop::space::render_output::<_, WaylandSurfaceRenderElement<GlesRenderer>, _, _>(
&output,
backend.renderer(),
1.0,
0,
[&state.space],
&[],
&mut damage_tracker,
[0.1, 0.1, 0.1, 1.0],
)
.unwrap();
{
let (renderer, mut framebuffer) = backend.bind().unwrap();
smithay::desktop::space::render_output::<
_,
WaylandSurfaceRenderElement<GlesRenderer>,
_,
_,
>(
&output,
renderer,
&mut framebuffer,
1.0,
0,
[&state.space],
&[],
&mut damage_tracker,
[0.1, 0.1, 0.1, 1.0],
)
.unwrap();
}
backend.submit(Some(&[damage])).unwrap();

state.space.elements().for_each(|window| {
Expand Down
Loading

0 comments on commit 66f198f

Please sign in to comment.