mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-02-05 20:46:27 +01:00
Dedup render element generation code
This commit is contained in:
parent
d75e0dad22
commit
806e739ec2
3 changed files with 188 additions and 251 deletions
|
@ -10,7 +10,6 @@ use std::{
|
|||
ffi::OsString,
|
||||
os::fd::FromRawFd,
|
||||
path::Path,
|
||||
sync::Mutex,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
|
@ -31,10 +30,7 @@ use smithay::{
|
|||
libinput::{LibinputInputBackend, LibinputSessionInterface},
|
||||
renderer::{
|
||||
damage::{self, OutputDamageTracker},
|
||||
element::{
|
||||
self, surface::WaylandSurfaceRenderElement, texture::TextureBuffer,
|
||||
AsRenderElements, RenderElement, RenderElementStates,
|
||||
},
|
||||
element::{texture::TextureBuffer, RenderElement, RenderElementStates},
|
||||
gles::{GlesRenderer, GlesTexture},
|
||||
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
|
||||
sync::SyncPoint,
|
||||
|
@ -51,11 +47,10 @@ use smithay::{
|
|||
},
|
||||
delegate_dmabuf,
|
||||
desktop::{
|
||||
space::{self, SurfaceTree},
|
||||
utils::{send_frames_surface_tree, OutputPresentationFeedback},
|
||||
Space,
|
||||
},
|
||||
input::pointer::{CursorImageAttributes, CursorImageStatus},
|
||||
input::pointer::CursorImageStatus,
|
||||
output::{Output, PhysicalProperties, Subpixel},
|
||||
reexports::{
|
||||
ash::vk::ExtPhysicalDeviceDrmFn,
|
||||
|
@ -79,11 +74,8 @@ use smithay::{
|
|||
backend::GlobalId, protocol::wl_surface::WlSurface, Display, DisplayHandle,
|
||||
},
|
||||
},
|
||||
utils::{
|
||||
Clock, DeviceFd, IsAlive, Logical, Monotonic, Physical, Point, Rectangle, Scale, Transform,
|
||||
},
|
||||
utils::{Clock, DeviceFd, Logical, Monotonic, Physical, Point, Rectangle, Transform},
|
||||
wayland::{
|
||||
compositor,
|
||||
dmabuf::{
|
||||
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState,
|
||||
ImportError,
|
||||
|
@ -98,8 +90,8 @@ use smithay_drm_extras::{
|
|||
|
||||
use crate::{
|
||||
api::msg::{Args, OutgoingMsg},
|
||||
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
|
||||
state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback, WithState},
|
||||
render::{pointer::PointerElement, CustomRenderElements},
|
||||
state::{take_presentation_feedback, CalloopData, State, SurfaceDmabufFeedback},
|
||||
window::WindowElement,
|
||||
};
|
||||
|
||||
|
@ -1486,129 +1478,18 @@ fn render_surface<'a>(
|
|||
clock: &Clock<Monotonic>,
|
||||
focus_stack: &[WindowElement],
|
||||
) -> Result<bool, SwapBuffersError> {
|
||||
let output_geometry = space.output_geometry(output).unwrap();
|
||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||
|
||||
let mut custom_render_elements: Vec<CustomRenderElements<_>> = Vec::new();
|
||||
// draw input method surface if any
|
||||
let rectangle = input_method.coordinates();
|
||||
let position = Point::from((
|
||||
rectangle.loc.x + rectangle.size.w,
|
||||
rectangle.loc.y + rectangle.size.h,
|
||||
));
|
||||
input_method.with_surface(|surface| {
|
||||
custom_render_elements.extend(AsRenderElements::<UdevRenderer<'a, '_>>::render_elements(
|
||||
&SurfaceTree::from_surface(surface),
|
||||
renderer,
|
||||
position.to_physical_precise_round(scale),
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
});
|
||||
|
||||
if output_geometry.to_f64().contains(pointer_location) {
|
||||
let cursor_hotspot = if let CursorImageStatus::Surface(ref surface) = cursor_status {
|
||||
compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<CursorImageAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.hotspot
|
||||
})
|
||||
} else {
|
||||
(0, 0).into()
|
||||
};
|
||||
let cursor_pos = pointer_location - output_geometry.loc.to_f64() - cursor_hotspot.to_f64();
|
||||
let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round();
|
||||
|
||||
// set cursor
|
||||
pointer_element.set_texture(pointer_image.clone());
|
||||
|
||||
// draw the cursor as relevant
|
||||
{
|
||||
// reset the cursor if the surface is no longer alive
|
||||
let mut reset = false;
|
||||
if let CursorImageStatus::Surface(ref surface) = *cursor_status {
|
||||
reset = !surface.alive();
|
||||
}
|
||||
if reset {
|
||||
*cursor_status = CursorImageStatus::Default;
|
||||
}
|
||||
|
||||
pointer_element.set_status(cursor_status.clone());
|
||||
}
|
||||
|
||||
custom_render_elements.extend(pointer_element.render_elements(
|
||||
renderer,
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
|
||||
if let Some(dnd_icon) = dnd_icon {
|
||||
custom_render_elements.extend(AsRenderElements::render_elements(
|
||||
&smithay::desktop::space::SurfaceTree::from_surface(dnd_icon),
|
||||
renderer,
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let output_render_elements = {
|
||||
let top_fullscreen_window = focus_stack.iter().rev().find(|win| {
|
||||
win.with_state(|state| {
|
||||
state.status.is_fullscreen() && state.tags.iter().any(|tag| tag.active())
|
||||
})
|
||||
});
|
||||
|
||||
// If fullscreen windows exist, render only the topmost one
|
||||
// TODO: wait until the fullscreen window has committed, this will stop flickering
|
||||
if let Some(window) = top_fullscreen_window {
|
||||
let mut output_render_elements =
|
||||
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
|
||||
|
||||
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
|
||||
window.render_elements(renderer, (0, 0).into(), scale, 1.0);
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
|
||||
output_render_elements.extend(
|
||||
window_render_elements
|
||||
.into_iter()
|
||||
.map(|elem| OutputRenderElements::Window(element::Wrap::from(elem))),
|
||||
);
|
||||
|
||||
output_render_elements
|
||||
} else {
|
||||
// render everything
|
||||
let space_render_elements =
|
||||
space::space_render_elements(renderer, [space], output, 1.0)
|
||||
.expect("Failed to get render elements");
|
||||
|
||||
let mut output_render_elements =
|
||||
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements.extend(
|
||||
space_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements
|
||||
}
|
||||
};
|
||||
let output_render_elements = crate::render::generate_render_elements(
|
||||
renderer,
|
||||
space,
|
||||
output,
|
||||
input_method,
|
||||
pointer_location,
|
||||
pointer_element,
|
||||
Some(pointer_image),
|
||||
cursor_status,
|
||||
dnd_icon,
|
||||
focus_stack,
|
||||
);
|
||||
|
||||
let res = surface.compositor.render_frame::<_, _, GlesTexture>(
|
||||
renderer,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use std::{error::Error, ffi::OsString, sync::Mutex, time::Duration};
|
||||
use std::{error::Error, ffi::OsString, time::Duration};
|
||||
|
||||
use smithay::{
|
||||
backend::{
|
||||
|
@ -8,15 +8,14 @@ use smithay::{
|
|||
egl::EGLDevice,
|
||||
renderer::{
|
||||
damage::{self, OutputDamageTracker},
|
||||
element::{self, surface::WaylandSurfaceRenderElement, AsRenderElements},
|
||||
gles::{GlesRenderer, GlesTexture},
|
||||
ImportDma, ImportEgl, ImportMemWl,
|
||||
},
|
||||
winit::{WinitError, WinitEvent, WinitGraphicsBackend},
|
||||
},
|
||||
delegate_dmabuf,
|
||||
desktop::{layer_map_for_output, space, utils::send_frames_surface_tree},
|
||||
input::pointer::{CursorImageAttributes, CursorImageStatus},
|
||||
desktop::{layer_map_for_output, utils::send_frames_surface_tree},
|
||||
input::pointer::CursorImageStatus,
|
||||
output::{Output, Subpixel},
|
||||
reexports::{
|
||||
calloop::{
|
||||
|
@ -26,19 +25,19 @@ use smithay::{
|
|||
wayland_protocols::wp::presentation_time::server::wp_presentation_feedback,
|
||||
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
||||
},
|
||||
utils::{IsAlive, Scale, Transform},
|
||||
utils::{IsAlive, Transform},
|
||||
wayland::{
|
||||
compositor,
|
||||
dmabuf::{
|
||||
DmabufFeedback, DmabufFeedbackBuilder, DmabufGlobal, DmabufHandler, DmabufState,
|
||||
ImportError,
|
||||
},
|
||||
input_method::InputMethodSeat,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
|
||||
state::{take_presentation_feedback, CalloopData, State, WithState},
|
||||
render::pointer::PointerElement,
|
||||
state::{take_presentation_feedback, CalloopData, State},
|
||||
};
|
||||
|
||||
use super::Backend;
|
||||
|
@ -258,106 +257,18 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
let full_redraw = &mut state.backend_data.full_redraw;
|
||||
*full_redraw = full_redraw.saturating_sub(1);
|
||||
|
||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||
let cursor_hotspot =
|
||||
if let CursorImageStatus::Surface(ref surface) = state.cursor_status {
|
||||
compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<CursorImageAttributes>>()
|
||||
.expect("Mutex<CursorImageAttributes> wasn't in the data map")
|
||||
.lock()
|
||||
.expect("Failed to lock Mutex<CursorImageAttributes>")
|
||||
.hotspot
|
||||
})
|
||||
} else {
|
||||
(0, 0).into()
|
||||
};
|
||||
let cursor_pos = state.pointer_location - cursor_hotspot.to_f64();
|
||||
let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round::<i32>();
|
||||
|
||||
let mut custom_render_elements = Vec::<CustomRenderElements<GlesRenderer>>::new();
|
||||
|
||||
custom_render_elements.extend(pointer_element.render_elements(
|
||||
let output_render_elements = crate::render::generate_render_elements(
|
||||
state.backend_data.backend.renderer(),
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
|
||||
if let Some(dnd_icon) = state.dnd_icon.as_ref() {
|
||||
custom_render_elements.extend(AsRenderElements::<GlesRenderer>::render_elements(
|
||||
&smithay::desktop::space::SurfaceTree::from_surface(dnd_icon),
|
||||
state.backend_data.backend.renderer(),
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
}
|
||||
|
||||
let output_render_elements = {
|
||||
let renderer = state.backend_data.backend.renderer();
|
||||
|
||||
let top_fullscreen_window =
|
||||
state.focus_state.focus_stack.iter().rev().find(|win| {
|
||||
win.with_state(|state| {
|
||||
state.status.is_fullscreen()
|
||||
&& state.tags.iter().any(|tag| tag.active())
|
||||
})
|
||||
});
|
||||
|
||||
// If fullscreen windows exist, render only the topmost one
|
||||
// TODO: wait until the fullscreen window has committed, this will stop flickering
|
||||
if let Some(window) = top_fullscreen_window {
|
||||
let mut output_render_elements = Vec::<
|
||||
OutputRenderElements<
|
||||
GlesRenderer,
|
||||
WaylandSurfaceRenderElement<GlesRenderer>,
|
||||
>,
|
||||
>::new();
|
||||
|
||||
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
|
||||
window.render_elements(renderer, (0, 0).into(), scale, 1.0);
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
|
||||
output_render_elements.extend(
|
||||
window_render_elements
|
||||
.into_iter()
|
||||
.map(|elem| OutputRenderElements::Window(element::Wrap::from(elem))),
|
||||
);
|
||||
|
||||
output_render_elements
|
||||
} else {
|
||||
// render everything
|
||||
let space_render_elements =
|
||||
space::space_render_elements(renderer, [&state.space], &output, 1.0)
|
||||
.expect("Failed to get render elements");
|
||||
|
||||
let mut output_render_elements = Vec::<
|
||||
OutputRenderElements<
|
||||
GlesRenderer,
|
||||
WaylandSurfaceRenderElement<GlesRenderer>,
|
||||
>,
|
||||
>::new();
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements.extend(
|
||||
space_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements
|
||||
}
|
||||
};
|
||||
&state.space,
|
||||
&output,
|
||||
state.seat.input_method(),
|
||||
state.pointer_location,
|
||||
&mut pointer_element,
|
||||
None,
|
||||
&mut state.cursor_status,
|
||||
state.dnd_icon.as_ref(),
|
||||
&state.focus_state.focus_stack,
|
||||
);
|
||||
|
||||
let render_res = state.backend_data.backend.bind().and_then(|_| {
|
||||
let age = if *full_redraw > 0 {
|
||||
|
|
161
src/render.rs
161
src/render.rs
|
@ -1,16 +1,28 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use smithay::{
|
||||
backend::renderer::{
|
||||
element::{surface::WaylandSurfaceRenderElement, AsRenderElements, Wrap},
|
||||
element::{
|
||||
self, surface::WaylandSurfaceRenderElement, texture::TextureBuffer, AsRenderElements,
|
||||
Wrap,
|
||||
},
|
||||
ImportAll, ImportMem, Renderer, Texture,
|
||||
},
|
||||
desktop::space::SpaceRenderElements,
|
||||
desktop::{
|
||||
space::{self, SpaceRenderElements, SurfaceTree},
|
||||
Space,
|
||||
},
|
||||
input::pointer::{CursorImageAttributes, CursorImageStatus},
|
||||
output::Output,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
render_elements,
|
||||
utils::{Physical, Point, Scale},
|
||||
utils::{IsAlive, Logical, Physical, Point, Scale},
|
||||
wayland::{compositor, input_method::InputMethodHandle},
|
||||
};
|
||||
|
||||
use crate::window::WindowElement;
|
||||
use crate::{state::WithState, window::WindowElement};
|
||||
|
||||
use self::pointer::{PointerElement, PointerRenderElement};
|
||||
|
||||
|
@ -61,14 +73,147 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn render_elements<R, T>(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn generate_render_elements<R, T>(
|
||||
renderer: &mut R,
|
||||
space: &Space<WindowElement>,
|
||||
output: &Output,
|
||||
input_method: &InputMethodHandle,
|
||||
pointer_location: Point<f64, Logical>,
|
||||
pointer_element: &mut PointerElement<T>,
|
||||
pointer_image: Option<&TextureBuffer<T>>,
|
||||
cursor_status: &mut CursorImageStatus,
|
||||
dnd_icon: Option<&WlSurface>,
|
||||
focus_stack: &[WindowElement],
|
||||
) -> Vec<OutputRenderElements<R, WaylandSurfaceRenderElement<R>>>
|
||||
where
|
||||
R: Renderer + ImportAll,
|
||||
R: Renderer<TextureId = T> + ImportAll + ImportMem,
|
||||
<R as Renderer>::TextureId: 'static,
|
||||
T: Texture,
|
||||
T: Texture + Clone,
|
||||
{
|
||||
vec![]
|
||||
let output_geometry = space
|
||||
.output_geometry(output)
|
||||
.expect("called output_geometry on an unmapped output");
|
||||
let scale = Scale::from(output.current_scale().fractional_scale());
|
||||
|
||||
let mut custom_render_elements: Vec<CustomRenderElements<_>> = Vec::new();
|
||||
// draw input method surface if any
|
||||
let rectangle = input_method.coordinates();
|
||||
let position = Point::from((
|
||||
rectangle.loc.x + rectangle.size.w,
|
||||
rectangle.loc.y + rectangle.size.h,
|
||||
));
|
||||
input_method.with_surface(|surface| {
|
||||
custom_render_elements.extend(AsRenderElements::<R>::render_elements(
|
||||
&SurfaceTree::from_surface(surface),
|
||||
renderer,
|
||||
position.to_physical_precise_round(scale),
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
});
|
||||
|
||||
if output_geometry.to_f64().contains(pointer_location) {
|
||||
let cursor_hotspot = if let CursorImageStatus::Surface(ref surface) = cursor_status {
|
||||
compositor::with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<CursorImageAttributes>>()
|
||||
.expect("surface data map had no CursorImageAttributes")
|
||||
.lock()
|
||||
.expect("failed to lock mutex")
|
||||
.hotspot
|
||||
})
|
||||
} else {
|
||||
(0, 0).into()
|
||||
};
|
||||
let cursor_pos = pointer_location - output_geometry.loc.to_f64() - cursor_hotspot.to_f64();
|
||||
let cursor_pos_scaled = cursor_pos.to_physical(scale).to_i32_round();
|
||||
|
||||
// set cursor
|
||||
if let Some(pointer_image) = pointer_image {
|
||||
pointer_element.set_texture(pointer_image.clone());
|
||||
}
|
||||
|
||||
// draw the cursor as relevant and
|
||||
// reset the cursor if the surface is no longer alive
|
||||
if let CursorImageStatus::Surface(surface) = &*cursor_status {
|
||||
if !surface.alive() {
|
||||
*cursor_status = CursorImageStatus::Default;
|
||||
}
|
||||
}
|
||||
|
||||
pointer_element.set_status(cursor_status.clone());
|
||||
|
||||
custom_render_elements.extend(pointer_element.render_elements(
|
||||
renderer,
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
|
||||
if let Some(dnd_icon) = dnd_icon {
|
||||
custom_render_elements.extend(AsRenderElements::render_elements(
|
||||
&smithay::desktop::space::SurfaceTree::from_surface(dnd_icon),
|
||||
renderer,
|
||||
cursor_pos_scaled,
|
||||
scale,
|
||||
1.0,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let output_render_elements = {
|
||||
let top_fullscreen_window = focus_stack.iter().rev().find(|win| {
|
||||
win.with_state(|state| {
|
||||
state.status.is_fullscreen() && state.tags.iter().any(|tag| tag.active())
|
||||
})
|
||||
});
|
||||
|
||||
// If fullscreen windows exist, render only the topmost one
|
||||
// TODO: wait until the fullscreen window has committed, this will stop flickering
|
||||
if let Some(window) = top_fullscreen_window {
|
||||
let mut output_render_elements =
|
||||
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
|
||||
|
||||
let window_render_elements: Vec<WaylandSurfaceRenderElement<_>> =
|
||||
window.render_elements(renderer, (0, 0).into(), scale, 1.0);
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
|
||||
output_render_elements.extend(
|
||||
window_render_elements
|
||||
.into_iter()
|
||||
.map(|elem| OutputRenderElements::Window(element::Wrap::from(elem))),
|
||||
);
|
||||
|
||||
output_render_elements
|
||||
} else {
|
||||
// render everything
|
||||
let space_render_elements =
|
||||
space::space_render_elements(renderer, [space], output, 1.0)
|
||||
.expect("Failed to get render elements");
|
||||
|
||||
let mut output_render_elements =
|
||||
Vec::<OutputRenderElements<_, WaylandSurfaceRenderElement<_>>>::new();
|
||||
|
||||
output_render_elements.extend(
|
||||
custom_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements.extend(
|
||||
space_render_elements
|
||||
.into_iter()
|
||||
.map(OutputRenderElements::from),
|
||||
);
|
||||
output_render_elements
|
||||
}
|
||||
};
|
||||
|
||||
output_render_elements
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue