AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Copied base ramps and external ownership share the frame commit. */3
static struct wlr_gamma_control_v1 *output_gamma_control(struct output *o) {4
return o->server->gamma_manager ?5
wlr_gamma_control_manager_v1_get_control(o->server->gamma_manager,o->native) : NULL;6
}7
static void output_gamma_finish(struct server *s) {8
struct output *o;9
wl_list_for_each(o,&s->outputs,link) {10
if(!o->native->enabled || output_gamma_control(o)) continue;11
struct wlr_output_state state;12
wlr_output_state_init(&state);13
if((!wlr_output_state_set_gamma_lut(&state,0,NULL,NULL,NULL) ||14
!wlr_output_commit_state(o->native,&state)) && wlr_output_get_gamma_size(o->native)>0)15
wlr_log(WLR_ERROR,"failed to restore neutral gamma on output %s",o->native->name);16
wlr_output_state_finish(&state);17
}18
}19
static void output_gamma_observe(struct server *s) {20
if(!s->gamma_manager) return;21
struct output *o;22
wl_list_for_each(o,&s->outputs,link) {23
struct wlr_gamma_control_v1 *control=output_gamma_control(o);24
bool external=control!=NULL;25
if(external==o->gamma_external) continue;26
o->gamma_external=external;27
o->gamma_retry_at=0;28
/* Acquisition alone owns gamma, even before the first table arrives. */29
if(!external) o->gamma_pending=true;30
else if(!control->table) o->gamma_pending=false;31
EVENT(130,o->id,wlr_output_get_gamma_size(o->native),external);32
if(!external) wlr_output_schedule_frame(o->native);33
}34
}35
static bool output_set_gamma(struct server *s,uint64_t token,const int64_t *words,size_t count) {36
if(count<2 || words[1]<2 || words[1]>16384 || count!=2+3*(size_t)words[1]) return false;37
struct output *o=find_output(s,words[0]);38
if(!o || (size_t)words[1]!=wlr_output_get_gamma_size(o->native)) return false;39
for(size_t i=2;i<count;i++) if(words[i]<0 || words[i]>UINT16_MAX) return false;40
uint16_t *table=malloc((count-2)*sizeof(*table));41
if(!table) return false;42
for(size_t i=2;i<count;i++) table[i-2]=words[i];43
free(o->gamma_table);44
o->gamma_table=table; o->gamma_size=words[1]; o->gamma_token=token;45
if(!output_gamma_control(o)) {46
o->gamma_pending=true;47
wlr_output_schedule_frame(o->native);48
}49
return true;50
}51
static bool output_base_gamma(struct output *o,struct wlr_output_state *state) {52
if(!o->gamma_table) return wlr_output_state_set_gamma_lut(state,0,NULL,NULL,NULL);53
return wlr_output_state_set_gamma_lut(state,o->gamma_size,54
o->gamma_table,o->gamma_table+o->gamma_size,o->gamma_table+2*o->gamma_size);55
}56
static void output_gamma_present(struct wl_listener *listener,void *data) {57
(void)data;58
struct output *o=wl_container_of(listener,o,gamma_present);59
if(!o->gamma_retry_at) return;60
o->gamma_retry_at=0;61
wlr_output_schedule_frame(o->native);62
}63
static void output_gamma_expire(struct server *s) {64
struct output *o;65
wl_list_for_each(o,&s->outputs,link) {66
if(!o->gamma_retry_at || now_ms()<o->gamma_retry_at) continue;67
o->gamma_retry_at=0;68
if(o->native->enabled) wlr_output_schedule_frame(o->native);69
}70
}71
static bool output_commit_gamma(struct output *o) {72
/* A page flip must finish before another buffer/gamma commit. Never issue73
* a second commit from this frame callback after a runtime failure. */74
if(o->native->frame_pending) return false;75
o->gamma_retry_at=0;76
struct wlr_gamma_control_v1 *control=output_gamma_control(o);77
if(control && !control->table) {78
o->gamma_pending=false;79
return wlr_scene_output_commit(o->scene,NULL);80
}81
struct wlr_output_state state;82
wlr_output_state_init(&state);83
bool gamma=control ? wlr_gamma_control_v1_apply(control,&state) : output_base_gamma(o,&state);84
bool built=gamma && wlr_scene_output_build_state(o->scene,&state,NULL);85
bool supported=built && wlr_output_test_state(o->native,&state);86
if(built && !supported) {87
/* Invalid LUTs cannot prevent the same scene's normal presentation.88
* Keep the rendered buffer and remove just the rejected LUT field. */89
state.committed &= ~WLR_OUTPUT_STATE_GAMMA_LUT;90
if(!wlr_output_test_state(o->native,&state)) {91
/* The scene itself is temporarily invalid. Do not blame the LUT92
* or revoke a client's ownership for an unrelated backend fault. */93
wlr_output_state_finish(&state);94
o->gamma_retry_at=now_ms()+16;95
return false;96
}97
o->gamma_pending=false;98
if(control) wlr_gamma_control_v1_send_failed_and_destroy(control);99
else EVENT(131,o->id,o->gamma_token,false);100
}101
bool committed=built && wlr_output_commit_state(o->native,&state);102
wlr_output_state_finish(&state);103
if(committed && supported) {104
o->gamma_pending=false;105
if(!control) EVENT(131,o->id,o->gamma_token,true);106
} else if(!committed) {107
/* EBUSY and other runtime failures retain the LUT and scene damage.108
* Retry on the next backend frame rather than racing the page flip. */109
o->gamma_retry_at=now_ms()+16;110
}111
return committed;112
}