Fix screencopy transparency on udev

Using a hack to set the cursor to the primary plane. Also the code is still doodoo
This commit is contained in:
Ottatop 2024-04-01 22:01:46 -05:00
parent ed2135e8f5
commit 2dbc13d55d
4 changed files with 55 additions and 29 deletions

2
Cargo.lock generated
View file

@ -1355,7 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
dependencies = [
"cfg-if",
"windows-targets 0.52.4",
"windows-targets 0.48.5",
]
[[package]]

View file

@ -29,7 +29,7 @@ use smithay::{
libinput::{LibinputInputBackend, LibinputSessionInterface},
renderer::{
self, damage,
element::{texture::TextureBuffer, Element, RenderElement},
element::{self, texture::TextureBuffer, Element, RenderElement},
gles::{GlesRenderbuffer, GlesRenderer},
multigpu::{gbm::GbmGlesBackend, GpuManager, MultiRenderer, MultiTexture},
utils::CommitCounter,
@ -1298,12 +1298,8 @@ impl State {
udev.pointer_element.set_status(self.cursor_status.clone());
let pending_screencopy_without_cursor = output.with_state(|state| {
state
.screencopy
.as_ref()
.is_some_and(|sc| !sc.overlay_cursor())
});
let pending_screencopy_with_cursor =
output.with_state(|state| state.screencopy.as_ref().map(|sc| sc.overlay_cursor()));
let mut output_render_elements = Vec::new();
@ -1312,17 +1308,40 @@ impl State {
//
// This will cause the cursor to disappear for a frame if there is one though,
// but it shouldn't meaningfully affect anything.
if !pending_screencopy_without_cursor {
let pointer_render_elements = pointer_render_elements(
output,
&mut renderer,
&self.space,
pointer_location,
&mut self.cursor_status,
self.dnd_icon.as_ref(),
&udev.pointer_element,
);
output_render_elements.extend(pointer_render_elements);
match pending_screencopy_with_cursor {
Some(include_cursor) => {
if include_cursor {
// HACK: Doing `RenderFrameResult::blit_frame_result` with something on the
// | cursor plane causes the cursor to overwrite the pixels underneath it,
// | leading to a transparent hole under the cursor.
// | To circumvent that, we set the cursor to render on the primary plane instead.
udev.pointer_element
.set_element_kind(element::Kind::Unspecified);
let pointer_render_elements = pointer_render_elements(
output,
&mut renderer,
&self.space,
pointer_location,
&mut self.cursor_status,
self.dnd_icon.as_ref(),
&udev.pointer_element,
);
udev.pointer_element.set_element_kind(element::Kind::Cursor);
output_render_elements.extend(pointer_render_elements);
}
}
None => {
let pointer_render_elements = pointer_render_elements(
output,
&mut renderer,
&self.space,
pointer_location,
&mut self.cursor_status,
self.dnd_icon.as_ref(),
&udev.pointer_element,
);
output_render_elements.extend(pointer_render_elements);
}
}
output_render_elements.extend(crate::render::generate_render_elements(
@ -1345,6 +1364,9 @@ impl State {
}
// Compute damage
//
// Also, I'm pretty sure that `RenderFrameResult` used to give us the damage, didn't
// it? But it was removed in favor of the `is_empty` bool
let damage = match &render_frame_result.primary_element {
PrimaryPlaneElement::Swapchain(element) => {
@ -1375,11 +1397,13 @@ impl State {
let mut damage = damage.unwrap_or_else(|| {
vec![Rectangle::from_loc_and_size(
Point::from((0, 0)),
output.current_mode().unwrap().size,
output.current_mode().unwrap().size, // TODO: transform
)]
});
// The primary plane had no damage but something got rendered, so it must be the cursor
//
// We currently have overlay planes disabled, so we don't have to worry about that.
if damage.is_empty() && !render_frame_result.is_empty {
if let Some(cursor_elem) = render_frame_result.cursor_element {
damage.push(cursor_elem.geometry(smithay::utils::Scale::from(
@ -1388,8 +1412,6 @@ impl State {
}
}
// dbg!(&damage);
if let Some(mut screencopy) = output.with_state_mut(|state| state.screencopy.take()) {
'screencopy: {
assert!(screencopy.output() == output);

View file

@ -548,6 +548,9 @@ delegate_layer_shell!(State);
impl ScreencopyHandler for State {
fn frame(&mut self, frame: Screencopy) {
let output = frame.output().clone();
if !frame.with_damage() {
self.schedule_render(&output);
}
output.with_state_mut(|state| state.screencopy.replace(frame));
}
}

View file

@ -18,6 +18,7 @@ use smithay::{
pub struct PointerElement<T: Texture> {
texture: Option<TextureBuffer<T>>,
status: CursorImageStatus,
kind: element::Kind,
}
impl<T: Texture> Default for PointerElement<T> {
@ -25,6 +26,7 @@ impl<T: Texture> Default for PointerElement<T> {
Self {
texture: Default::default(),
status: CursorImageStatus::default_named(),
kind: element::Kind::Cursor,
}
}
}
@ -41,6 +43,10 @@ impl<T: Texture> PointerElement<T> {
pub fn set_texture(&mut self, texture: TextureBuffer<T>) {
self.texture = Some(texture);
}
pub fn set_element_kind(&mut self, kind: element::Kind) {
self.kind = kind;
}
}
render_elements! {
@ -74,7 +80,7 @@ where
None,
None,
None,
element::Kind::Cursor,
self.kind,
),
)
.into()]
@ -85,12 +91,7 @@ where
CursorImageStatus::Surface(surface) => {
let elements: Vec<PointerRenderElement<R>> =
surface::render_elements_from_surface_tree(
renderer,
surface,
location,
scale,
alpha,
element::Kind::Cursor,
renderer, surface, location, scale, alpha, self.kind,
);
elements.into_iter().map(C::from).collect()
}