AtlatestRepositorysigil-wm

sigil-wm / tree / src / cdeadlines.h

1/* SPDX-License-Identifier: BSD-3-Clause
2 * The native owner recomputes deadlines after every dispatched batch, before
3 * blocking. Admission and cancellation in any protocol/idle callback therefore
4 * update the next wait without a periodic scan or per-protocol re-arm hooks. */
5static void earlier_deadline(uint64_t *next,uint64_t deadline) {
6 if(deadline && deadline<*next) *next=deadline;
7}
8static uint64_t native_deadline(struct server *s,uint64_t now) {
9 uint64_t next=UINT64_MAX;
10 if(atomic_load(&bridge.input_resync)) earlier_deadline(&next,now);
11 if(s->plan) earlier_deadline(&next,s->plan_deadline);
12 struct output *output;
13 wl_list_for_each(output,&s->outputs,link) {
14 earlier_deadline(&next,output->gamma_retry_at);
15 earlier_deadline(&next,output->scene_retry_at);
16 }
17 earlier_deadline(&next,s->scene_update_deadline);
18 if(s->lock_state==1) earlier_deadline(&next,s->lock_deadline);
19 if(s->has_pending_motion) earlier_deadline(&next,(uint64_t)s->motion_last+s->motion_period);
20 bool head=true;
21 for(unsigned index=s->input_read;index!=s->input_write;index++) {
22 struct input *in=&s->inputs[index%QUEUE_SIZE];
23 if(in->completed) continue;
24 if(in->kind==30 && in->native) earlier_deadline(&next,in->order_deadline);
25 if(in->kind==32 && !in->ready) earlier_deadline(&next,in->deadline);
26 if(head) {
27 if(in->native && in->kind==32 && in->generation==s->generation && motion_matches(s,in))
28 earlier_deadline(&next,(uint64_t)s->motion_last+s->motion_period);
29 else if(!in->ready) earlier_deadline(&next,in->deadline);
30 }
31 head=false;
32 }
33 struct permission *permission;
34 wl_list_for_each(permission,&s->permissions,link) earlier_deadline(&next,permission->deadline);
35 struct data_request *data;
36 wl_list_for_each(data,&s->data_requests,link) earlier_deadline(&next,data->deadline);
37 struct output_control_request *control;
38 wl_list_for_each(control,&s->output_controls,link) {
39 if(!find_output(s,control->output)) earlier_deadline(&next,now);
40 else if(!control->resolved) earlier_deadline(&next,control->deadline);
41 }
42 struct output_configuration_request *request;
43 wl_list_for_each(request,&s->output_requests,link)
44 earlier_deadline(&next,request->revision==s->output_revision ? request->deadline : now);
45 struct pointer_hint *hint;
46 wl_list_for_each(hint,&s->pointer_hints,link)
47 earlier_deadline(&next,hint->generation==s->generation ? hint->deadline : now);
48 struct popup *popup;
49 wl_list_for_each(popup,&s->popups,link) earlier_deadline(&next,popup->deadline);
50 return next==UINT64_MAX ? 0 : next;
52static int rearm_deadline(struct server *s,uint64_t now) {
53 uint64_t next=native_deadline(s,now);
54 if(next==s->timer_deadline) return 0;
55 uint64_t delay=next>now ? next-now : 1;
56 int milliseconds=next ? (delay>INT_MAX ? INT_MAX : (int)delay) : 0;
57 int result=wl_event_source_timer_update(s->timer,milliseconds);
58 if(result==0) s->timer_deadline=next;
59 return result;
61static int dispatch_native_once(struct server *s,int timeout) {
62 struct wl_event_loop *loop=wl_display_get_event_loop(s->display);
63 /* Wayland dispatches idles before blocking. Drain them before computing
64 * the wait too, so even work admitted by an idle has a timer armed. */
65 wl_event_loop_dispatch_idle(loop);
66 if(s->stopping) return 0;
67 if(rearm_deadline(s,now_ms())<0) return -1;
68 wl_display_flush_clients(s->display);
69 int result=wl_event_loop_dispatch(loop,timeout);
70 output_gamma_observe(s);
71 return result;