Make screenshot UI render target-aware

This commit is contained in:
Ivan Molodetskikh
2024-03-24 11:11:15 +04:00
parent e43e10f44e
commit 5f23d344d5
3 changed files with 57 additions and 40 deletions
+9 -6
View File
@@ -402,14 +402,17 @@ animations {
// To preview and set up this rule, check the preview-render option // To preview and set up this rule, check the preview-render option
// in the debug section of the config. // in the debug section of the config.
// //
// WARNING: the window is NOT blocked out from the screenshot UI. // WARNING: the window is NOT blocked out from third-party screenshot tools.
// If you open the screenshot UI while screencasting, blocked out windows // If you open some screenshot tool with preview while screencasting,
// WILL BE VISIBLE on the screencast. // blocked out windows WILL BE VISIBLE on the screencast.
//
// The built-in screenshot UI is not affected though, you can use it safely,
// and windows will remain blocked out even when screencasting it.
block-out-from "screencast" block-out-from "screencast"
// You can also block out the window out of all screen captures, including // You can also block out the window out of all screen captures, including
// the screenshot UI. This way you avoid accidentally showing the window // third-party screenshot tools. This way you avoid accidentally showing
// on a screencast when opening the screenshot UI. // the window on a screencast when opening a third-party screenshot preview.
block-out-from "screen-capture" block-out-from "screen-capture"
// You can amend the window's minimum and maximum size in logical pixels. // You can amend the window's minimum and maximum size in logical pixels.
@@ -459,7 +462,7 @@ window-rule {
match app-id=r#"^org\.keepassxc\.KeePassXC$"# match app-id=r#"^org\.keepassxc\.KeePassXC$"#
match app-id=r#"^org\.gnome\.World\.Secrets$"# match app-id=r#"^org\.gnome\.World\.Secrets$"#
// Warning: will be visible when opening the screenshot UI. // Warning: will be visible on third-party screenshot tools.
block-out-from "screencast" block-out-from "screencast"
// Use this instead to block out from all screen captures. // Use this instead to block out from all screen captures.
+27 -21
View File
@@ -2307,7 +2307,7 @@ impl Niri {
if self.screenshot_ui.is_open() { if self.screenshot_ui.is_open() {
elements.extend( elements.extend(
self.screenshot_ui self.screenshot_ui
.render_output(output) .render_output(output, target)
.into_iter() .into_iter()
.map(OutputRenderElements::from), .map(OutputRenderElements::from),
); );
@@ -3104,31 +3104,37 @@ impl Niri {
let size = transform.transform_size(size); let size = transform.transform_size(size);
let scale = Scale::from(output.current_scale().fractional_scale()); let scale = Scale::from(output.current_scale().fractional_scale());
let elements = self.render::<GlesRenderer>( let targets = [
renderer, RenderTarget::Output,
&output, RenderTarget::Screencast,
true,
RenderTarget::ScreenCapture, RenderTarget::ScreenCapture,
); ];
let elements = elements.iter().rev(); let textures = targets.map(|target| {
let elements = self.render::<GlesRenderer>(renderer, &output, true, target);
let elements = elements.iter().rev();
let res = render_to_texture( let res = render_to_texture(
renderer, renderer,
size, size,
scale, scale,
Transform::Normal, Transform::Normal,
Fourcc::Abgr8888, Fourcc::Abgr8888,
elements, elements,
); );
let screenshot = match res {
Ok((texture, _)) => texture, if let Err(err) = &res {
Err(err) => {
warn!("error rendering output {}: {err:?}", output.name()); warn!("error rendering output {}: {err:?}", output.name());
return None;
} }
};
Some((output, screenshot)) res
});
if textures.iter().any(|res| res.is_err()) {
return None;
}
let textures = textures.map(|res| res.unwrap().0);
Some((output, textures))
}) })
.collect(); .collect();
+21 -13
View File
@@ -19,6 +19,7 @@ use smithay::utils::{Physical, Point, Rectangle, Size, Transform};
use crate::niri_render_elements; use crate::niri_render_elements;
use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement; use crate::render_helpers::primary_gpu_texture::PrimaryGpuTextureRenderElement;
use crate::render_helpers::RenderTarget;
const BORDER: i32 = 2; const BORDER: i32 = 2;
@@ -42,8 +43,9 @@ pub struct OutputData {
size: Size<i32, Physical>, size: Size<i32, Physical>,
scale: i32, scale: i32,
transform: Transform, transform: Transform,
texture: GlesTexture, // Output, screencast, screen capture.
texture_buffer: TextureBuffer<GlesTexture>, texture: [GlesTexture; 3],
texture_buffer: [TextureBuffer<GlesTexture>; 3],
buffers: [SolidColorBuffer; 8], buffers: [SolidColorBuffer; 8],
locations: [Point<i32, Physical>; 8], locations: [Point<i32, Physical>; 8],
} }
@@ -65,7 +67,8 @@ impl ScreenshotUi {
pub fn open( pub fn open(
&mut self, &mut self,
renderer: &GlesRenderer, renderer: &GlesRenderer,
screenshots: HashMap<Output, GlesTexture>, // Output, screencast, screen capture.
screenshots: HashMap<Output, [GlesTexture; 3]>,
default_output: Output, default_output: Output,
) -> bool { ) -> bool {
if screenshots.is_empty() { if screenshots.is_empty() {
@@ -110,13 +113,9 @@ impl ScreenshotUi {
let output_mode = output.current_mode().unwrap(); let output_mode = output.current_mode().unwrap();
let size = transform.transform_size(output_mode.size); let size = transform.transform_size(output_mode.size);
let scale = output.current_scale().integer_scale(); let scale = output.current_scale().integer_scale();
let texture_buffer = TextureBuffer::from_texture( let texture_buffer = texture.clone().map(|texture| {
renderer, TextureBuffer::from_texture(renderer, texture, scale, Transform::Normal, None)
texture.clone(), });
scale,
Transform::Normal,
None,
);
let buffers = [ let buffers = [
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]), SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]), SolidColorBuffer::new((0, 0), [1., 1., 1., 1.]),
@@ -243,7 +242,11 @@ impl ScreenshotUi {
} }
} }
pub fn render_output(&self, output: &Output) -> ArrayVec<ScreenshotUiRenderElement, 9> { pub fn render_output(
&self,
output: &Output,
target: RenderTarget,
) -> ArrayVec<ScreenshotUiRenderElement, 9> {
let _span = tracy_client::span!("ScreenshotUi::render_output"); let _span = tracy_client::span!("ScreenshotUi::render_output");
let Self::Open { output_data, .. } = self else { let Self::Open { output_data, .. } = self else {
@@ -269,10 +272,15 @@ impl ScreenshotUi {
})); }));
// The screenshot itself goes last. // The screenshot itself goes last.
let index = match target {
RenderTarget::Output => 0,
RenderTarget::Screencast => 1,
RenderTarget::ScreenCapture => 2,
};
elements.push( elements.push(
PrimaryGpuTextureRenderElement(TextureRenderElement::from_texture_buffer( PrimaryGpuTextureRenderElement(TextureRenderElement::from_texture_buffer(
(0., 0.), (0., 0.),
&output_data.texture_buffer, &output_data.texture_buffer[index],
None, None,
None, None,
None, None,
@@ -307,7 +315,7 @@ impl ScreenshotUi {
.to_buffer(1, Transform::Normal, &data.size.to_logical(1)); .to_buffer(1, Transform::Normal, &data.size.to_logical(1));
let mapping = renderer let mapping = renderer
.copy_texture(&data.texture, buf_rect, Fourcc::Abgr8888) .copy_texture(&data.texture[0], buf_rect, Fourcc::Abgr8888)
.context("error copying texture")?; .context("error copying texture")?;
let copy = renderer let copy = renderer
.map_texture(&mapping) .map_texture(&mapping)