fix screen artifacts when setting gamma
the artifacts were caused because we tried to set the gamma right after receiving the event, this resulted in two pending page-flips, which not always play well together. This also seems to fix a screen freeze when turning on a monitor that has gamma. Additionally the current method won't work once [0] is merged [0]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4423
This commit is contained in:
parent
e1f3983bf8
commit
6f8a3f9374
47
dwl.c
47
dwl.c
|
@ -194,6 +194,7 @@ struct Monitor {
|
||||||
unsigned int sellt;
|
unsigned int sellt;
|
||||||
uint32_t tagset[2];
|
uint32_t tagset[2];
|
||||||
double mfact;
|
double mfact;
|
||||||
|
int gamma_lut_changed;
|
||||||
int nmaster;
|
int nmaster;
|
||||||
char ltsymbol[16];
|
char ltsymbol[16];
|
||||||
};
|
};
|
||||||
|
@ -1870,6 +1871,8 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
* generally at the output's refresh rate (e.g. 60Hz). */
|
* generally at the output's refresh rate (e.g. 60Hz). */
|
||||||
Monitor *m = wl_container_of(listener, m, frame);
|
Monitor *m = wl_container_of(listener, m, frame);
|
||||||
Client *c;
|
Client *c;
|
||||||
|
struct wlr_output_state pending = {0};
|
||||||
|
struct wlr_gamma_control_v1 *gamma_control;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
|
|
||||||
/* Render if no XDG clients have an outstanding resize and are visible on
|
/* Render if no XDG clients have an outstanding resize and are visible on
|
||||||
|
@ -1877,12 +1880,38 @@ rendermon(struct wl_listener *listener, void *data)
|
||||||
wl_list_for_each(c, &clients, link)
|
wl_list_for_each(c, &clients, link)
|
||||||
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HACK: The "correct" way to set the gamma is to commit it together with
|
||||||
|
* the rest of the state in one go, but to do that we would need to rewrite
|
||||||
|
* wlr_scene_output_commit() in order to add the gamma to the pending
|
||||||
|
* state before committing, instead try to commit the gamma in one frame,
|
||||||
|
* and commit the rest of the state in the next one (or in the same frame if
|
||||||
|
* the gamma can not be committed).
|
||||||
|
*/
|
||||||
|
if (m->gamma_lut_changed) {
|
||||||
|
gamma_control = wlr_gamma_control_manager_v1_get_control(gamma_control_mgr, m->wlr_output);
|
||||||
|
m->gamma_lut_changed = 0;
|
||||||
|
|
||||||
|
if (!wlr_gamma_control_v1_apply(gamma_control, &pending))
|
||||||
|
goto commit;
|
||||||
|
|
||||||
|
if (!wlr_output_test_state(m->wlr_output, &pending)) {
|
||||||
|
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
||||||
|
goto commit;
|
||||||
|
}
|
||||||
|
wlr_output_commit_state(m->wlr_output, &pending);
|
||||||
|
wlr_output_schedule_frame(m->wlr_output);
|
||||||
|
} else {
|
||||||
|
commit:
|
||||||
wlr_scene_output_commit(m->scene_output, NULL);
|
wlr_scene_output_commit(m->scene_output, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
/* Let clients know a frame has been rendered */
|
/* Let clients know a frame has been rendered */
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
wlr_scene_output_send_frame_done(m->scene_output, &now);
|
wlr_scene_output_send_frame_done(m->scene_output, &now);
|
||||||
|
wlr_output_state_finish(&pending);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2057,21 +2086,9 @@ void
|
||||||
setgamma(struct wl_listener *listener, void *data)
|
setgamma(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
|
struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
|
||||||
struct wlr_output_state state;
|
Monitor *m = event->output->data;
|
||||||
wlr_output_state_init(&state);
|
m->gamma_lut_changed = 1;
|
||||||
if (!wlr_gamma_control_v1_apply(event->control, &state)) {
|
wlr_output_schedule_frame(m->wlr_output);
|
||||||
wlr_output_state_finish(&state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wlr_output_test_state(event->output, &state)) {
|
|
||||||
wlr_gamma_control_v1_send_failed_and_destroy(event->control);
|
|
||||||
wlr_output_state_finish(&state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_output_commit_state(event->output, &state);
|
|
||||||
wlr_output_schedule_frame(event->output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in a new issue