diff options
author | Leonardo Hernández Hernández <leohdz172@proton.me> | 2023-11-16 20:58:45 -0600 |
---|---|---|
committer | Leonardo Hernández Hernández <leohdz172@proton.me> | 2023-11-17 11:01:30 -0600 |
commit | 6f8a3f93749aae35b863946d333043d4779d2b54 (patch) | |
tree | f52f7e21e78c4557fc4050958df0db03b1e2f7dc | |
parent | e1f3983bf8a548f0357a92d9023c90aa4c273f64 (diff) |
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
-rw-r--r-- | dwl.c | 47 |
1 files changed, 32 insertions, 15 deletions
@@ -194,6 +194,7 @@ struct Monitor { unsigned int sellt; uint32_t tagset[2]; double mfact; + int gamma_lut_changed; int nmaster; char ltsymbol[16]; }; @@ -1870,6 +1871,8 @@ rendermon(struct wl_listener *listener, void *data) * generally at the output's refresh rate (e.g. 60Hz). */ Monitor *m = wl_container_of(listener, m, frame); Client *c; + struct wlr_output_state pending = {0}; + struct wlr_gamma_control_v1 *gamma_control; struct timespec now; /* 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) if (c->resize && !c->isfloating && client_is_rendered_on_mon(c, m) && !client_is_stopped(c)) 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); + } skip: /* Let clients know a frame has been rendered */ clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(m->scene_output, &now); + wlr_output_state_finish(&pending); } void @@ -2057,21 +2086,9 @@ void setgamma(struct wl_listener *listener, void *data) { struct wlr_gamma_control_manager_v1_set_gamma_event *event = data; - struct wlr_output_state state; - wlr_output_state_init(&state); - if (!wlr_gamma_control_v1_apply(event->control, &state)) { - 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); + Monitor *m = event->output->data; + m->gamma_lut_changed = 1; + wlr_output_schedule_frame(m->wlr_output); } void |