Commit 867b15d7c12f
tarball6 files changed+115-87
@@ -1,6 +1,7 @@
11
//! ext-image-copy-capture of outputs and single windows, for grim and screen22
//! sharing portals.33
4
+use crate::frame::{CLEAR, FrameCtx};45
use crate::scene::Draw;56
use crate::state::{State, now_ns};67
use monolith_layout::{OutputId, WindowId};@@ -204,7 +205,19 @@ impl State {
204205
frame.fail(CaptureFailureReason::Stopped);205206
return;206207
};207
- self.output_elements(o, &output, session.draw_cursor())208
+ let ctx = FrameCtx {209
+ renderer: &mut self.renderer,210
+ wm: &mut self.wm,211
+ input: &mut self.input,212
+ lock: &self.services.lock,213
+ deco: &self.settings.config.decoration,214
+ unmanaged: self215
+ .services216
+ .xwayland217
+ .as_ref()218
+ .map_or(&[], |x| &x.unmanaged),219
+ };220
+ crate::frame::compose(ctx, o, &output, now_ns(), session.draw_cursor())208221
}209222
Target::Window(id) => match self.wm.window(*id) {210223
Some(window) => window_elements(&mut self.renderer, window),@@ -274,38 +287,6 @@ impl State {
274287
Ok(())275288
}276289
277
- /// Everything output `o` shows, as the backends draw it.278
- pub fn output_elements(&mut self, o: OutputId, output: &Output, cursor: bool) -> Vec<Draw> {279
- let now = now_ns();280
- let mut elements = Vec::new();281
- if cursor && let Some(area) = self.wm.layout.output(o).map(|out| out.area) {282
- let local = self.input.pointer_pos - Point::from((area.x, area.y));283
- if local.x >= 0.0 && local.y >= 0.0 && local.x < area.w && local.y < area.h {284
- elements.extend(self.input.cursor.elements(285
- &mut self.renderer,286
- &self.input.cursor_status,287
- local,288
- ));289
- }290
- }291
- match crate::lock::elements(&self.services.lock, &mut self.renderer, output) {292
- Some(locked) => elements.extend(locked),293
- None => elements.extend(crate::scene::build(294
- &mut self.wm,295
- o,296
- &mut self.renderer,297
- now,298
- &self.settings.config.decoration,299
- Some(output),300
- self.services301
- .xwayland302
- .as_ref()303
- .map_or(&[], |x| &x.unmanaged),304
- )),305
- }306
- elements307
- }308
-309290
fn output_named(&self, name: &str) -> Option<(OutputId, Output)> {310291
self.wm311292
.layout@@ -325,5 +306,3 @@ fn window_elements(renderer: &mut VulkanRenderer, window: &smithay::desktop::Win
325306
326307
/// Marks a session that has had a frame, so later ones wait for damage.327308
struct Delivered;328
-329
-const CLEAR: [f32; 4] = [0.07, 0.075, 0.09, 1.0];@@ -41,7 +41,7 @@ use std::collections::{HashMap, VecDeque};
4141
use std::path::{Path, PathBuf};4242
use std::time::Duration;4343
44
-const CLEAR: [f32; 4] = [0.07, 0.075, 0.09, 1.0];44
+use crate::frame::{CLEAR, FrameCtx};4545
/// Frames that only move the cursor stay at or below 60 Hz under VRR, so the4646
/// mouse does not override the refresh rate a game is pacing.4747
const CURSOR_FRAME_NS: u64 = 16_666_667;@@ -658,30 +658,21 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
658658
}659659
let began = std::time::Instant::now();660660
let now = target;661
- let Some(area) = wm.layout.output(surface.id).map(|o| o.area) else {661
+ if wm.layout.output(surface.id).is_none() {662662
return false;663
- };664
- let mut elements = Vec::new();665
- let local = input.pointer_pos - Point::from((area.x, area.y));666
- if local.x >= 0.0 && local.y >= 0.0 && local.x < area.w && local.y < area.h {667
- elements.extend(input.cursor.elements(renderer, &input.cursor_status, local));668663
}669664
let scene_began = std::time::Instant::now();670
- match crate::lock::elements(lock, renderer, &surface.output) {671
- Some(locked) => elements.extend(locked),672
- None => elements.extend(crate::scene::build(673
- wm,674
- surface.id,675
- renderer,676
- now,677
- &settings.config.decoration,678
- Some(&surface.output),679
- xwayland.as_ref().map_or(&[], |x| &x.unmanaged),680
- )),681
- }665
+ let ctx = FrameCtx {666
+ renderer: &mut *renderer,667
+ wm: &mut *wm,668
+ input: &mut *input,669
+ lock: &*lock,670
+ deco: &settings.config.decoration,671
+ unmanaged: xwayland.as_ref().map_or(&[], |x| &x.unmanaged),672
+ };673
+ let elements = crate::frame::compose(ctx, surface.id, &surface.output, now, true);682674
let scene_ns = scene_began.elapsed().as_nanos() as u64;683675
let animating = wm.anim.active(now);684
- wm.anim.prune(now);685676
let render_began = std::time::Instant::now();686677
let cpu_began = thread_cpu_ns();687678
let mut queue_ns = 0;@@ -724,17 +715,7 @@ fn render_surface(state: &mut State, crtc: crtc::Handle, target: u64) -> bool {
724715
}725716
surface.redraw = animating;726717
let elapsed = core.start.elapsed();727
- let output = surface.output.clone();728
- if lock.active() {729
- crate::lock::send_frames(lock, &output, elapsed);730
- return animating && !surface.queued;731
- }732
- for window in wm.space.elements_for_output(&output) {733
- window.send_frame(&output, elapsed, Some(Duration::ZERO), |_, _| {734
- Some(output.clone())735
- });736
- }737
- crate::layers::send_frames(&output, elapsed);718
+ crate::frame::send_frame_callbacks(wm, lock, &surface.output, elapsed);738719
animating && !surface.queued739720
}740721
@@ -0,0 +1,75 @@
1
+//! What every output shows, shared by the backends and screen capture.2
+//! Backends only decide when to draw and how to present.3
+4
+use crate::lock::Lock;5
+use crate::scene::Draw;6
+use crate::state::Input;7
+use crate::wm::Wm;8
+use monolith_config::Decoration;9
+use monolith_layout::OutputId;10
+use monolith_render_vk::VulkanRenderer;11
+use smithay::output::Output;12
+use smithay::utils::Point;13
+use smithay::xwayland::X11Surface;14
+use std::time::Duration;15
+16
+pub const CLEAR: [f32; 4] = [0.07, 0.075, 0.09, 1.0];17
+18
+/// Everything a frame reads, borrowed apart from the rest of the state.19
+pub struct FrameCtx<'a> {20
+ pub renderer: &'a mut VulkanRenderer,21
+ pub wm: &'a mut Wm,22
+ pub input: &'a mut Input,23
+ pub lock: &'a Lock,24
+ pub deco: &'a Decoration,25
+ pub unmanaged: &'a [X11Surface],26
+}27
+28
+/// The elements output `o` shows at `now`, front to back. `cursor` draws the29
+/// pointer, which a nested session leaves to its host.30
+pub fn compose(31
+ ctx: FrameCtx<'_>,32
+ o: OutputId,33
+ output: &Output,34
+ now: u64,35
+ cursor: bool,36
+) -> Vec<Draw> {37
+ let mut elements = Vec::new();38
+ if cursor && let Some(area) = ctx.wm.layout.output(o).map(|out| out.area) {39
+ let local = ctx.input.pointer_pos - Point::from((area.x, area.y));40
+ if local.x >= 0.0 && local.y >= 0.0 && local.x < area.w && local.y < area.h {41
+ elements.extend(ctx.input.cursor.elements(42
+ ctx.renderer,43
+ &ctx.input.cursor_status,44
+ local,45
+ ));46
+ }47
+ }48
+ match crate::lock::elements(ctx.lock, ctx.renderer, output) {49
+ Some(locked) => elements.extend(locked),50
+ None => elements.extend(crate::scene::build(51
+ ctx.wm,52
+ o,53
+ ctx.renderer,54
+ now,55
+ ctx.deco,56
+ Some(output),57
+ ctx.unmanaged,58
+ )),59
+ }60
+ elements61
+}62
+63
+/// Lets clients shown on `output` draw their next frame.64
+pub fn send_frame_callbacks(wm: &Wm, lock: &Lock, output: &Output, elapsed: Duration) {65
+ if lock.active() {66
+ crate::lock::send_frames(lock, output, elapsed);67
+ return;68
+ }69
+ for window in wm.space.elements_for_output(output) {70
+ window.send_frame(output, elapsed, Some(Duration::ZERO), |_, _| {71
+ Some(output.clone())72
+ });73
+ }74
+ crate::layers::send_frames(output, elapsed);75
+}@@ -6,6 +6,7 @@ mod commands;
66
mod cursor;77
mod drm;88
mod focus;9
+mod frame;910
mod globals;1011
mod handlers;1112
mod idle;@@ -18,7 +18,6 @@ use smithay::backend::renderer::damage::OutputDamageTracker;
1818
use smithay::output::{Mode, Output, PhysicalProperties, Subpixel};1919
use smithay::reexports::calloop::EventLoop;2020
use smithay::utils::{Logical, Size, Transform};21
-use std::time::Duration;2221
use wayland_client::globals::{GlobalListContents, registry_queue_init};2322
use wayland_client::protocol::{wl_buffer, wl_callback, wl_compositor, wl_registry, wl_surface};2423
use wayland_client::{Connection, Dispatch, QueueHandle, delegate_noop};@@ -31,7 +30,7 @@ use wayland_protocols::xdg::decoration::zv1::client::{
3130
};3231
use wayland_protocols::xdg::shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base};3332
34
-const CLEAR: [f32; 4] = [0.07, 0.075, 0.09, 1.0];33
+use crate::frame::{CLEAR, FrameCtx};3534
const DEFAULT_SIZE: (i32, i32) = (1280, 800);3635
const CLOCK_MONOTONIC: u32 = 1;3736
@@ -175,6 +174,7 @@ pub fn render(state: &mut State) {
175174
backend,176175
renderer,177176
wm,177
+ input,178178
dirty,179179
core,180180
settings,@@ -231,17 +231,15 @@ pub fn render(state: &mut State) {
231231
}232232
};233233
let o = host.output_id;234
- let elements = crate::lock::elements(lock, renderer, &host.output).unwrap_or_else(|| {235
- crate::scene::build(236
- wm,237
- o,238
- renderer,239
- now,240
- &settings.config.decoration,241
- Some(&host.output),242
- xwayland.as_ref().map_or(&[], |x| &x.unmanaged),243
- )244
- });234
+ let ctx = FrameCtx {235
+ renderer: &mut *renderer,236
+ wm: &mut *wm,237
+ input: &mut *input,238
+ lock: &*lock,239
+ deco: &settings.config.decoration,240
+ unmanaged: xwayland.as_ref().map_or(&[], |x| &x.unmanaged),241
+ };242
+ let elements = crate::frame::compose(ctx, o, &host.output, now, false);245243
match host246244
.damage247245
.render_output(renderer, &mut fb, slot.age() as usize, &elements, CLEAR)@@ -259,16 +257,9 @@ pub fn render(state: &mut State) {
259257
}260258
};261259
dirty.redraw = wm.anim.active(now);262
- wm.anim.prune(now);263260
lock.shown(&host.output);264261
let elapsed = core.start.elapsed();265
- crate::lock::send_frames(lock, &host.output, elapsed);266
- for window in wm.space.elements().filter(|_| !lock.active()) {267
- window.send_frame(&host.output, elapsed, Some(Duration::ZERO), |_, _| {268
- Some(host.output.clone())269
- });270
- }271
- crate::layers::send_frames(&host.output, elapsed);262
+ crate::frame::send_frame_callbacks(wm, lock, &host.output, elapsed);272263
if damage.is_some() {273264
captures.output_damaged(&host.output);274265
}@@ -193,6 +193,7 @@ impl State {
193193
crate::backend::Backend::Nested(_) => crate::nested::render(self),194194
crate::backend::Backend::Starting => {}195195
}196
+ self.wm.anim.prune(now_ns());196197
self.confirm_lock();197198
self.complete_captures();198199
crate::ipc::broadcast(self);