From e04115898892129977a44e76aa39103a2bdd2144 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 2 Apr 2020 12:41:19 +0200 Subject: [PATCH] output: introduce wlr_output_test --- backend/drm/drm.c | 11 +++++- backend/headless/output.c | 13 ++++++- backend/wayland/output.c | 18 ++++++++-- backend/x11/output.c | 18 ++++++++-- include/wlr/interfaces/wlr_output.h | 1 + include/wlr/types/wlr_output.h | 8 +++++ types/wlr_output.c | 53 ++++++++++++++++++----------- 7 files changed, 94 insertions(+), 28 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d845a888..53d49d17 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -334,6 +334,10 @@ static bool drm_connector_attach_render(struct wlr_output *output, return make_drm_surface_current(&conn->crtc->primary->surf, buffer_age); } +static bool drm_connector_test(struct wlr_output *output) { + return true; +} + static bool drm_connector_commit_buffer(struct wlr_output *output) { struct wlr_drm_connector *conn = get_drm_connector_from_output(output); struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend); @@ -455,6 +459,10 @@ static bool drm_connector_set_custom_mode(struct wlr_output *output, static bool drm_connector_commit(struct wlr_output *output) { struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend); + if (!drm_connector_test(output)) { + return false; + } + if (!drm->session->active) { return false; } @@ -501,7 +509,7 @@ static bool drm_connector_commit(struct wlr_output *output) { static void fill_empty_gamma_table(size_t size, uint16_t *r, uint16_t *g, uint16_t *b) { - assert(0xFFFF < UINT64_MAX / (size - 1)); + assert(0xFFFF < UINT64_MAX / (size - 1)); for (uint32_t i = 0; i < size; ++i) { uint16_t val = (uint64_t)0xffff * i / (size - 1); r[i] = g[i] = b[i] = val; @@ -1068,6 +1076,7 @@ static const struct wlr_output_impl output_impl = { .move_cursor = drm_connector_move_cursor, .destroy = drm_connector_destroy, .attach_render = drm_connector_attach_render, + .test = drm_connector_test, .commit = drm_connector_commit, .set_gamma = set_drm_connector_gamma, .get_gamma_size = drm_connector_get_gamma_size, diff --git a/backend/headless/output.c b/backend/headless/output.c index a2836159..326c9605 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -57,7 +57,7 @@ static bool output_attach_render(struct wlr_output *wlr_output, buffer_age); } -static bool output_commit(struct wlr_output *wlr_output) { +static bool output_test(struct wlr_output *wlr_output) { if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { wlr_log(WLR_DEBUG, "Cannot disable a headless output"); return false; @@ -65,6 +65,17 @@ static bool output_commit(struct wlr_output *wlr_output) { if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + } + + return true; +} + +static bool output_commit(struct wlr_output *wlr_output) { + if (!output_test(wlr_output)) { + return false; + } + + if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { if (!output_set_custom_mode(wlr_output, wlr_output->pending.custom_mode.width, wlr_output->pending.custom_mode.height, diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 1f00209b..1a1835e1 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -197,17 +197,28 @@ static bool output_attach_buffer(struct wlr_output *wlr_output, return true; } +static bool output_test(struct wlr_output *wlr_output) { + if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { + wlr_log(WLR_DEBUG, "Cannot disable a Wayland output"); + return false; + } + + if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { + assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + } + + return true; +} + static bool output_commit(struct wlr_output *wlr_output) { struct wlr_wl_output *output = get_wl_output_from_output(wlr_output); - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { - wlr_log(WLR_DEBUG, "Cannot disable a Wayland output"); + if (!output_test(wlr_output)) { return false; } 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, @@ -419,6 +430,7 @@ static const struct wlr_output_impl output_impl = { .destroy = output_destroy, .attach_render = output_attach_render, .attach_buffer = output_attach_buffer, + .test = output_test, .commit = output_commit, .set_cursor = output_set_cursor, .move_cursor = output_move_cursor, diff --git a/backend/x11/output.c b/backend/x11/output.c index 9d184c48..6546c23e 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -99,17 +99,28 @@ static bool output_attach_render(struct wlr_output *wlr_output, return wlr_egl_make_current(&x11->egl, output->surf, buffer_age); } +static bool output_test(struct wlr_output *wlr_output) { + if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { + wlr_log(WLR_DEBUG, "Cannot disable an X11 output"); + return false; + } + + if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) { + assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM); + } + + return true; +} + static bool output_commit(struct wlr_output *wlr_output) { struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); struct wlr_x11_backend *x11 = output->x11; - if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ENABLED) { - wlr_log(WLR_DEBUG, "Cannot disable an X11 output"); + if (!output_test(wlr_output)) { return false; } 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, @@ -152,6 +163,7 @@ static bool output_commit(struct wlr_output *wlr_output) { static const struct wlr_output_impl output_impl = { .destroy = output_destroy, .attach_render = output_attach_render, + .test = output_test, .commit = output_commit, }; diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 12980ee5..c99d0c93 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -21,6 +21,7 @@ struct wlr_output_impl { bool (*move_cursor)(struct wlr_output *output, int x, int y); void (*destroy)(struct wlr_output *output); bool (*attach_render)(struct wlr_output *output, int *buffer_age); + bool (*test)(struct wlr_output *output); bool (*commit)(struct wlr_output *output); bool (*set_gamma)(struct wlr_output *output, size_t size, const uint16_t *r, const uint16_t *g, const uint16_t *b); diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 3b7f7ee3..0e2954b9 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -337,6 +337,14 @@ bool wlr_output_preferred_read_format(struct wlr_output *output, */ void wlr_output_set_damage(struct wlr_output *output, pixman_region32_t *damage); +/** + * Test whether the pending output state would be accepted by the backend. If + * this function returns true, `wlr_output_commit` can only fail due to a + * runtime error. + * + * This function doesn't mutate the pending state. + */ +bool wlr_output_test(struct wlr_output *output); /** * Commit the pending output state. If `wlr_output_attach_render` has been * called, the pending frame will be submitted for display and a `frame` event diff --git a/types/wlr_output.c b/types/wlr_output.c index 1692a2a0..38df4c9f 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -473,16 +473,11 @@ static void output_state_clear(struct wlr_output_state *state) { state->committed = 0; } -bool wlr_output_commit(struct wlr_output *output) { - if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { - if (output->frame_pending) { - wlr_log(WLR_ERROR, "Tried to commit a buffer while a frame is pending"); - goto error; - } - if (output->idle_frame != NULL) { - wl_event_source_remove(output->idle_frame); - output->idle_frame = NULL; - } +static bool output_basic_test(struct wlr_output *output) { + if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) && + output->frame_pending) { + wlr_log(WLR_DEBUG, "Tried to commit a buffer while a frame is pending"); + return false; } bool enabled = output->enabled; @@ -491,16 +486,38 @@ bool wlr_output_commit(struct wlr_output *output) { } if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { - wlr_log(WLR_ERROR, "Tried to commit a buffer on a disabled output"); - goto error; + wlr_log(WLR_DEBUG, "Tried to commit a buffer on a disabled output"); + return false; } if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_MODE) { - wlr_log(WLR_ERROR, "Tried to modeset a disabled output"); - goto error; + wlr_log(WLR_DEBUG, "Tried to modeset a disabled output"); + return false; } if (!enabled && output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) { - wlr_log(WLR_ERROR, "Tried to enable adaptive sync on a disabled output"); - goto error; + wlr_log(WLR_DEBUG, "Tried to enable adaptive sync on a disabled output"); + return false; + } + + return true; +} + +bool wlr_output_test(struct wlr_output *output) { + if (!output_basic_test(output)) { + return false; + } + return output->impl->test(output); +} + +bool wlr_output_commit(struct wlr_output *output) { + if (!output_basic_test(output)) { + wlr_log(WLR_ERROR, "Basic output test failed"); + return false; + } + + if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) && + output->idle_frame != NULL) { + wl_event_source_remove(output->idle_frame); + output->idle_frame = NULL; } struct timespec now; @@ -565,10 +582,6 @@ bool wlr_output_commit(struct wlr_output *output) { output_state_clear(&output->pending); return true; - -error: - output_state_clear(&output->pending); - return false; } void wlr_output_rollback(struct wlr_output *output) {