+static void
+_tdm_server_output_cb_get_dpms(struct wl_client *client, struct wl_resource *resource)
+{
+ tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_error ret;
+
+ TDM_RETURN_IF_FAIL(output_info != NULL);
+
+ ret = tdm_output_get_conn_status(output_info->output, &status);
+ TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed);
+
+ if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+ tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF;
+
+ ret = tdm_output_get_dpms(output_info->output, &dpms_value);
+ TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, failed);
+
+ wl_tdm_output_send_dpms(output_info->resource, dpms_value, ret);
+ } else {
+ wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF, TDM_ERROR_OUTPUT_DISCONNECTED);
+ }
+
+ return;
+failed:
+ wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF, ret);
+}
+
+static const struct wl_tdm_output_interface tdm_output_implementation = {
+ _tdm_server_output_cb_destroy,
+ _tdm_server_output_cb_create_vblank,
+ _tdm_server_output_cb_watch_output_changes,
+ _tdm_server_output_cb_get_connection,
+ _tdm_server_output_cb_get_mode,
+ _tdm_server_output_cb_get_dpms,
+};
+
+static void
+destroy_output_callback(struct wl_resource *resource)
+{
+ tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+ tdm_server_vblank_info *v = NULL, *vv = NULL;
+
+ TDM_RETURN_IF_FAIL(output_info != NULL);
+
+ LIST_DEL(&output_info->link);
+
+ tdm_output_remove_change_handler(output_info->output,
+ _tdm_server_cb_output_change, output_info);
+
+ LIST_FOR_EACH_ENTRY_SAFE(v, vv, &output_info->vblank_list, link) {
+ wl_resource_destroy(v->resource);
+ }
+
+ free(output_info);
+}
+
+static void
+_tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resource,
+ const char *name, uint32_t id)
+{
+ tdm_private_server *private_server = wl_resource_get_user_data(resource);
+ tdm_server_output_info *output_info;
+ struct wl_resource *output_resource = NULL;
+ tdm_output *output;
+ tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ tdm_error ret;
+
+ output = tdm_display_find_output(private_server->private_loop->dpy, name, NULL);
+ if (!output) {
+ /* LCOV_EXCL_START */
+
+ TDM_ERR("There is no '%s' output", name);
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "There is no '%s' output", name);
+ return;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ output_resource =
+ wl_resource_create(client, &wl_tdm_output_interface,
+ wl_resource_get_version(resource), id);
+ if (!output_resource) {
+ /* LCOV_EXCL_START */
+
+ wl_resource_post_no_memory(resource);
+ TDM_ERR("wl_resource_create failed");
+ return;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ output_info = calloc(1, sizeof * output_info);
+ if (!output_info) {
+ /* LCOV_EXCL_START */
+
+ wl_resource_post_no_memory(resource);
+ wl_resource_destroy(output_resource);
+ TDM_ERR("alloc failed");
+ return;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = tdm_output_add_change_handler(output, _tdm_server_cb_output_change, output_info);