AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* The native owner recomputes deadlines after every dispatched batch, before3
* blocking. Admission and cancellation in any protocol/idle callback therefore4
* update the next wait without a periodic scan or per-protocol re-arm hooks. */5
static void earlier_deadline(uint64_t *next,uint64_t deadline) {6
if(deadline && deadline<*next) *next=deadline;7
}8
static 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;51
}52
static 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;60
}61
static 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 computing64
* 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;72
}