diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 89240352..b3af3005 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -121,22 +121,21 @@ static void handle_session_active(struct wl_listener *listener, void *data) { struct wlr_drm_connector *conn; wl_list_for_each(conn, &drm->connectors, link) { struct wlr_output_mode *mode = NULL; - uint32_t committed = WLR_OUTPUT_STATE_ENABLED; if (conn->status != DRM_MODE_DISCONNECTED && conn->output.enabled && conn->output.current_mode != NULL) { - committed |= WLR_OUTPUT_STATE_MODE; mode = conn->output.current_mode; } - struct wlr_output_state state = { - .committed = committed, - .allow_artifacts = true, - .enabled = mode != NULL, - .mode_type = WLR_OUTPUT_STATE_MODE_FIXED, - .mode = mode, - }; + + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_enabled(&state, mode != NULL); + if (mode != NULL) { + wlr_output_state_set_mode(&state, mode); + } if (!drm_connector_commit_state(conn, &state)) { wlr_drm_conn_log(conn, WLR_ERROR, "Failed to restore state after VT switch"); } + wlr_output_state_finish(&state); } } else { wlr_log(WLR_INFO, "DRM fd paused"); diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 22bc6681..7ead82ab 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1155,16 +1155,15 @@ static void dealloc_crtc(struct wlr_drm_connector *conn) { wlr_drm_conn_log(conn, WLR_DEBUG, "De-allocating CRTC %" PRIu32, conn->crtc->id); - struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_ENABLED, - .allow_artifacts = true, - .enabled = false, - }; + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_enabled(&state, false); if (!drm_connector_commit_state(conn, &state)) { // On GPU unplug, disabling the CRTC can fail with EPERM wlr_drm_conn_log(conn, WLR_ERROR, "Failed to disable CRTC %"PRIu32, conn->crtc->id); } + wlr_output_state_finish(&state); } static void realloc_crtcs(struct wlr_drm_backend *drm, diff --git a/backend/wayland/output.c b/backend/wayland/output.c index d16b0dbc..22f61de0 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -703,12 +703,11 @@ static void xdg_toplevel_handle_configure(void *data, return; } - struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_MODE, - .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, - .custom_mode = { .width = width, .height = height }, - }; + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_custom_mode(&state, width, height, 0); wlr_output_send_request_state(&output->wlr_output, &state); + wlr_output_state_finish(&state); } static void xdg_toplevel_handle_close(void *data, diff --git a/backend/x11/output.c b/backend/x11/output.c index 517ea85b..0fd9b9c5 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -623,12 +623,11 @@ void handle_x11_configure_notify(struct wlr_x11_output *output, return; } - struct wlr_output_state state = { - .committed = WLR_OUTPUT_STATE_MODE, - .mode_type = WLR_OUTPUT_STATE_MODE_CUSTOM, - .custom_mode = { .width = ev->width, .height = ev->height }, - }; + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_custom_mode(&state, ev->width, ev->height, 0); wlr_output_send_request_state(&output->wlr_output, &state); + wlr_output_state_finish(&state); } bool wlr_output_is_x11(struct wlr_output *wlr_output) { diff --git a/examples/fullscreen-shell.c b/examples/fullscreen-shell.c index 9800a4c2..22053493 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -89,7 +89,8 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { int width, height; wlr_output_effective_resolution(output->wlr_output, &width, &height); - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &state, NULL, NULL); if (pass == NULL) { @@ -166,7 +167,8 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); diff --git a/examples/output-layers.c b/examples/output-layers.c index e6ec8150..092394f5 100644 --- a/examples/output-layers.c +++ b/examples/output-layers.c @@ -82,7 +82,8 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { }; } - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); wlr_output_state_set_layers(&output_state, layers_arr.data, layers_arr.size / sizeof(struct wlr_output_layer_state)); @@ -175,7 +176,8 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); diff --git a/examples/output-layout.c b/examples/output-layout.c index ee45c9c2..1cd7d6e9 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -114,7 +114,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct sample_state *sample = output->sample; struct wlr_output *wlr_output = output->output; - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ @@ -178,7 +179,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); diff --git a/examples/pointer.c b/examples/pointer.c index c67ce1ca..127b77f3 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -101,7 +101,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_renderer *renderer = state->renderer; assert(renderer); - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ .box = { .width = wlr_output->width, .height = wlr_output->height }, @@ -280,7 +281,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); diff --git a/examples/rotation.c b/examples/rotation.c index c7bd85ae..2770529f 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -59,7 +59,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { int32_t width, height; wlr_output_effective_resolution(wlr_output, &width, &height); - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ @@ -122,7 +123,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { sample_output->x_offs = sample_output->y_offs = 0; sample_output->x_vel = sample_output->y_vel = 128; - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_transform(&state, sample->transform); sample_output->output = output; diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 68441c11..0ea61c28 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -83,7 +83,8 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); diff --git a/examples/simple.c b/examples/simple.c index fa52bce5..533e42b5 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -62,7 +62,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { sample->dec = inc; } - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ .box = { .width = wlr_output->width, .height = wlr_output->height }, @@ -107,7 +108,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(sample_output->output, &state); wlr_output_state_finish(&state); diff --git a/examples/tablet.c b/examples/tablet.c index ee6712b1..7ac81549 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -87,7 +87,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { int32_t width, height; wlr_output_effective_resolution(wlr_output, &width, &height); - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ @@ -285,7 +286,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); diff --git a/examples/touch.c b/examples/touch.c index ab2e80ce..c054fea9 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -76,7 +76,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { int32_t width, height; wlr_output_effective_resolution(wlr_output, &width, &height); - struct wlr_output_state output_state = {0}; + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ .box = { .width = width, .height = height }, @@ -184,7 +185,8 @@ static void new_output_notify(struct wl_listener *listener, void *data) { struct wlr_output_mode *mode = wlr_output_preferred_mode(output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index ad034982..aa3d7a18 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -88,10 +88,8 @@ struct wlr_output_state { uint32_t render_format; enum wl_output_subpixel subpixel; - // only valid if WLR_OUTPUT_STATE_BUFFER struct wlr_buffer *buffer; - // only valid if WLR_OUTPUT_STATE_MODE enum wlr_output_state_mode_type mode_type; struct wlr_output_mode *mode; struct { @@ -99,11 +97,9 @@ struct wlr_output_state { int32_t refresh; // mHz, may be zero } custom_mode; - // only valid if WLR_OUTPUT_STATE_GAMMA_LUT uint16_t *gamma_lut; size_t gamma_lut_size; - // only valid if WLR_OUTPUT_STATE_LAYERS struct wlr_output_layer_state *layers; size_t layers_len; }; @@ -567,6 +563,10 @@ bool wlr_output_cursor_move(struct wlr_output_cursor *cursor, double x, double y); void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor); +/** + * Initialize an output state. + */ +void wlr_output_state_init(struct wlr_output_state *state); /** * Releases all resources associated with an output state. */ diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index e6e3ceee..80f08e70 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -603,7 +603,8 @@ static void server_new_output(struct wl_listener *listener, void *data) { * would let the user configure it. */ struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); if (mode != NULL) { - struct wlr_output_state state = {0}; + struct wlr_output_state state; + wlr_output_state_init(&state); wlr_output_state_set_mode(&state, mode); wlr_output_state_set_enabled(&state, true); if (!wlr_output_commit_state(wlr_output, &state)) { diff --git a/types/output/output.c b/types/output/output.c index 86c04474..76fa87e3 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -319,15 +319,10 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { wlr_output_destroy_global(output); } -static void output_state_init(struct wlr_output_state *state) { - memset(state, 0, sizeof(*state)); - pixman_region32_init(&state->damage); -} - static void output_state_move(struct wlr_output_state *dst, struct wlr_output_state *src) { *dst = *src; - output_state_init(src); + wlr_output_state_init(src); } void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, @@ -359,7 +354,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.description); wl_signal_init(&output->events.request_state); wl_signal_init(&output->events.destroy); - output_state_init(&output->pending); + wlr_output_state_init(&output->pending); output->software_cursor_locks = env_parse_bool("WLR_NO_HARDWARE_CURSORS"); if (output->software_cursor_locks) { diff --git a/types/output/state.c b/types/output/state.c index 7775fbb7..41610f03 100644 --- a/types/output/state.c +++ b/types/output/state.c @@ -3,20 +3,19 @@ #include #include "types/wlr_output.h" +void wlr_output_state_init(struct wlr_output_state *state) { + *state = (struct wlr_output_state){0}; + pixman_region32_init(&state->damage); +} + void wlr_output_state_finish(struct wlr_output_state *state) { - if (state->committed & WLR_OUTPUT_STATE_BUFFER) { - wlr_buffer_unlock(state->buffer); - // struct wlr_buffer is ref'counted, so the pointer may remain valid after - // wlr_buffer_unlock(). Reset the field to NULL to ensure nobody mistakenly - // reads it after output_state_finish(). - state->buffer = NULL; - } - if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { - pixman_region32_fini(&state->damage); - } - if (state->committed & WLR_OUTPUT_STATE_GAMMA_LUT) { - free(state->gamma_lut); - } + wlr_buffer_unlock(state->buffer); + // struct wlr_buffer is ref'counted, so the pointer may remain valid after + // wlr_buffer_unlock(). Reset the field to NULL to ensure nobody mistakenly + // reads it after output_state_finish(). + state->buffer = NULL; + pixman_region32_fini(&state->damage); + free(state->gamma_lut); } void wlr_output_state_set_enabled(struct wlr_output_state *state, @@ -75,23 +74,14 @@ void wlr_output_state_set_subpixel(struct wlr_output_state *state, void wlr_output_state_set_buffer(struct wlr_output_state *state, struct wlr_buffer *buffer) { - if (state->committed & WLR_OUTPUT_STATE_BUFFER) { - wlr_buffer_unlock(state->buffer); - } - state->committed |= WLR_OUTPUT_STATE_BUFFER; + wlr_buffer_unlock(state->buffer); state->buffer = wlr_buffer_lock(buffer); } void wlr_output_state_set_damage(struct wlr_output_state *state, const pixman_region32_t *damage) { - if (state->committed & WLR_OUTPUT_STATE_DAMAGE) { - pixman_region32_fini(&state->damage); - } - state->committed |= WLR_OUTPUT_STATE_DAMAGE; - - pixman_region32_init(&state->damage); pixman_region32_copy(&state->damage, damage); } @@ -99,11 +89,7 @@ bool wlr_output_state_set_gamma_lut(struct wlr_output_state *state, size_t ramp_size, const uint16_t *r, const uint16_t *g, const uint16_t *b) { uint16_t *gamma_lut = NULL; if (ramp_size > 0) { - if (state->committed & WLR_OUTPUT_STATE_GAMMA_LUT) { - gamma_lut = realloc(state->gamma_lut, 3 * ramp_size * sizeof(uint16_t)); - } else { - gamma_lut = malloc(3 * ramp_size * sizeof(uint16_t)); - } + gamma_lut = realloc(state->gamma_lut, 3 * ramp_size * sizeof(uint16_t)); if (gamma_lut == NULL) { wlr_log_errno(WLR_ERROR, "Allocation failed"); return false; @@ -112,9 +98,7 @@ bool wlr_output_state_set_gamma_lut(struct wlr_output_state *state, memcpy(gamma_lut + ramp_size, g, ramp_size * sizeof(uint16_t)); memcpy(gamma_lut + 2 * ramp_size, b, ramp_size * sizeof(uint16_t)); } else { - if (state->committed & WLR_OUTPUT_STATE_GAMMA_LUT) { - free(state->gamma_lut); - } + free(state->gamma_lut); } state->committed |= WLR_OUTPUT_STATE_GAMMA_LUT; @@ -136,6 +120,10 @@ bool wlr_output_state_copy(struct wlr_output_state *dst, copy.committed &= ~(WLR_OUTPUT_STATE_BUFFER | WLR_OUTPUT_STATE_DAMAGE | WLR_OUTPUT_STATE_GAMMA_LUT); + copy.buffer = NULL; + pixman_region32_init(©.damage); + copy.gamma_lut = NULL; + copy.gamma_lut_size = 0; if (src->committed & WLR_OUTPUT_STATE_BUFFER) { wlr_output_state_set_buffer(©, src->buffer); @@ -146,21 +134,18 @@ bool wlr_output_state_copy(struct wlr_output_state *dst, } if (src->committed & WLR_OUTPUT_STATE_GAMMA_LUT) { - size_t gamma_buffer_size = 3 * src->gamma_lut_size * sizeof(uint16_t); - copy.gamma_lut = malloc(gamma_buffer_size); - if (!copy.gamma_lut) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); + const uint16_t *r = src->gamma_lut; + const uint16_t *g = src->gamma_lut + src->gamma_lut_size; + const uint16_t *b = src->gamma_lut + 2 * src->gamma_lut_size; + if (!wlr_output_state_set_gamma_lut(©, src->gamma_lut_size, r, g, b)) { goto err; } - - copy.committed |= WLR_OUTPUT_STATE_GAMMA_LUT; - memcpy(copy.gamma_lut, src->gamma_lut, gamma_buffer_size); - copy.gamma_lut_size = src->gamma_lut_size; } wlr_output_state_finish(dst); *dst = copy; return true; + err: wlr_output_state_finish(©); return false; diff --git a/types/output/swapchain.c b/types/output/swapchain.c index 0b0c6a8b..5a16610d 100644 --- a/types/output/swapchain.c +++ b/types/output/swapchain.c @@ -65,8 +65,9 @@ static bool test_swapchain(struct wlr_output *output, bool wlr_output_configure_primary_swapchain(struct wlr_output *output, const struct wlr_output_state *state, struct wlr_swapchain **swapchain_ptr) { - const struct wlr_output_state empty_state = {0}; + struct wlr_output_state empty_state; if (state == NULL) { + wlr_output_state_init(&empty_state); state = &empty_state; } diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 0e200fcf..ab5cd91f 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1534,7 +1534,8 @@ static bool scene_buffer_can_consider_direct_scanout(struct wlr_scene_buffer *bu static bool scene_buffer_try_direct_scanout(struct wlr_scene_buffer *buffer, struct wlr_scene_output *scene_output, struct wlr_output_state *state) { - struct wlr_output_state pending = {0}; + struct wlr_output_state pending; + wlr_output_state_init(&pending); if (!wlr_output_state_copy(&pending, state)) { return false; } @@ -1564,19 +1565,23 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { return true; } - struct wlr_output_state state = {0}; + bool ok = false; + struct wlr_output_state state; + wlr_output_state_init(&state); if (!wlr_scene_output_build_state(scene_output, &state)) { - return false; + goto out; } - bool success = wlr_output_commit_state(scene_output->output, &state); - wlr_output_state_finish(&state); - - if (success) { - wlr_damage_ring_rotate(&scene_output->damage_ring); + ok = wlr_output_commit_state(scene_output->output, &state); + if (!ok) { + goto out; } - return success; + wlr_damage_ring_rotate(&scene_output->damage_ring); + +out: + wlr_output_state_finish(&state); + return ok; } bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,