element/surface: Avoid scanning out translucent surfaces
This commit is contained in:
parent
7ee78d9c13
commit
603c90b103
1 changed files with 45 additions and 7 deletions
|
|
@ -4,7 +4,10 @@ use crate::{
|
|||
wayland::{SurfaceRenderElement, push_render_elements_from_surface_tree},
|
||||
},
|
||||
shell::focus::target::PointerFocusTarget,
|
||||
wayland::handlers::{compositor::frame_time_filter_fn, corner_radius::surface_corners},
|
||||
wayland::handlers::{
|
||||
background_effect::ComputedBlurRegionCachedState, compositor::frame_time_filter_fn,
|
||||
corner_radius::surface_corners,
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
|
@ -19,7 +22,7 @@ use smithay::{
|
|||
backend::{
|
||||
drm::DrmNode,
|
||||
renderer::{
|
||||
ImportAll, Renderer,
|
||||
ImportAll, Renderer, buffer_has_alpha,
|
||||
element::{Kind, RenderElementStates, surface::KindEvaluation},
|
||||
utils::RendererSurfaceStateUserData,
|
||||
},
|
||||
|
|
@ -48,6 +51,7 @@ use smithay::{
|
|||
IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, user_data::UserDataMap,
|
||||
},
|
||||
wayland::{
|
||||
alpha_modifier::AlphaModifierSurfaceCachedState,
|
||||
compositor::{
|
||||
SubsurfaceCachedState, SurfaceData, TraversalAction, get_parent, with_states,
|
||||
with_surface_tree_downward,
|
||||
|
|
@ -81,6 +85,39 @@ fn buffer_node(data: &SurfaceData) -> Option<DrmNode> {
|
|||
.and_then(|dmabuf| dmabuf.node())
|
||||
}
|
||||
|
||||
fn is_likely_translucent(alpha: f32, data: &SurfaceData) -> bool {
|
||||
if alpha < 1.0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut alpha_modifier_state = data.cached_state.get::<AlphaModifierSurfaceCachedState>();
|
||||
let alpha_multiplier = alpha_modifier_state
|
||||
.current()
|
||||
.multiplier_f32()
|
||||
.unwrap_or(1.0);
|
||||
if alpha_multiplier < 1.0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
let Some(surface_state) = data.data_map.get::<RendererSurfaceStateUserData>() else {
|
||||
return false;
|
||||
};
|
||||
let surface_state = surface_state.lock().unwrap();
|
||||
if surface_state
|
||||
.buffer()
|
||||
.is_none_or(|buffer| !buffer_has_alpha(buffer).unwrap_or(true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut blur_state = data.cached_state.get::<ComputedBlurRegionCachedState>();
|
||||
blur_state
|
||||
.current()
|
||||
.blur_region
|
||||
.as_ref()
|
||||
.is_none_or(|region| region.is_empty())
|
||||
}
|
||||
|
||||
/// Build the [`KindEvaluation`] for a window's surface tree.
|
||||
///
|
||||
/// `scanout_node`, when set, is the scan-out target [`DrmNode`] of the output currently being
|
||||
|
|
@ -89,6 +126,7 @@ fn buffer_node(data: &SurfaceData) -> Option<DrmNode> {
|
|||
fn scanout_kind_eval(
|
||||
scanout_override: Option<bool>,
|
||||
scanout_node: Option<DrmNode>,
|
||||
alpha: f32,
|
||||
) -> KindEvaluation {
|
||||
match (scanout_override, scanout_node) {
|
||||
// Forced off.
|
||||
|
|
@ -98,14 +136,14 @@ fn scanout_kind_eval(
|
|||
(None, None) => FRAME_TIME_FILTER,
|
||||
// Node restriction in effect: only buffers on the scan-out node may be candidates.
|
||||
(Some(true), Some(node)) => KindEvaluation::Closure(Box::new(move |data| {
|
||||
if buffer_node(data) == Some(node) {
|
||||
if buffer_node(data) == Some(node) && !is_likely_translucent(alpha, data) {
|
||||
Kind::ScanoutCandidate
|
||||
} else {
|
||||
Kind::Unspecified
|
||||
}
|
||||
})),
|
||||
(None, Some(node)) => KindEvaluation::Closure(Box::new(move |data| {
|
||||
if buffer_node(data) == Some(node) {
|
||||
if buffer_node(data) == Some(node) && !is_likely_translucent(alpha, data) {
|
||||
frame_time_filter_fn(data)
|
||||
} else {
|
||||
Kind::Unspecified
|
||||
|
|
@ -879,7 +917,7 @@ impl CosmicSurface {
|
|||
radii,
|
||||
None,
|
||||
blur_strength,
|
||||
scanout_kind_eval(None, scanout_node),
|
||||
scanout_kind_eval(None, scanout_node, alpha),
|
||||
push,
|
||||
None,
|
||||
)
|
||||
|
|
@ -924,7 +962,7 @@ impl CosmicSurface {
|
|||
radii,
|
||||
None,
|
||||
blur_strength,
|
||||
scanout_kind_eval(scanout_override, scanout_node),
|
||||
scanout_kind_eval(scanout_override, scanout_node, alpha),
|
||||
push_above,
|
||||
push_below,
|
||||
)
|
||||
|
|
@ -945,7 +983,7 @@ impl CosmicSurface {
|
|||
radii,
|
||||
None,
|
||||
blur_strength,
|
||||
scanout_kind_eval(scanout_override, scanout_node),
|
||||
scanout_kind_eval(scanout_override, scanout_node, alpha),
|
||||
push_above,
|
||||
push_below,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue