AtlatestRepositorysigil-wm

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

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copied base ramps and external ownership share the frame commit. */
3static 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}
7static 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 }
19static 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 }
35static 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;
51static 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);
56static 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);
63static 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 }
71static bool output_commit_gamma(struct output *o) {
72 /* A page flip must finish before another buffer/gamma commit. Never issue
73 * 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 LUT
92 * 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;