From 52eca1efc87b46a754e8d0de7445d1e84061ced6 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 1 Aug 2018 21:34:57 +0900 Subject: [PATCH] virtual: add protocol to share wl_buffer(tbm_surface) with tdm_client Change-Id: I5066e0a66230b309dc55101276885445ed7968a1 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 1 + configure.ac | 2 +- packaging/libtdm.spec | 1 + protocol/tdm.xml | 42 ++++++++ src/tdm_private.h | 2 + src/tdm_server.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 596 insertions(+), 5 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 92b1626..53434f1 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -33,6 +33,8 @@ * **************************************************************************/ +#define WL_HIDE_DEPRECATED + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -53,6 +55,8 @@ #include "tdm.h" #include "tdm_private.h" +#define TDM_ARRAY_NTH_DATA(array, type, n) (((type*)((array)->data)) + n) + typedef struct _tdm_private_client_vblank tdm_private_client_vblank; typedef struct _tdm_private_client { @@ -89,6 +93,11 @@ typedef struct _tdm_private_client_output { struct list_head link; } tdm_private_client_output; +typedef struct _tdm_private_client_buffer { + struct list_head link; + struct wl_buffer *wl_buffer; +} tdm_private_client_buffer; + typedef struct _tdm_private_client_voutput { tdm_private_client_output base; struct wl_tdm_voutput *wl_voutput; @@ -104,6 +113,10 @@ typedef struct _tdm_private_client_voutput { unsigned int mmheight; uint32_t msg; + + struct list_head buffer_list; + tbm_bufmgr bufmgr; + tdm_private_client_buffer *commit_buffer; } tdm_private_client_voutput; struct _tdm_private_client_vblank { @@ -1620,6 +1633,223 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank) return (LIST_LENGTH(&private_vblank->wait_list) > 0) ? 1 : 0; } +static tbm_surface_h +_tdm_client_voutput_create_surface_from_param(tbm_bufmgr bufmgr, + int is_fd, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + uint32_t buf0, + uint32_t buf1, + uint32_t buf2) +{ + int32_t names[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1}; + tbm_surface_info_s info = { 0, }; + tbm_bo bos[TBM_SURF_PLANE_MAX]; + int i, numPlane, numName; + tbm_surface_h tbm_surface; + + numPlane = tbm_surface_internal_get_num_planes(format); + TDM_RETURN_VAL_IF_FAIL(numPlane == num_plane, NULL); + + info.width = width; + info.height = height; + info.format = format; + info.bpp = bpp; + info.size = size; + info.num_planes = numPlane; + + /*Fill plane info*/ + for (i = 0; i < numPlane; i++) { + info.planes[i].offset = *TDM_ARRAY_NTH_DATA(plane_offset, int32_t, i); + info.planes[i].stride = *TDM_ARRAY_NTH_DATA(plane_stride, int32_t, i); + info.planes[i].size = *TDM_ARRAY_NTH_DATA(plane_size, int32_t, i); + } + + /*Fill buffer*/ + numName = num_buf; + names[0] = buf0; + names[1] = buf1; + names[2] = buf2; + + for (i = 0; i < numName; i++) { + if (is_fd) + bos[i] = tbm_bo_import_fd(bufmgr, names[i]); + else + bos[i] = tbm_bo_import(bufmgr, names[i]); + } + + tbm_surface = tbm_surface_internal_create_with_bos(&info, bos, numName); + if (tbm_surface == NULL) { + if (is_fd) { + close(buf0); + close(buf1); + close(buf2); + } + return NULL; + } + + if (is_fd) { + close(buf0); + close(buf1); + close(buf2); + } + + for (i = 0; i < numName; i++) + tbm_bo_unref(bos[i]); + + return tbm_surface; +} +static void +tdm_client_voutput_cb_buffer_import_with_id(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + uint32_t buf0, + uint32_t buf1, + uint32_t buf2) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *buffer = NULL; + tbm_surface_h tbm_surface; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + buffer = calloc(1, sizeof *buffer); + TDM_RETURN_IF_FAIL(buffer != NULL); + + tbm_surface = _tdm_client_voutput_create_surface_from_param(private_voutput->bufmgr, 0, + width, height, format, bpp, size, + num_plane, + plane_buf_idx, plane_offset, plane_stride, plane_size, + 0, + num_buf, + buf0, buf1, buf2); + TDM_GOTO_IF_FAIL(tbm_surface != NULL, fail); + + tbm_surface_internal_ref(tbm_surface); + wl_buffer_set_user_data(wl_buffer, tbm_surface); + + buffer->wl_buffer = wl_buffer; + + LIST_ADDTAIL(&buffer->link, &private_voutput->buffer_list); + + return; + +fail: + if (buffer) + free(buffer); + + if (wl_buffer) + wl_buffer_destroy(wl_buffer); +} + +static void +tdm_client_voutput_cb_buffer_import_with_fd(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer, + int32_t width, + int32_t height, + uint32_t format, + int32_t bpp, + int32_t size, + int32_t num_plane, + struct wl_array *plane_buf_idx, + struct wl_array *plane_offset, + struct wl_array *plane_stride, + struct wl_array *plane_size, + uint32_t flags, + int32_t num_buf, + int32_t buf0, + int32_t buf1, + int32_t buf2) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *buffer = NULL; + tbm_surface_h tbm_surface; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + buffer = calloc(1, sizeof *buffer); + TDM_RETURN_IF_FAIL(buffer != NULL); + + tbm_surface = _tdm_client_voutput_create_surface_from_param(private_voutput->bufmgr, 1, + width, height, format, bpp, size, + num_plane, + plane_buf_idx, plane_offset, plane_stride, plane_size, + 0, + num_buf, + buf0, buf1, buf2); + TDM_GOTO_IF_FAIL(tbm_surface != NULL, fail); + + tbm_surface_internal_ref(tbm_surface); + wl_buffer_set_user_data(wl_buffer, tbm_surface); + + buffer->wl_buffer = wl_buffer; + + LIST_ADDTAIL(&buffer->link, &private_voutput->buffer_list); + + return; + +fail: + if (buffer) + free(buffer); + + if (wl_buffer) + wl_buffer_destroy(wl_buffer); +} + +static void +tdm_client_voutput_cb_buffer_destroy(void *data, + struct wl_tdm_voutput *wl_voutput, + struct wl_buffer *wl_buffer) +{ + tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)data; + tdm_private_client_buffer *cb = NULL, *cbb = NULL; + tbm_surface_h tbm_surface = NULL; + + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + LIST_FOR_EACH_ENTRY_SAFE(cb, cbb, &private_voutput->buffer_list, link) { + if (wl_buffer == cb->wl_buffer) { + LIST_DEL(&cb->link); + + tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(wl_buffer); + if (tbm_surface) + tbm_surface_internal_unref(tbm_surface); + + wl_buffer_set_user_data(wl_buffer, NULL); + wl_buffer_destroy(wl_buffer); + + free(cb); + + break; + } + } + + return; +} + void tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) { @@ -1656,6 +1886,9 @@ tdm_client_voutput_cb_ack_message(void *data, struct wl_tdm_voutput *wl_voutput, } static const struct wl_tdm_voutput_listener tdm_client_voutput_lisntener = { + tdm_client_voutput_cb_buffer_import_with_id, + tdm_client_voutput_cb_buffer_import_with_fd, + tdm_client_voutput_cb_buffer_destroy, tdm_client_voutput_cb_commit, tdm_client_voutput_cb_ack_message }; @@ -1723,11 +1956,25 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); return NULL; /* LOCV_EXCL_STOP */ } + private_voutput->bufmgr = tbm_bufmgr_init(-1); + if (private_voutput->bufmgr == NULL) { + /* LCOV_EXCL_START */ + TDM_ERR("fail tbm_bufmgr_init"); + free(private_voutput); + if (error) + *error = TDM_ERROR_OUT_OF_MEMORY; + pthread_mutex_unlock(&private_client->lock); + return NULL; + /* LCOV_EXCL_STOP */ + } + LIST_INITHEAD(&private_voutput->commit_handler_list); + LIST_INITHEAD(&private_voutput->buffer_list); private_voutput->base.private_client = private_client; @@ -1783,6 +2030,30 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (!private_voutput) return; + if (!(LIST_IS_EMPTY(&private_voutput->buffer_list))) { + tdm_private_client_buffer *cb = NULL, *cbb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(cb, cbb, &private_voutput->buffer_list, link) { + tbm_surface_h tbm_surface = NULL; + + if (!cb) continue; + + LIST_DEL(&cb->link); + + tbm_surface = (tbm_surface_h)wl_buffer_get_user_data(cb->wl_buffer); + if (tbm_surface) + tbm_surface_internal_unref(tbm_surface); + + wl_buffer_set_user_data(cb->wl_buffer, NULL); + wl_buffer_destroy(cb->wl_buffer); + + free(cb); + } + } + + if (private_voutput->bufmgr) + tbm_bufmgr_deinit(private_voutput->bufmgr); + if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); diff --git a/client/tdm_client.h b/client/tdm_client.h index f431f1c..420c5e2 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -431,6 +431,7 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank); /* Virtual Output */ #include +#include tdm_client_voutput * tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error); diff --git a/configure.ac b/configure.ac index 81d3828..51ceb3c 100644 --- a/configure.ac +++ b/configure.ac @@ -45,7 +45,7 @@ fi PKG_CHECK_MODULES(WAYLAND_SCANNER, wayland-scanner >= 1.7.0) PKG_CHECK_MODULES(TDM, dlog libtbm libpng pixman-1 wayland-server iniparser) -PKG_CHECK_MODULES(TDM_CLIENT, dlog wayland-client) +PKG_CHECK_MODULES(TDM_CLIENT, dlog libtbm wayland-client) PKG_CHECK_MODULES(TTRACE, [ttrace], diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index c915e01..ada8f04 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -13,6 +13,7 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(libpng) BuildRequires: pkgconfig(ttrace) BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(pixman-1) BuildRequires: gtest-devel diff --git a/protocol/tdm.xml b/protocol/tdm.xml index b1d6699..20ba4cd 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -92,6 +92,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tdm_private.h b/src/tdm_private.h index 02464d8..fea8715 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -268,6 +268,8 @@ tdm_error tdm_output_set_connect(tdm_output *output); tdm_error tdm_output_set_disconnect(tdm_output *output); +tdm_error +tdm_output_send_buffer(tdm_output *output, tbm_surface_h tbm_surface); #ifdef __cplusplus } diff --git a/src/tdm_server.c b/src/tdm_server.c index c86de65..bf38211 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -37,6 +37,8 @@ #include "config.h" #endif +#define WL_HIDE_DEPRECATED + #include #include "tdm_private.h" @@ -66,6 +68,12 @@ typedef struct _tdm_server_output_info { unsigned int watch_output_changes; } tdm_server_output_info; +typedef struct _tdm_server_voutput_buffer { + struct list_head link; + struct wl_resource *wl_buffer; + tbm_surface_h surface; +} tdm_server_voutput_buffer; + typedef struct _tdm_server_voutput_info { struct list_head link; tdm_private_server *private_server; @@ -82,6 +90,9 @@ typedef struct _tdm_server_voutput_info { unsigned int mmwidth; unsigned int mmheight; + + struct list_head buffer_list; + tdm_server_voutput_buffer *attach_buffer; } tdm_server_voutput_info; typedef struct _tdm_server_vblank_info { @@ -813,13 +824,275 @@ static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_commit_done }; +static void +_tdm_voutput_wl_buffer_destroy(struct wl_client *client, struct wl_resource *wl_buffer) +{ + wl_resource_destroy(wl_buffer); +} + +static const struct wl_buffer_interface _tdm_voutput_buffer_impementation = { + _tdm_voutput_wl_buffer_destroy +}; + +static void +_tdm_voutput_buffer_destory(struct wl_resource *wl_buffer) +{ + tdm_server_voutput_info *voutput_info = NULL; + tdm_server_voutput_buffer *vb = NULL; + + voutput_info = (tdm_server_voutput_info *)wl_resource_get_user_data(wl_buffer); + TDM_RETURN_IF_FAIL(voutput_info != NULL); + + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { + if (vb->wl_buffer == wl_buffer) { + tbm_surface_internal_unref(vb->surface); + wl_resource_set_user_data(wl_buffer, NULL); + free(vb); + } + } +} + +struct wl_resource * +_tdm_voutput_create_wl_buffer(tdm_server_voutput_info *voutput_info) +{ + struct wl_client *wl_client; + struct wl_resource *wl_buffer = NULL; + + wl_client = wl_resource_get_client(voutput_info->resource); + + /* create a wl_buffer resource */ + wl_buffer = wl_resource_create(wl_client, &wl_buffer_interface, 1, 0); + TDM_RETURN_VAL_IF_FAIL(wl_buffer != NULL, NULL); + + wl_resource_set_implementation(wl_buffer, + (void (**)(void)) &_tdm_voutput_buffer_impementation, + voutput_info, _tdm_voutput_buffer_destory); + + return wl_buffer; +} + +struct wl_resource * +_tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, + tbm_surface_h surface) +{ + int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1}; + struct wl_resource *wl_buffer = NULL; + int num_buf, is_fd = -1, i; + tbm_surface_info_s info; + uint32_t flags = 0; + struct wl_array plane_buf_idx, plane_offset, plane_stride, plane_size; + int *p; + + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, NULL); + TDM_RETURN_VAL_IF_FAIL(surface != NULL, NULL); + + if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) { + TDM_ERR("Failed to create buffer from surface"); + return NULL; + } + + if (info.num_planes > 3) { + TDM_ERR("invalid num_planes(%d)", info.num_planes); + return NULL; + } + + num_buf = tbm_surface_internal_get_num_bos(surface); + if (num_buf == 0) { + TDM_ERR("surface doesn't have any bo."); + return NULL; + } + + for (i = 0; i < num_buf; i++) { + tbm_bo bo = tbm_surface_internal_get_bo(surface, i); + if (bo == NULL) { + TDM_ERR("Failed to get bo from surface"); + goto err; + } + + /* try to get fd first */ + if (is_fd == -1 || is_fd == 1) { + bufs[i] = tbm_bo_export_fd(bo); + if (is_fd == -1 && bufs[i] >= 0) + is_fd = 1; + } + + /* if fail to get fd, try to get name second */ + if (is_fd == -1 || is_fd == 0) { + bufs[i] = tbm_bo_export(bo); + if (is_fd == -1 && bufs[i] > 0) + is_fd = 0; + } + + if (is_fd == -1 || + (is_fd == 1 && bufs[i] < 0) || + (is_fd == 0 && bufs[i] <= 0)) { + TDM_ERR("Failed to export(is_fd:%d, bufs:%d)", is_fd, bufs[i]); + goto err; + } + } + + wl_buffer = _tdm_voutput_create_wl_buffer(voutput_info); + if (!wl_buffer) { + TDM_ERR("Failed to create wl_buffer"); + goto err; + } + + wl_array_init(&plane_buf_idx); + wl_array_init(&plane_offset); + wl_array_init(&plane_stride); + wl_array_init(&plane_size); + + for (i = 0; i < 3; i++) { + p = wl_array_add(&plane_buf_idx, sizeof(int)); + *p = tbm_surface_internal_get_plane_bo_idx(surface, i); + p = wl_array_add(&plane_offset, sizeof(int)); + *p = info.planes[i].offset; + p = wl_array_add(&plane_stride, sizeof(int)); + *p = info.planes[i].stride; + p = wl_array_add(&plane_size, sizeof(int)); + *p = info.planes[i].size; + } + + if (is_fd == 1) + wl_tdm_voutput_send_buffer_set_with_fd(voutput_info->resource, + wl_buffer, + info.width, info.height, info.format, info.bpp, info.size, info.num_planes, + &plane_buf_idx, &plane_offset, &plane_stride, &plane_size, + flags, num_buf, bufs[0], + (bufs[1] == -1) ? bufs[0] : bufs[1], + (bufs[2] == -1) ? bufs[0] : bufs[2]); + else + wl_tdm_voutput_send_buffer_set_with_id(voutput_info->resource, + wl_buffer, + info.width, info.height, info.format, info.bpp, info.size, info.num_planes, + &plane_buf_idx, &plane_offset, &plane_stride, &plane_size, + flags, + num_buf, bufs[0], bufs[1], bufs[2]); + + wl_array_release(&plane_buf_idx); + wl_array_release(&plane_offset); + wl_array_release(&plane_stride); + wl_array_release(&plane_size); + + for (i = 0; i < TBM_SURF_PLANE_MAX; i++) { + if (is_fd == 1 && (bufs[i] >= 0)) + close(bufs[i]); + } + + return wl_buffer; + +err: + for (i = 0; i < TBM_SURF_PLANE_MAX; i++) { + if (is_fd == 1 && (bufs[i] >= 0)) + close(bufs[i]); + } + + return NULL; +} + +tdm_server_voutput_buffer * +_tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surface_h surface) +{ + tdm_server_voutput_buffer *voutput_buffer = NULL, *vb = NULL; + + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { + if (vb && vb->surface == surface) + return vb; + } + + tbm_surface_internal_ref(surface); + voutput_buffer = calloc(1, sizeof *voutput_buffer); + if (!voutput_buffer) { + /* LCOV_EXCL_START */ + + TDM_ERR("fail calloc"); + tbm_surface_internal_unref(surface); + return NULL; + + /* LCOV_EXCL_STOP */ + } + + voutput_buffer->wl_buffer = _tdm_voutput_export_buffer(voutput_info, surface); + if (!voutput_buffer->wl_buffer) { + /* LCOV_EXCL_START */ + + TDM_ERR("fail export buffer"); + free(voutput_buffer); + tbm_surface_internal_unref(surface); + return NULL; + + /* LCOV_EXCL_STOP */ + } + + voutput_buffer->surface = surface; + LIST_ADDTAIL(&voutput_info->link, &voutput_info->buffer_list); + + return voutput_buffer; +} + +tdm_error +tdm_output_send_buffer(tdm_output *output, tbm_surface_h surface) +{ + tdm_private_server *private_server = keep_private_server; + tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; + tdm_server_voutput_buffer *voutput_buffer = NULL; + + TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED); + + LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) { + if (vo && vo->output == output) { + voutput_info = vo; + break; + } + } + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER); + + voutput_buffer = _tdm_output_get_voutput_buffer(voutput_info, surface); + TDM_RETURN_VAL_IF_FAIL(voutput_buffer != NULL, TDM_ERROR_OUT_OF_MEMORY); + + voutput_info->attach_buffer = voutput_buffer; + + return TDM_ERROR_NONE; +} + +tdm_error +tdm_output_commit_buffer(tdm_output *output) +{ + tdm_private_server *private_server = keep_private_server; + tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; + + TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED); + + LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) { + if (vo && vo->output == output) { + voutput_info = vo; + break; + } + } + TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + + wl_tdm_voutput_send_commit(voutput_info->resource); + + return TDM_ERROR_NONE; +} + void tdm_voutput_cb_resource_destroy(struct wl_resource *resource) { tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource); - + tdm_server_voutput_buffer *vb, *vbb; TDM_RETURN_IF_FAIL(voutput_info != NULL); + LIST_FOR_EACH_ENTRY_SAFE(vb, vbb, &voutput_info->buffer_list, link) { + if (!vb) continue; + + LIST_DEL(&vb->link); + + if (vb->wl_buffer) + wl_resource_destroy(vb->wl_buffer); + } + LIST_DEL(&voutput_info->link); /* Do free your own resource */ @@ -881,6 +1154,7 @@ _tdm_server_cb_create_virtual_output(struct wl_client *client, struct wl_resourc voutput_info->resource = voutput_resource; voutput_info->output = output; LIST_INITHEAD(&voutput_info->output_list); + LIST_INITHEAD(&voutput_info->buffer_list); wl_resource_set_implementation(voutput_resource, &tdm_voutput_implementation, @@ -1047,7 +1321,7 @@ INTERN void tdm_server_deinit(tdm_private_loop *private_loop) { tdm_server_output_info *o = NULL, *oo = NULL; -// tdm_server_voutput_info *vo = NULL, *voo = NULL; + tdm_server_voutput_info *vo = NULL, *voo = NULL; tdm_server_wait_info *w = NULL, *ww = NULL; tdm_server_client_info *c = NULL, *cc = NULL; tdm_private_server *private_server; @@ -1064,11 +1338,11 @@ tdm_server_deinit(tdm_private_loop *private_loop) LIST_FOR_EACH_ENTRY_SAFE(o, oo, &private_server->output_list, link) { wl_resource_destroy(o->resource); } -#if 0 + LIST_FOR_EACH_ENTRY_SAFE(vo, voo, &private_server->voutput_list, link) { wl_resource_destroy(vo->resource); } -#endif + LIST_FOR_EACH_ENTRY_SAFE(c, cc, &client_list, link) { wl_resource_destroy(c->resource); } -- 2.7.4