output: atomic mode, enabled, scale and transform

This commit makes more output properties (mode, enabled, scale and transform)
atomic. This means that they are double-buffered and only applied on commit.

Compositors now need to call wlr_output_commit after setting any of those
properties.

Internally, backends still apply properties sequentially. The behaviour should
be exactly the same as before. Future commits will update some backends to take
advantage of the atomic interface. Some backends are non-atomic by design, e.g.
the X11 backend or the legacy DRM backend.

Updates: https://github.com/swaywm/wlroots/issues/1640
This commit is contained in:
Simon Ser 2019-07-18 21:38:12 +03:00 committed by Drew DeVault
parent d20aee6c9d
commit ee5f98ad49
10 changed files with 291 additions and 114 deletions

View file

@ -63,26 +63,44 @@ static bool output_commit(struct wlr_output *wlr_output) {
struct wlr_wl_output *output =
get_wl_output_from_output(wlr_output);
if (output->frame_callback != NULL) {
wlr_log(WLR_ERROR, "Skipping buffer swap");
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) {
wlr_log(WLR_DEBUG, "Cannot disable a Wayland output");
return false;
}
output->frame_callback = wl_surface_frame(output->surface);
wl_callback_add_listener(output->frame_callback, &frame_listener, output);
pixman_region32_t *damage = NULL;
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
damage = &wlr_output->pending.damage;
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
if (!output_set_custom_mode(wlr_output,
wlr_output->pending.custom_mode.width,
wlr_output->pending.custom_mode.height,
wlr_output->pending.custom_mode.refresh)) {
return false;
}
}
if (!wlr_egl_swap_buffers(&output->backend->egl,
output->egl_surface, damage)) {
return false;
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
if (output->frame_callback != NULL) {
wlr_log(WLR_ERROR, "Skipping buffer swap");
return false;
}
output->frame_callback = wl_surface_frame(output->surface);
wl_callback_add_listener(output->frame_callback, &frame_listener, output);
pixman_region32_t *damage = NULL;
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
damage = &wlr_output->pending.damage;
}
if (!wlr_egl_swap_buffers(&output->backend->egl,
output->egl_surface, damage)) {
return false;
}
// TODO: if available, use the presentation-time protocol
wlr_output_send_present(wlr_output, NULL);
}
// TODO: if available, use the presentation-time protocol
wlr_output_send_present(wlr_output, NULL);
return true;
}
@ -219,7 +237,6 @@ static bool output_schedule_frame(struct wlr_output *wlr_output) {
}
static const struct wlr_output_impl output_impl = {
.set_custom_mode = output_set_custom_mode,
.destroy = output_destroy,
.attach_render = output_attach_render,
.commit = output_commit,