AtlatestRepositorysigil-wm

sigil-wm / tree / src / coutput-atomic.h

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Render the current isolated scene into a tested multi-output modeset. */
3static bool output_debug(void) { return getenv("SIGIL_WM_DEBUG_OUTPUTS")!=NULL; }
4static void output_wake_present(struct wl_listener *listener,void *data) {
5 struct output *output=wl_container_of(listener,output,wake_present);
6 struct wlr_output_event_present *event=data;
7 if(!output->wake_armed || !event->presented ||
8 (int32_t)(event->commit_seq-output->wake_commit)<0) return;
9 output->wake_armed=false;
10 if(output_debug())
11 wlr_log(WLR_ERROR,"OUTPUT_FIRST_PRESENT name=%s request-to-present-ms=%llu commit-to-present-ms=%llu sequence=%u locked=%d",
12 output->native->name,(unsigned long long)(now_ms()-output->wake_requested),
13 (unsigned long long)(now_ms()-output->wake_commit_time),event->commit_seq,
14 output->server->lock_state!=0);
15 output->wake_requested=0;
17static bool output_state_enabled(struct wlr_backend_output_state *state) {
18 return state->base.committed&WLR_OUTPUT_STATE_ENABLED ? state->base.enabled : state->output->enabled;
20static bool output_render_states(struct server *s,struct wlr_backend_output_state *states,
21 size_t count,struct wlr_output_swapchain_manager *manager) {
22 for(size_t index=0;index<count;index++) {
23 struct output *output=states[index].output->data;
24 if(!output) return false;
25 if(!output_state_enabled(&states[index])) continue;
26 struct wlr_scene_output_state_options options={0};
27 if(manager) options.swapchain=wlr_output_swapchain_manager_get_swapchain(manager,output->native);
28 /* The normal scene is disabled throughout lock ownership and recovery.
29 * The scene builder therefore includes only lock surfaces/opaque fill. */
30 lock_arm(output);
31 wlr_damage_ring_add_whole(&output->scene->damage_ring);
32 if(!wlr_scene_output_build_state(output->scene,&states[index].base,&options)) return false;
33 }
34 (void)s;
35 return true;
37static bool output_atomic_commit(struct server *s,struct wlr_backend_output_state *states,
38 size_t count,bool apply,bool per_output) {
39 if(!states || !count) return false;
40 s->output_commit_attempted=false;
41 struct wlr_output_swapchain_manager manager;
42 wlr_output_swapchain_manager_init(&manager,s->backend);
43 bool prepared=!per_output && wlr_output_swapchain_manager_prepare(&manager,states,count);
44 bool rendered=(prepared || per_output) && output_render_states(s,states,count,prepared ? &manager : NULL);
45 bool tested=!per_output && rendered && wlr_backend_test(s->backend,states,count);
46 bool fallback=per_output || !prepared || (rendered && !tested);
47 bool success=tested;
48 if(fallback) {
49 /* Only a failed atomic test permits per-output fallback. Rendering or
50 * commit failures are reported to the caller for its rollback path. */
51 if(!per_output && output_debug()) wlr_log(WLR_ERROR,"OUTPUT_ATOMIC_TEST_FAILED outputs=%zu fallback=per-output",count);
52 success=rendered || output_render_states(s,states,count,NULL);
53 for(size_t index=0;success && index<count;index++)
54 success=wlr_output_test_state(states[index].output,&states[index].base);
55 }
56 if(success && apply) {
57 s->output_commit_attempted=true;
58 uint64_t now=now_ms();
59 for(size_t index=0;index<count;index++) {
60 struct output *output=states[index].output->data;
61 if(!output_state_enabled(&states[index])) { output->wake_armed=false; continue; }
62 if(!output->wake_requested) output->wake_requested=now;
63 output->wake_commit_time=now;
64 output->wake_commit=output->native->commit_seq+1;
65 output->wake_armed=true;
66 }
67 if(output_debug()) wlr_log(WLR_ERROR,"OUTPUT_COMMIT outputs=%zu atomic=%d rendered=1 locked=%d",count,!fallback,s->lock_state!=0);
68 if(fallback) {
69 for(size_t index=0;success && index<count;index++)
70 success=wlr_output_commit_state(states[index].output,&states[index].base);
71 } else success=wlr_backend_commit(s->backend,states,count);
72 if(success && prepared) wlr_output_swapchain_manager_apply(&manager);
73 if(!success) {
74 for(size_t index=0;index<count;index++) {
75 struct output *output=states[index].output->data;
76 output->wake_armed=false;
77 }
78 wlr_log(WLR_ERROR,"OUTPUT_COMMIT_FAILED outputs=%zu atomic=%d",count,!fallback);
79 }
80 }
81 wlr_output_swapchain_manager_finish(&manager);
82 return success;