kms: Support screen filters
This commit is contained in:
parent
18335c6758
commit
7929e25966
5 changed files with 198 additions and 80 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::{output_elements, CursorMode, GlMultiRenderer, CLEAR_COLOR},
|
backend::render::{output_elements, CursorMode, GlMultiRenderer, CLEAR_COLOR},
|
||||||
config::{AdaptiveSync, OutputConfig, OutputState},
|
config::{AdaptiveSync, OutputConfig, OutputState, ScreenFilter},
|
||||||
shell::Shell,
|
shell::Shell,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::protocols::screencopy::Frame as ScreencopyFrame,
|
wayland::protocols::screencopy::Frame as ScreencopyFrame,
|
||||||
|
|
@ -272,6 +272,7 @@ impl State {
|
||||||
maybe_crtc,
|
maybe_crtc,
|
||||||
(w, 0),
|
(w, 0),
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
|
self.common.config.dynamic_conf.screen_filter().clone(),
|
||||||
self.common.shell.clone(),
|
self.common.shell.clone(),
|
||||||
self.common.startup_done.clone(),
|
self.common.startup_done.clone(),
|
||||||
) {
|
) {
|
||||||
|
|
@ -365,6 +366,7 @@ impl State {
|
||||||
maybe_crtc,
|
maybe_crtc,
|
||||||
(w, 0),
|
(w, 0),
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
|
self.common.config.dynamic_conf.screen_filter().clone(),
|
||||||
self.common.shell.clone(),
|
self.common.shell.clone(),
|
||||||
self.common.startup_done.clone(),
|
self.common.startup_done.clone(),
|
||||||
) {
|
) {
|
||||||
|
|
@ -516,6 +518,7 @@ impl Device {
|
||||||
maybe_crtc: Option<crtc::Handle>,
|
maybe_crtc: Option<crtc::Handle>,
|
||||||
position: (u32, u32),
|
position: (u32, u32),
|
||||||
evlh: &LoopHandle<'static, State>,
|
evlh: &LoopHandle<'static, State>,
|
||||||
|
screen_filter: ScreenFilter,
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
startup_done: Arc<AtomicBool>,
|
startup_done: Arc<AtomicBool>,
|
||||||
) -> Result<(Output, bool)> {
|
) -> Result<(Output, bool)> {
|
||||||
|
|
@ -579,6 +582,7 @@ impl Device {
|
||||||
self.dev_node,
|
self.dev_node,
|
||||||
self.render_node,
|
self.render_node,
|
||||||
evlh,
|
evlh,
|
||||||
|
screen_filter,
|
||||||
shell,
|
shell,
|
||||||
startup_done,
|
startup_done,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{AdaptiveSync, OutputState},
|
config::{AdaptiveSync, OutputState, ScreenFilter},
|
||||||
shell::Shell,
|
shell::Shell,
|
||||||
state::BackendData,
|
state::BackendData,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
|
|
@ -558,6 +558,7 @@ impl KmsState {
|
||||||
&mut self,
|
&mut self,
|
||||||
test_only: bool,
|
test_only: bool,
|
||||||
loop_handle: &LoopHandle<'static, State>,
|
loop_handle: &LoopHandle<'static, State>,
|
||||||
|
screen_filter: &ScreenFilter,
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
startup_done: Arc<AtomicBool>,
|
startup_done: Arc<AtomicBool>,
|
||||||
clock: &Clock<Monotonic>,
|
clock: &Clock<Monotonic>,
|
||||||
|
|
@ -658,6 +659,7 @@ impl KmsState {
|
||||||
Some(crtc),
|
Some(crtc),
|
||||||
(w, 0),
|
(w, 0),
|
||||||
loop_handle,
|
loop_handle,
|
||||||
|
screen_filter.clone(),
|
||||||
shell.clone(),
|
shell.clone(),
|
||||||
startup_done.clone(),
|
startup_done.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
@ -927,4 +929,19 @@ impl KmsState {
|
||||||
|
|
||||||
Ok(all_outputs)
|
Ok(all_outputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> Result<()> {
|
||||||
|
for device in self.drm_devices.values_mut() {
|
||||||
|
for surface in device.surfaces.values_mut() {
|
||||||
|
surface.set_screen_filter(screen_filter.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't expect this to fail in a meaningful way.
|
||||||
|
// The shader is already compiled at this point and we don't rely on any features,
|
||||||
|
// that might not be available for any filters we currently expose.
|
||||||
|
//
|
||||||
|
// But we might conditionally fail here in the future.
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
init_shaders, output_elements, CursorMode, GlMultiRenderer, PostprocessOutputConfig,
|
init_shaders, output_elements, CursorMode, GlMultiRenderer, PostprocessOutputConfig,
|
||||||
PostprocessShader, PostprocessState, CLEAR_COLOR,
|
PostprocessShader, PostprocessState, CLEAR_COLOR,
|
||||||
},
|
},
|
||||||
config::AdaptiveSync,
|
config::{AdaptiveSync, ScreenFilter},
|
||||||
shell::Shell,
|
shell::Shell,
|
||||||
state::SurfaceDmabufFeedback,
|
state::SurfaceDmabufFeedback,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
|
|
@ -40,12 +40,12 @@ use smithay::{
|
||||||
utils::{constrain_render_elements, ConstrainAlign, ConstrainScaleBehavior},
|
utils::{constrain_render_elements, ConstrainAlign, ConstrainScaleBehavior},
|
||||||
Element, Kind, RenderElementStates,
|
Element, Kind, RenderElementStates,
|
||||||
},
|
},
|
||||||
gles::{GlesRenderbuffer, GlesTexture},
|
gles::{element::TextureShaderElement, GlesRenderbuffer, GlesRenderer, Uniform},
|
||||||
glow::GlowRenderer,
|
glow::GlowRenderer,
|
||||||
multigpu::{Error as MultiError, GpuManager},
|
multigpu::{Error as MultiError, GpuManager},
|
||||||
sync::SyncPoint,
|
sync::SyncPoint,
|
||||||
utils::with_renderer_surface_state,
|
utils::with_renderer_surface_state,
|
||||||
Bind, ImportDma, Offscreen, Renderer, RendererSuper, Texture,
|
Bind, Blit, ImportDma, Offscreen, Renderer, RendererSuper, Texture, TextureFilter,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
desktop::utils::OutputPresentationFeedback,
|
desktop::utils::OutputPresentationFeedback,
|
||||||
|
|
@ -74,7 +74,7 @@ use smithay::{
|
||||||
use tracing::{error, trace, warn};
|
use tracing::{error, trace, warn};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::BorrowMut,
|
borrow::{Borrow, BorrowMut},
|
||||||
collections::{hash_map, HashMap, HashSet},
|
collections::{hash_map, HashMap, HashSet},
|
||||||
mem,
|
mem,
|
||||||
sync::{
|
sync::{
|
||||||
|
|
@ -129,6 +129,7 @@ pub struct SurfaceThreadState {
|
||||||
|
|
||||||
output: Output,
|
output: Output,
|
||||||
mirroring: Option<Output>,
|
mirroring: Option<Output>,
|
||||||
|
screen_filter: ScreenFilter,
|
||||||
postprocess_textures: HashMap<DrmNode, PostprocessState>,
|
postprocess_textures: HashMap<DrmNode, PostprocessState>,
|
||||||
|
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
|
|
@ -190,6 +191,7 @@ pub enum ThreadCommand {
|
||||||
node: DrmNode,
|
node: DrmNode,
|
||||||
},
|
},
|
||||||
UpdateMirroring(Option<Output>),
|
UpdateMirroring(Option<Output>),
|
||||||
|
UpdateScreenFilter(ScreenFilter),
|
||||||
VBlank(Option<DrmEventMetadata>),
|
VBlank(Option<DrmEventMetadata>),
|
||||||
ScheduleRender,
|
ScheduleRender,
|
||||||
AdaptiveSyncAvailable(SyncSender<Result<VrrSupport>>),
|
AdaptiveSyncAvailable(SyncSender<Result<VrrSupport>>),
|
||||||
|
|
@ -214,6 +216,7 @@ impl Surface {
|
||||||
dev_node: DrmNode,
|
dev_node: DrmNode,
|
||||||
target_node: DrmNode,
|
target_node: DrmNode,
|
||||||
evlh: &LoopHandle<'static, State>,
|
evlh: &LoopHandle<'static, State>,
|
||||||
|
screen_filter: ScreenFilter,
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
startup_done: Arc<AtomicBool>,
|
startup_done: Arc<AtomicBool>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
|
@ -233,6 +236,7 @@ impl Surface {
|
||||||
target_node,
|
target_node,
|
||||||
shell,
|
shell,
|
||||||
active_clone,
|
active_clone,
|
||||||
|
screen_filter,
|
||||||
tx2,
|
tx2,
|
||||||
rx,
|
rx,
|
||||||
startup_done,
|
startup_done,
|
||||||
|
|
@ -354,6 +358,12 @@ impl Surface {
|
||||||
.send(ThreadCommand::UpdateMirroring(output));
|
.send(ThreadCommand::UpdateMirroring(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_screen_filter(&mut self, config: ScreenFilter) {
|
||||||
|
let _ = self
|
||||||
|
.thread_command
|
||||||
|
.send(ThreadCommand::UpdateScreenFilter(config));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn adaptive_sync_support(&self) -> Result<VrrSupport> {
|
pub fn adaptive_sync_support(&self) -> Result<VrrSupport> {
|
||||||
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
let (tx, rx) = std::sync::mpsc::sync_channel(1);
|
||||||
let _ = self
|
let _ = self
|
||||||
|
|
@ -447,6 +457,7 @@ fn surface_thread(
|
||||||
target_node: DrmNode,
|
target_node: DrmNode,
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
active: Arc<AtomicBool>,
|
active: Arc<AtomicBool>,
|
||||||
|
screen_filter: ScreenFilter,
|
||||||
thread_sender: Sender<SurfaceCommand>,
|
thread_sender: Sender<SurfaceCommand>,
|
||||||
thread_receiver: Channel<ThreadCommand>,
|
thread_receiver: Channel<ThreadCommand>,
|
||||||
startup_done: Arc<AtomicBool>,
|
startup_done: Arc<AtomicBool>,
|
||||||
|
|
@ -490,6 +501,7 @@ fn surface_thread(
|
||||||
|
|
||||||
output,
|
output,
|
||||||
mirroring: None,
|
mirroring: None,
|
||||||
|
screen_filter,
|
||||||
postprocess_textures: HashMap::new(),
|
postprocess_textures: HashMap::new(),
|
||||||
|
|
||||||
shell,
|
shell,
|
||||||
|
|
@ -528,6 +540,9 @@ fn surface_thread(
|
||||||
Event::Msg(ThreadCommand::UpdateMirroring(mirroring_output)) => {
|
Event::Msg(ThreadCommand::UpdateMirroring(mirroring_output)) => {
|
||||||
state.update_mirroring(mirroring_output);
|
state.update_mirroring(mirroring_output);
|
||||||
}
|
}
|
||||||
|
Event::Msg(ThreadCommand::UpdateScreenFilter(filter_config)) => {
|
||||||
|
state.update_screen_filter(filter_config);
|
||||||
|
}
|
||||||
Event::Msg(ThreadCommand::AdaptiveSyncAvailable(result)) => {
|
Event::Msg(ThreadCommand::AdaptiveSyncAvailable(result)) => {
|
||||||
if let Some(compositor) = state.compositor.as_mut() {
|
if let Some(compositor) = state.compositor.as_mut() {
|
||||||
let _ = result.send(
|
let _ = result.send(
|
||||||
|
|
@ -989,11 +1004,15 @@ impl SurfaceThreadState {
|
||||||
let source_output = self
|
let source_output = self
|
||||||
.mirroring
|
.mirroring
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
.or((!self.screen_filter.is_noop()).then(|| &self.output))
|
||||||
.filter(|output| {
|
.filter(|output| {
|
||||||
PostprocessOutputConfig::for_output_untransformed(output)
|
PostprocessOutputConfig::for_output_untransformed(output)
|
||||||
!= PostprocessOutputConfig::for_output(&self.output)
|
!= PostprocessOutputConfig::for_output(&self.output)
|
||||||
|
|| !self.screen_filter.is_noop()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut pre_postprocess_states = None;
|
||||||
|
let mut pre_postprocess_texture = None;
|
||||||
let res = if let Some(source_output) = source_output {
|
let res = if let Some(source_output) = source_output {
|
||||||
let offscreen_output_config =
|
let offscreen_output_config =
|
||||||
PostprocessOutputConfig::for_output_untransformed(source_output);
|
PostprocessOutputConfig::for_output_untransformed(source_output);
|
||||||
|
|
@ -1023,6 +1042,10 @@ impl SurfaceThreadState {
|
||||||
.texture
|
.texture
|
||||||
.render()
|
.render()
|
||||||
.draw::<_, <GlMultiRenderer as RendererSuper>::Error>(|tex| {
|
.draw::<_, <GlMultiRenderer as RendererSuper>::Error>(|tex| {
|
||||||
|
if self.mirroring.is_none() {
|
||||||
|
pre_postprocess_texture = Some(tex.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let mut fb = renderer.bind(tex)?;
|
let mut fb = renderer.bind(tex)?;
|
||||||
let res = match postprocess_state.damage_tracker.render_output(
|
let res = match postprocess_state.damage_tracker.render_output(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
|
|
@ -1035,6 +1058,11 @@ impl SurfaceThreadState {
|
||||||
Err(RenderError::Rendering(err)) => return Err(err),
|
Err(RenderError::Rendering(err)) => return Err(err),
|
||||||
Err(RenderError::OutputNoMode(_)) => unreachable!(),
|
Err(RenderError::OutputNoMode(_)) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if self.mirroring.is_none() {
|
||||||
|
pre_postprocess_states = Some(res.states);
|
||||||
|
}
|
||||||
|
|
||||||
renderer.wait(&res.sync)?;
|
renderer.wait(&res.sync)?;
|
||||||
std::mem::drop(fb);
|
std::mem::drop(fb);
|
||||||
|
|
||||||
|
|
@ -1061,29 +1089,52 @@ impl SurfaceThreadState {
|
||||||
None,
|
None,
|
||||||
Kind::Unspecified,
|
Kind::Unspecified,
|
||||||
);
|
);
|
||||||
let texture_geometry =
|
|
||||||
texture_elem.geometry(self.output.current_scale().fractional_scale().into());
|
|
||||||
elements = constrain_render_elements(
|
|
||||||
std::iter::once(texture_elem),
|
|
||||||
(0, 0),
|
|
||||||
Rectangle::from_size(
|
|
||||||
self.output
|
|
||||||
.geometry()
|
|
||||||
.size
|
|
||||||
.as_logical()
|
|
||||||
.to_f64()
|
|
||||||
.to_physical(self.output.current_scale().fractional_scale())
|
|
||||||
.to_i32_round(),
|
|
||||||
),
|
|
||||||
texture_geometry,
|
|
||||||
ConstrainScaleBehavior::Fit,
|
|
||||||
ConstrainAlign::CENTER,
|
|
||||||
1.0,
|
|
||||||
)
|
|
||||||
.map(CosmicElement::Postprocess)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
renderer = self.api.single_renderer(&self.target_node).unwrap();
|
renderer = self.api.single_renderer(&self.target_node).unwrap();
|
||||||
|
|
||||||
|
let postprocess_texture_shader = Borrow::<GlesRenderer>::borrow(renderer.as_mut())
|
||||||
|
.egl_context()
|
||||||
|
.user_data()
|
||||||
|
.get::<PostprocessShader>()
|
||||||
|
.expect("OffscreenShader should be available through `init_shaders`");
|
||||||
|
let texture_geometry =
|
||||||
|
texture_elem.geometry(self.output.current_scale().fractional_scale().into());
|
||||||
|
elements = {
|
||||||
|
let texture_elem = TextureShaderElement::new(
|
||||||
|
texture_elem,
|
||||||
|
postprocess_texture_shader.0.clone(),
|
||||||
|
vec![
|
||||||
|
Uniform::new("invert", if self.screen_filter.inverted { 1. } else { 0. }),
|
||||||
|
Uniform::new(
|
||||||
|
"color_mode",
|
||||||
|
self.screen_filter
|
||||||
|
.color_filter
|
||||||
|
.map(|val| val as u8 as f32)
|
||||||
|
.unwrap_or(0.),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
constrain_render_elements(
|
||||||
|
std::iter::once(texture_elem),
|
||||||
|
(0, 0),
|
||||||
|
Rectangle::from_size(
|
||||||
|
self.output
|
||||||
|
.geometry()
|
||||||
|
.size
|
||||||
|
.as_logical()
|
||||||
|
.to_f64()
|
||||||
|
.to_physical(self.output.current_scale().fractional_scale())
|
||||||
|
.to_i32_round(),
|
||||||
|
),
|
||||||
|
texture_geometry,
|
||||||
|
ConstrainScaleBehavior::Fit,
|
||||||
|
ConstrainAlign::CENTER,
|
||||||
|
1.0,
|
||||||
|
)
|
||||||
|
.map(CosmicElement::Postprocess)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
};
|
||||||
|
|
||||||
if let Err(err) = compositor.with_compositor(|c| c.use_vrr(vrr)) {
|
if let Err(err) = compositor.with_compositor(|c| c.use_vrr(vrr)) {
|
||||||
warn!("Unable to set adaptive VRR state: {}", err);
|
warn!("Unable to set adaptive VRR state: {}", err);
|
||||||
}
|
}
|
||||||
|
|
@ -1150,16 +1201,15 @@ impl SurfaceThreadState {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut sync = SyncPoint::default();
|
let mut sync = SyncPoint::default();
|
||||||
|
|
||||||
let mut dmabuf_clone;
|
let mut dmabuf_clone;
|
||||||
let mut render_buffer;
|
let mut render_buffer;
|
||||||
let buffer = frame.buffer();
|
let buffer = frame.buffer();
|
||||||
let mut shm_buffer = false;
|
let mut shm_buffer = false;
|
||||||
let mut fb = if let Ok(dmabuf) = get_dmabuf(&buffer) {
|
let mut fb = if let Ok(dmabuf) = get_dmabuf(&buffer) {
|
||||||
dmabuf_clone = dmabuf.clone();
|
dmabuf_clone = dmabuf.clone();
|
||||||
renderer
|
Some(renderer
|
||||||
.bind(&mut dmabuf_clone)
|
.bind(&mut dmabuf_clone)
|
||||||
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?
|
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?)
|
||||||
} else {
|
} else {
|
||||||
shm_buffer = true;
|
shm_buffer = true;
|
||||||
let size = buffer_dimensions(&buffer).ok_or(RenderError::<
|
let size = buffer_dimensions(&buffer).ok_or(RenderError::<
|
||||||
|
|
@ -1171,16 +1221,24 @@ impl SurfaceThreadState {
|
||||||
with_buffer_contents(&buffer, |_, _, data| shm_format_to_fourcc(data.format))
|
with_buffer_contents(&buffer, |_, _, data| shm_format_to_fourcc(data.format))
|
||||||
.map_err(|_| OutputNoMode)? // eh, we have to do some error
|
.map_err(|_| OutputNoMode)? // eh, we have to do some error
|
||||||
.expect("We should be able to convert all hardcoded shm screencopy formats");
|
.expect("We should be able to convert all hardcoded shm screencopy formats");
|
||||||
render_buffer =
|
|
||||||
Offscreen::<GlesRenderbuffer>::create_buffer(
|
if pre_postprocess_texture
|
||||||
&mut renderer,
|
.as_ref()
|
||||||
format,
|
.is_some_and(|tex| tex.format() == Some(format))
|
||||||
size,
|
{
|
||||||
)
|
None
|
||||||
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?;
|
} else {
|
||||||
renderer
|
render_buffer =
|
||||||
.bind(&mut render_buffer)
|
Offscreen::<GlesRenderbuffer>::create_buffer(
|
||||||
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?
|
&mut renderer,
|
||||||
|
format,
|
||||||
|
size,
|
||||||
|
)
|
||||||
|
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?;
|
||||||
|
Some(renderer
|
||||||
|
.bind(&mut render_buffer)
|
||||||
|
.map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref damage) = damage {
|
if let Some(ref damage) = damage {
|
||||||
|
|
@ -1214,52 +1272,76 @@ impl SurfaceThreadState {
|
||||||
d
|
d
|
||||||
});
|
});
|
||||||
|
|
||||||
match frame_result
|
if let Some(tex) = pre_postprocess_texture.as_mut() {
|
||||||
.blit_frame_result(
|
let mut tex_fb = renderer.bind(tex).map_err(RenderError::<<GlMultiRenderer as RendererSuper>::Error>::Rendering)?;
|
||||||
output_size,
|
|
||||||
output_transform,
|
if let Some(fb) = fb.as_mut() {
|
||||||
output_scale,
|
for rect in adjusted {
|
||||||
&mut renderer,
|
renderer
|
||||||
&mut fb,
|
.blit(
|
||||||
adjusted,
|
&mut tex_fb,
|
||||||
filter,
|
fb,
|
||||||
)
|
rect,
|
||||||
.map_err(|err| match err {
|
rect,
|
||||||
BlitFrameResultError::Rendering(err) => RenderError::<
|
TextureFilter::Linear,
|
||||||
<GlMultiRenderer as RendererSuper>::Error,
|
)
|
||||||
>::Rendering(
|
.map_err(
|
||||||
err
|
RenderError::<
|
||||||
),
|
<GlMultiRenderer as RendererSuper>::Error,
|
||||||
BlitFrameResultError::Export(_) => RenderError::<
|
>::Rendering,
|
||||||
<GlMultiRenderer as RendererSuper>::Error,
|
)?;
|
||||||
>::Rendering(
|
}
|
||||||
MultiError::DeviceMissing,
|
} else {
|
||||||
),
|
fb = Some(tex_fb);
|
||||||
}) {
|
|
||||||
Ok(new_sync) => {
|
|
||||||
sync = new_sync;
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tracing::warn!(?err, "Failed to screencopy");
|
|
||||||
session
|
|
||||||
.user_data()
|
|
||||||
.get::<SessionData>()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.reset();
|
|
||||||
frame.fail(FailureReason::Unknown);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
match frame_result
|
||||||
|
.blit_frame_result(
|
||||||
|
output_size,
|
||||||
|
output_transform,
|
||||||
|
output_scale,
|
||||||
|
&mut renderer,
|
||||||
|
fb.as_mut().unwrap(),
|
||||||
|
adjusted,
|
||||||
|
filter,
|
||||||
|
)
|
||||||
|
.map_err(|err| match err {
|
||||||
|
BlitFrameResultError::Rendering(err) => RenderError::<
|
||||||
|
<GlMultiRenderer as RendererSuper>::Error,
|
||||||
|
>::Rendering(
|
||||||
|
err
|
||||||
|
),
|
||||||
|
BlitFrameResultError::Export(_) => RenderError::<
|
||||||
|
<GlMultiRenderer as RendererSuper>::Error,
|
||||||
|
>::Rendering(
|
||||||
|
MultiError::DeviceMissing,
|
||||||
|
),
|
||||||
|
}) {
|
||||||
|
Ok(new_sync) => {
|
||||||
|
sync = new_sync;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!(?err, "Failed to screencopy");
|
||||||
|
session
|
||||||
|
.user_data()
|
||||||
|
.get::<SessionData>()
|
||||||
|
.unwrap()
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.reset();
|
||||||
|
frame.fail(FailureReason::Unknown);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
let transform = self.output.current_transform();
|
let transform = self.output.current_transform();
|
||||||
|
|
||||||
match submit_buffer(
|
match submit_buffer(
|
||||||
frame,
|
frame,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
shm_buffer.then_some(&mut fb),
|
shm_buffer.then_some(fb.as_mut().unwrap()),
|
||||||
transform,
|
transform,
|
||||||
damage.as_deref(),
|
damage.as_deref(),
|
||||||
sync,
|
sync,
|
||||||
|
|
@ -1286,7 +1368,8 @@ impl SurfaceThreadState {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.mirroring.is_none() {
|
if self.mirroring.is_none() {
|
||||||
let states = frame_result.states;
|
// If postprocessing, use states from first render
|
||||||
|
let states = pre_postprocess_states.unwrap_or(frame_result.states);
|
||||||
self.send_dmabuf_feedback(states);
|
self.send_dmabuf_feedback(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1386,6 +1469,11 @@ impl SurfaceThreadState {
|
||||||
self.postprocess_textures.clear();
|
self.postprocess_textures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_screen_filter(&mut self, filter_config: ScreenFilter) {
|
||||||
|
self.screen_filter = filter_config;
|
||||||
|
self.postprocess_textures.clear();
|
||||||
|
}
|
||||||
|
|
||||||
fn send_frame_callbacks(&mut self) {
|
fn send_frame_callbacks(&mut self) {
|
||||||
if self.mirroring.is_none() {
|
if self.mirroring.is_none() {
|
||||||
let _ = self
|
let _ = self
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,7 @@ impl BackendData {
|
||||||
&mut self,
|
&mut self,
|
||||||
test_only: bool,
|
test_only: bool,
|
||||||
loop_handle: &LoopHandle<'static, State>,
|
loop_handle: &LoopHandle<'static, State>,
|
||||||
|
screen_filter: &ScreenFilter,
|
||||||
shell: Arc<RwLock<Shell>>,
|
shell: Arc<RwLock<Shell>>,
|
||||||
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
|
workspace_state: &mut WorkspaceUpdateGuard<'_, State>,
|
||||||
xdg_activation_state: &XdgActivationState,
|
xdg_activation_state: &XdgActivationState,
|
||||||
|
|
@ -318,6 +319,7 @@ impl BackendData {
|
||||||
BackendData::Kms(ref mut state) => state.apply_config_for_outputs(
|
BackendData::Kms(ref mut state) => state.apply_config_for_outputs(
|
||||||
test_only,
|
test_only,
|
||||||
loop_handle,
|
loop_handle,
|
||||||
|
screen_filter,
|
||||||
shell.clone(),
|
shell.clone(),
|
||||||
startup_done,
|
startup_done,
|
||||||
clock,
|
clock,
|
||||||
|
|
@ -453,7 +455,12 @@ impl BackendData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> anyhow::Result<()> {
|
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> anyhow::Result<()> {
|
||||||
let _ = screen_filter; // TODO
|
match self {
|
||||||
|
BackendData::Kms(ref mut state) => state.update_screen_filter(screen_filter),
|
||||||
|
BackendData::Winit(ref mut state) => {}, // TODO
|
||||||
|
BackendData::X11(ref mut state) => {}, // TODO
|
||||||
|
_ => unreachable!("No backend set when setting screen filters"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ impl State {
|
||||||
let res = self.backend.apply_config_for_outputs(
|
let res = self.backend.apply_config_for_outputs(
|
||||||
test_only,
|
test_only,
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
|
self.common.config.dynamic_conf.screen_filter(),
|
||||||
self.common.shell.clone(),
|
self.common.shell.clone(),
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
&self.common.xdg_activation_state,
|
&self.common.xdg_activation_state,
|
||||||
|
|
@ -158,6 +159,7 @@ impl State {
|
||||||
if let Err(err) = self.backend.apply_config_for_outputs(
|
if let Err(err) = self.backend.apply_config_for_outputs(
|
||||||
false,
|
false,
|
||||||
&self.common.event_loop_handle,
|
&self.common.event_loop_handle,
|
||||||
|
self.common.config.dynamic_conf.screen_filter(),
|
||||||
self.common.shell.clone(),
|
self.common.shell.clone(),
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
&self.common.xdg_activation_state,
|
&self.common.xdg_activation_state,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue