AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Render the current isolated scene into a tested multi-output modeset. */3
static bool output_debug(void) { return getenv("SIGIL_WM_DEBUG_OUTPUTS")!=NULL; }4
static 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;16
}17
static 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;19
}20
static 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;36
}37
static 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 or50
* 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;83
}