diff --git a/output.c b/output.c index 5ccc939..093836b 100644 --- a/output.c +++ b/output.c @@ -21,12 +21,14 @@ #if WLR_HAS_X11_BACKEND #include #endif +#include #include #include #include #include #include #include +#include #include #include #include @@ -130,31 +132,6 @@ output_disable(struct cg_output *output) output_layout_remove(output); } -static bool -output_apply_config(struct cg_output *output, struct wlr_output_configuration_head_v1 *head, bool test_only) -{ - struct wlr_output_state state = {0}; - wlr_output_head_v1_state_apply(&head->state, &state); - - if (test_only) { - bool ret = wlr_output_test_state(output->wlr_output, &state); - return ret; - } - - /* Apply output configuration */ - if (!wlr_output_commit_state(output->wlr_output, &state)) { - return false; - } - - if (head->state.enabled) { - output_layout_add(output, head->state.x, head->state.y); - } else { - output_layout_remove(output); - } - - return true; -} - static void handle_output_frame(struct wl_listener *listener, void *data) { @@ -355,17 +332,63 @@ output_set_window_title(struct cg_output *output, const char *title) static bool output_config_apply(struct cg_server *server, struct wlr_output_configuration_v1 *config, bool test_only) { - struct wlr_output_configuration_head_v1 *head; + bool ok = false; - wl_list_for_each (head, &config->heads, link) { - struct cg_output *output = head->state.output->data; + size_t states_len; + struct wlr_backend_output_state *states = wlr_output_configuration_v1_build_state(config, &states_len); + if (states == NULL) { + return false; + } - if (!output_apply_config(output, head, test_only)) { - return false; + struct wlr_output_swapchain_manager swapchain_manager; + wlr_output_swapchain_manager_init(&swapchain_manager, server->backend); + + ok = wlr_output_swapchain_manager_prepare(&swapchain_manager, states, states_len); + if (!ok || test_only) { + goto out; + } + + for (size_t i = 0; i < states_len; i++) { + struct wlr_backend_output_state *backend_state = &states[i]; + struct cg_output *output = backend_state->output->data; + + struct wlr_swapchain *swapchain = + wlr_output_swapchain_manager_get_swapchain(&swapchain_manager, backend_state->output); + struct wlr_scene_output_state_options options = { + .swapchain = swapchain, + }; + struct wlr_output_state *state = &backend_state->base; + if (!wlr_scene_output_build_state(output->scene_output, state, &options)) { + ok = false; + goto out; } } - return true; + ok = wlr_backend_commit(server->backend, states, states_len); + if (!ok) { + goto out; + } + + wlr_output_swapchain_manager_apply(&swapchain_manager); + + struct wlr_output_configuration_head_v1 *head; + wl_list_for_each (head, &config->heads, link) { + struct cg_output *output = head->state.output->data; + + if (head->state.enabled) { + output_layout_add(output, head->state.x, head->state.y); + } else { + output_layout_remove(output); + } + } + +out: + wlr_output_swapchain_manager_finish(&swapchain_manager); + for (size_t i = 0; i < states_len; i++) { + wlr_output_state_finish(&states[i].base); + } + free(states); + return ok; } void