feat: render layer shell surfaces
This commit is contained in:
1 parent
535a217c1c
commit
41e493728c
2 files changed
+105
-2
No files matched your search
@@ -13,7 +13,7 @@ use smithay::{
|
|||||||
session::{Event as SessionEvent, Session, libseat::LibSeatSession},
|
session::{Event as SessionEvent, Session, libseat::LibSeatSession},
|
||||||
udev::{UdevBackend, UdevEvent, primary_gpu},
|
udev::{UdevBackend, UdevEvent, primary_gpu},
|
||||||
},
|
},
|
||||||
desktop::utils::OutputPresentationFeedback,
|
desktop::{layer_map_for_output, utils::OutputPresentationFeedback},
|
||||||
output::{Mode as OutputMode, Output, PhysicalProperties, Scale, Subpixel},
|
output::{Mode as OutputMode, Output, PhysicalProperties, Scale, Subpixel},
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::EventLoop,
|
calloop::EventLoop,
|
||||||
@@ -321,6 +321,17 @@ fn render_device(state: &mut Ferese, node: DrmNode) {
|
|||||||
|_, _| Kind::Vsync | Kind::HwClock | Kind::HwCompletion,
|
|_, _| Kind::Vsync | Kind::HwClock | Kind::HwCompletion,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
let layers = layer_map_for_output(&device.output)
|
||||||
|
.layers()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
layers.iter().for_each(|layer| {
|
||||||
|
layer.take_presentation_feedback(
|
||||||
|
&mut presentation,
|
||||||
|
|_, _| Some(device.output.clone()),
|
||||||
|
|_, _| Kind::Vsync | Kind::HwClock | Kind::HwCompletion,
|
||||||
|
);
|
||||||
|
});
|
||||||
device
|
device
|
||||||
.surface
|
.surface
|
||||||
.queue_buffer(Some(result.sync), Some(damage), presentation)?;
|
.queue_buffer(Some(result.sync), Some(damage), presentation)?;
|
||||||
@@ -380,9 +391,22 @@ fn send_frame_callbacks(state: &mut Ferese) {
|
|||||||
|_, _| Some(output.clone()),
|
|_, _| Some(output.clone()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
let layers = layer_map_for_output(&output)
|
||||||
|
.layers()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
layers.iter().for_each(|layer| {
|
||||||
|
layer.send_frame(
|
||||||
|
&output,
|
||||||
|
state.start_time.elapsed(),
|
||||||
|
Some(Duration::ZERO),
|
||||||
|
|_, _| Some(output.clone()),
|
||||||
|
);
|
||||||
|
});
|
||||||
state.send_cursor_frame(&output);
|
state.send_cursor_frame(&output);
|
||||||
state.space.refresh();
|
state.space.refresh();
|
||||||
state.popups.cleanup();
|
state.popups.cleanup();
|
||||||
|
layer_map_for_output(&output).cleanup();
|
||||||
if let Err(error) = state.display_handle.flush_clients() {
|
if let Err(error) = state.display_handle.flush_clients() {
|
||||||
tracing::debug!(%error, "failed to flush clients after DRM frame");
|
tracing::debug!(%error, "failed to flush clients after DRM frame");
|
||||||
}
|
}
|
||||||
|
|||||||
+80
-1
@@ -8,7 +8,7 @@ use smithay::{
|
|||||||
renderer::{
|
renderer::{
|
||||||
damage::OutputDamageTracker,
|
damage::OutputDamageTracker,
|
||||||
element::{
|
element::{
|
||||||
Kind as RenderElementKind,
|
AsRenderElements, Kind as RenderElementKind,
|
||||||
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
|
surface::{WaylandSurfaceRenderElement, render_elements_from_surface_tree},
|
||||||
utils::{
|
utils::{
|
||||||
ConstrainAlign, ConstrainScaleBehavior, CropRenderElement, Relocate,
|
ConstrainAlign, ConstrainScaleBehavior, CropRenderElement, Relocate,
|
||||||
@@ -20,6 +20,7 @@ use smithay::{
|
|||||||
winit::{self, WinitEvent},
|
winit::{self, WinitEvent},
|
||||||
},
|
},
|
||||||
desktop::{
|
desktop::{
|
||||||
|
LayerSurface, layer_map_for_output,
|
||||||
space::{ConstrainBehavior, ConstrainReference, constrain_space_element},
|
space::{ConstrainBehavior, ConstrainReference, constrain_space_element},
|
||||||
utils::OutputPresentationFeedback,
|
utils::OutputPresentationFeedback,
|
||||||
},
|
},
|
||||||
@@ -28,6 +29,7 @@ use smithay::{
|
|||||||
reexports::calloop::EventLoop,
|
reexports::calloop::EventLoop,
|
||||||
reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback::Kind as PresentationKind,
|
reexports::wayland_protocols::wp::presentation_time::server::wp_presentation_feedback::Kind as PresentationKind,
|
||||||
utils::{Clock, Logical, Monotonic, Physical, Point, Rectangle, Transform},
|
utils::{Clock, Logical, Monotonic, Physical, Point, Rectangle, Transform},
|
||||||
|
wayland::shell::wlr_layer::Layer,
|
||||||
wayland::{compositor::with_states, presentation::Refresh},
|
wayland::{compositor::with_states, presentation::Refresh},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,6 +105,13 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
|_, _| PresentationKind::Vsync,
|
|_, _| PresentationKind::Vsync,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
layer_surfaces(&output).iter().for_each(|layer| {
|
||||||
|
layer.take_presentation_feedback(
|
||||||
|
&mut presentation,
|
||||||
|
|_, _| Some(output.clone()),
|
||||||
|
|_, _| PresentationKind::Vsync,
|
||||||
|
);
|
||||||
|
});
|
||||||
let rendered = (|| -> Result<(), Box<dyn Error>> {
|
let rendered = (|| -> Result<(), Box<dyn Error>> {
|
||||||
{
|
{
|
||||||
let (renderer, mut framebuffer) = backend.bind()?;
|
let (renderer, mut framebuffer) = backend.bind()?;
|
||||||
@@ -138,9 +147,18 @@ pub fn init(event_loop: &mut EventLoop<Ferese>, state: &mut Ferese) -> Result<()
|
|||||||
|_, _| Some(output.clone()),
|
|_, _| Some(output.clone()),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
layer_surfaces(&output).iter().for_each(|layer| {
|
||||||
|
layer.send_frame(
|
||||||
|
&output,
|
||||||
|
state.start_time.elapsed(),
|
||||||
|
Some(Duration::ZERO),
|
||||||
|
|_, _| Some(output.clone()),
|
||||||
|
);
|
||||||
|
});
|
||||||
state.send_cursor_frame(&output);
|
state.send_cursor_frame(&output);
|
||||||
state.space.refresh();
|
state.space.refresh();
|
||||||
state.popups.cleanup();
|
state.popups.cleanup();
|
||||||
|
layer_map_for_output(&output).cleanup();
|
||||||
if let Err(error) = state.display_handle.flush_clients() {
|
if let Err(error) = state.display_handle.flush_clients() {
|
||||||
tracing::debug!(%error, "failed to flush clients");
|
tracing::debug!(%error, "failed to flush clients");
|
||||||
}
|
}
|
||||||
@@ -163,6 +181,11 @@ pub(crate) fn animated_window_elements(
|
|||||||
let scale = output.current_scale().fractional_scale();
|
let scale = output.current_scale().fractional_scale();
|
||||||
|
|
||||||
let mut elements = cursor_elements(state, renderer, output_geometry, scale);
|
let mut elements = cursor_elements(state, renderer, output_geometry, scale);
|
||||||
|
elements.extend(layer_elements(
|
||||||
|
renderer,
|
||||||
|
output,
|
||||||
|
&[Layer::Overlay, Layer::Top],
|
||||||
|
));
|
||||||
elements.extend(
|
elements.extend(
|
||||||
state
|
state
|
||||||
.space
|
.space
|
||||||
@@ -204,9 +227,65 @@ pub(crate) fn animated_window_elements(
|
|||||||
})
|
})
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
);
|
||||||
|
elements.extend(layer_elements(
|
||||||
|
renderer,
|
||||||
|
output,
|
||||||
|
&[Layer::Bottom, Layer::Background],
|
||||||
|
));
|
||||||
elements
|
elements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn layer_surfaces(output: &Output) -> Vec<LayerSurface> {
|
||||||
|
layer_map_for_output(output).layers().cloned().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layer_elements(
|
||||||
|
renderer: &mut GlesRenderer,
|
||||||
|
output: &Output,
|
||||||
|
requested_layers: &[Layer],
|
||||||
|
) -> Vec<AnimatedWindowRenderElement> {
|
||||||
|
let scale = output.current_scale().fractional_scale();
|
||||||
|
let Some(mode) = output.current_mode() else {
|
||||||
|
return Vec::new();
|
||||||
|
};
|
||||||
|
let output_crop = Rectangle::<i32, Physical>::from_size(mode.size);
|
||||||
|
let layers = {
|
||||||
|
let map = layer_map_for_output(output);
|
||||||
|
|
||||||
|
requested_layers
|
||||||
|
.iter()
|
||||||
|
.flat_map(|requested| {
|
||||||
|
map.layers_on(*requested).rev().filter_map(|layer| {
|
||||||
|
map.layer_geometry(layer)
|
||||||
|
.map(|geometry| (geometry.loc, layer.clone()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
layers
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(location, layer)| {
|
||||||
|
AsRenderElements::<GlesRenderer>::render_elements::<
|
||||||
|
WaylandSurfaceRenderElement<GlesRenderer>,
|
||||||
|
>(
|
||||||
|
&layer,
|
||||||
|
renderer,
|
||||||
|
location.to_physical_precise_round(scale),
|
||||||
|
scale.into(),
|
||||||
|
1.0,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.filter_map(|element| {
|
||||||
|
let origin = Point::<i32, Physical>::default();
|
||||||
|
let element = RescaleRenderElement::from_element(element, origin, 1.0);
|
||||||
|
let element = RelocateRenderElement::from_element(element, origin, Relocate::Relative);
|
||||||
|
|
||||||
|
CropRenderElement::from_element(element, scale, output_crop)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn cursor_elements(
|
fn cursor_elements(
|
||||||
state: &Ferese,
|
state: &Ferese,
|
||||||
renderer: &mut GlesRenderer,
|
renderer: &mut GlesRenderer,
|
||||||
|
|||||||
Reference in new issue
Block a user