From 20059d63049f7c781c25383cf422f836b478cee1 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Thu, 26 Jul 2018 17:59:59 +0900 Subject: [PATCH 01/16] virtual (client): Add APIs and implementation for related commit. tdm_client_voutput_add_commit_handler() tdm_client_voutput_remove_commit_handler() tdm_client_voutput_commit_done() Change-Id: I895ae3e3478a140086801ab8599233b4d7faabde --- client/tdm_client.c | 135 +++++++++++++++++++++++++++++++++++++++++ client/tdm_client.h | 8 ++- haltests/src/tc_tdm_client.cpp | 32 ++++++++++ protocol/tdm.xml | 3 + src/tdm_server.c | 16 ++++- 5 files changed, 192 insertions(+), 2 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 65c37da..9aac858 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -92,6 +92,7 @@ typedef struct _tdm_private_client_output { typedef struct _tdm_private_client_voutput { tdm_private_client_output base; struct wl_tdm_voutput *wl_voutput; + struct list_head commit_handler_list; struct { @@ -157,6 +158,17 @@ typedef struct _tdm_client_wait_info { struct list_head call_link; } tdm_client_wait_info; +typedef struct _tdm_client_voutput_commit_handler_info +{ + tdm_private_client_voutput *private_voutput; + + tdm_client_voutput_commit_handler func; + void *user_data; + + struct list_head link; + struct list_head call_link; +} tdm_client_voutput_commit_handler_info; + static unsigned int _tdm_client_check_wl_error(tdm_private_client *private_client, const char *func, int line) { @@ -1615,6 +1627,33 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank) } void +tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; + struct list_head call_list; + + private_voutput = (tdm_private_client_voutput *)data; + TDM_RETURN_IF_FAIL(private_voutput != NULL); + + private_client = private_voutput->base.private_client; + + LIST_INITHEAD(&call_list); + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + LIST_ADDTAIL(&h->call_link, &call_list); + } + + pthread_mutex_unlock(&private_client->lock); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &call_list, call_link) { + if (h->func) + h->func(private_voutput, h->user_data); + } + pthread_mutex_lock(&private_client->lock); +} + +void tdm_client_voutput_cb_ack_message(void *data, struct wl_tdm_voutput *wl_voutput, uint32_t msg) { tdm_private_client_voutput *private_voutput = data; @@ -1623,6 +1662,7 @@ 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_commit, tdm_client_voutput_cb_ack_message }; @@ -1693,6 +1733,8 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error /* LOCV_EXCL_STOP */ } + LIST_INITHEAD(&private_voutput->commit_handler_list); + private_voutput->base.private_client = private_client; private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, private_voutput->base.name); @@ -1742,6 +1784,7 @@ void tdm_client_voutput_destroy(tdm_client_voutput *voutput) { tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)voutput; + tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; if (!private_voutput) return; @@ -1752,6 +1795,11 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (private_voutput->available_formats.formats) free(private_voutput->available_formats.formats); + LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_voutput->commit_handler_list, link) { + LIST_DEL(&h->link); + free(h); + } + wl_tdm_voutput_destroy(private_voutput->wl_voutput); free(private_voutput); @@ -1835,6 +1883,93 @@ tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int m return TDM_ERROR_NONE; } +tdm_error +tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, + tdm_client_voutput_commit_handler func, + void *user_data) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->base.private_client; + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + if (h->func == func && h->user_data == user_data) { + TDM_ERR("can't add twice"); + return TDM_ERROR_BAD_REQUEST; + } + } + + h = calloc(1, sizeof *h); + TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY); + + pthread_mutex_lock(&private_client->lock); + + if (CHECK_WL_PROTOCOL_ERROR(private_client)) { + free(h); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_PROTOCOL_ERROR; + } + + h->private_voutput = private_voutput; + h->func = func; + h->user_data = user_data; + LIST_ADDTAIL(&h->link, &private_voutput->commit_handler_list); + LIST_INITHEAD(&h->call_link); + + pthread_mutex_unlock(&private_client->lock); + + return TDM_ERROR_NONE; +} + +void +tdm_client_voutput_remove_commit_handler(tdm_client_voutput *voutput, + tdm_client_voutput_commit_handler func, + void *user_data) +{ + tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_client_voutput_commit_handler_info *h = NULL; + + TDM_RETURN_IF_FAIL(voutput != NULL); + TDM_RETURN_IF_FAIL(func != NULL); + + private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->base.private_client; + + pthread_mutex_lock(&private_client->lock); + + LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { + if (h->func != func || h->user_data != user_data) + continue; + + LIST_DEL(&h->link); + free(h); + + pthread_mutex_unlock(&private_client->lock); + } + + pthread_mutex_unlock(&private_client->lock); +} + +tdm_error +tdm_client_voutput_commit_done(tdm_client_voutput *voutput) +{ + tdm_private_client_voutput *private_voutput; + + TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_voutput = (tdm_private_client_voutput *)voutput; + wl_tdm_voutput_commit_done(private_voutput->wl_voutput); + + return TDM_ERROR_NONE; +} + tdm_client_output * tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error) { diff --git a/client/tdm_client.h b/client/tdm_client.h index c0ffeb7..d6dc32a 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -448,11 +448,17 @@ tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error -tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler *func); +tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler func, void *user_data); + +void +tdm_client_voutput_remove_commit_handler(tdm_client_voutput *voutput, tdm_client_voutput_commit_handler func, void *user_data); tdm_error tdm_client_voutput_get_committed_tbm_surface(tdm_client_voutput *voutput, tbm_surface_h surface); +tdm_error +tdm_client_voutput_commit_done(tdm_client_voutput *voutput); + tdm_client_output * tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error); diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 1ee78c5..fc43491 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1598,6 +1598,38 @@ TEST_F(TDMVirtualOutput, FailTestSetPhysicalSize) ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } +static void +_tc_tdm_client_voutput_commit_handler(tdm_client_voutput *voutput, void *user_data) +{ + int *flag; + flag = (int *)user_data; + *flag = 1; +} + +TEST_F(TDMVirtualOutput, AddCommitHandler) +{ + tdm_error ret; + int flag_callback_called = 0; + + ret = tdm_client_voutput_add_commit_handler(this->voutput, + _tc_tdm_client_voutput_commit_handler, + &flag_callback_called); + ASSERT_EQ(ret, TDM_ERROR_NONE); +// ASSERT_EQ(flag_callback_called, 1); + + tdm_client_voutput_remove_commit_handler(this->voutput, + _tc_tdm_client_voutput_commit_handler, + &flag_callback_called); +} + +TEST_F(TDMVirtualOutput, CommitDone) +{ + tdm_error ret; + + ret = tdm_client_voutput_commit_done(this->voutput); + ASSERT_EQ(ret, TDM_ERROR_NONE); +} + TEST_F(TDMVirtualOutput, GetClientOutput) { tdm_error ret; diff --git a/protocol/tdm.xml b/protocol/tdm.xml index f36636e..3de2c0f 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -94,6 +94,9 @@ + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index 08fb539..b99980b 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -821,13 +821,27 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc tdm_output_set_disconnect(voutput_info->output); } +static void +_tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_voutput_info *voutput_info; + + voutput_info = wl_resource_get_user_data(resource); + if (voutput_info->status != TDM_OUTPUT_CONN_STATUS_CONNECTED) + { + // handle error + return; + } +} + static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, _tdm_voutput_cb_set_available_formats, _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, - _tdm_voutput_cb_disconnect + _tdm_voutput_cb_disconnect, + _tdm_voutput_cb_commit_done }; void -- 2.7.4 From df5d9204977983ae215d9e23325338016c893f09 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 3 Aug 2018 11:21:10 +0900 Subject: [PATCH 02/16] Revert "virtual (client): Added implementation for setting available format." This reverts commit 7e7fcd357fbec8140bb607ba4f9417baef49f747. Change-Id: Ieac70ebde6f66460664bbae1f10687368b0e64aa --- client/tdm_client.c | 56 ------------------------------------------ client/tdm_client.h | 3 --- haltests/src/tc_tdm_client.cpp | 22 ----------------- protocol/tdm.xml | 4 --- src/tdm_server.c | 31 ----------------------- 5 files changed, 116 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 9aac858..92b1626 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -97,12 +97,6 @@ typedef struct _tdm_private_client_voutput { struct { int count; - tbm_format *formats; - } available_formats; - - struct - { - int count; tdm_client_output_mode *modes; } available_modes; @@ -1792,9 +1786,6 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); - if (private_voutput->available_formats.formats) - free(private_voutput->available_formats.formats); - LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_voutput->commit_handler_list, link) { LIST_DEL(&h->link); free(h); @@ -1835,35 +1826,6 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl } tdm_error -tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count) -{ - tdm_private_client_voutput *private_voutput; - - TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); - - if ((count > 0) && (formats == NULL)) - return TDM_ERROR_INVALID_PARAMETER; - - private_voutput = (tdm_private_client_voutput *)voutput; - - if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) - return TDM_ERROR_BAD_REQUEST; - - if (private_voutput->available_formats.formats) - free(private_voutput->available_formats.formats); - - private_voutput->available_formats.count = count; - - if (count != 0) - { - private_voutput->available_formats.formats = calloc(count, sizeof(tbm_format)); - memcpy(private_voutput->available_formats.formats, formats, sizeof(tbm_format) * count); - } - - return TDM_ERROR_NONE; -} - -tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight) { tdm_private_client_voutput *private_voutput; @@ -2011,23 +1973,6 @@ tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mo } void -_tdm_client_voutput_send_available_formats(tdm_private_client_voutput *private_voutput) -{ - tbm_format *format; - struct wl_array array; - int i, size; - - size = sizeof(tbm_format); - wl_array_init(&array); - for (i = 0; i < private_voutput->available_formats.count; i++) { - format = wl_array_add(&array, size); - *format = private_voutput->available_formats.formats[i]; - } - wl_tdm_voutput_set_available_formats(private_voutput->wl_voutput, &array); - wl_array_release(&array); -} - -void _tdm_client_voutput_send_available_modes(tdm_private_client_voutput *private_voutput) { tdm_client_output_mode *modes, *mode; @@ -2063,7 +2008,6 @@ tdm_client_output_connect(tdm_client_output *output) private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; _tdm_client_voutput_send_available_modes(private_voutput); - _tdm_client_voutput_send_available_formats(private_voutput); wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); diff --git a/client/tdm_client.h b/client/tdm_client.h index d6dc32a..f431f1c 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -442,9 +442,6 @@ tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count); tdm_error -tdm_client_voutput_set_available_formats(tdm_client_voutput *voutput, const tbm_format *formats, const int count); - -tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight); tdm_error diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index fc43491..3d4aa47 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1413,7 +1413,6 @@ protected: static tdm_client *client; static tdm_client_voutput *voutput; const int MODE_COUNT = 2; - const int FORMAT_COUNT = 2; private: static pid_t server_pid; @@ -1541,7 +1540,6 @@ _tc_tdm_client_virutual_make_available_mode(tdm_client_output_mode *modes, int c } } - TEST_F(TDMVirtualOutput, SetAvailableModes) { tdm_error ret; @@ -1567,19 +1565,6 @@ TEST_F(TDMVirtualOutput, FailTestSetAvailableModes) ASSERT_EQ(ret, TDM_ERROR_INVALID_PARAMETER); } -TEST_F(TDMVirtualOutput, SetAvailableFormats) -{ - const int nformats = 2; - tdm_error ret; - tbm_format formats[nformats]; - - formats[0] = TBM_FORMAT_ARGB8888; - formats[1] = TBM_FORMAT_XRGB8888; - - ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); - ASSERT_EQ(ret, TDM_ERROR_NONE); -} - TEST_F(TDMVirtualOutput, SetPhysicalSize) { tdm_error ret; @@ -1642,12 +1627,10 @@ TEST_F(TDMVirtualOutput, GetClientOutput) TEST_F(TDMVirtualOutput, Connect) { - const int nformats = 2; tdm_error ret; tdm_client_output *output; unsigned int mmWidth = 300, mmHeight = 150; tdm_client_output_mode modes[this->MODE_COUNT]; - tbm_format formats[nformats]; int count = this->MODE_COUNT; output = tdm_client_voutput_get_client_output(this->voutput, &ret); @@ -1661,11 +1644,6 @@ TEST_F(TDMVirtualOutput, Connect) ret = tdm_client_voutput_set_available_modes(this->voutput, modes, count); ASSERT_EQ(ret, TDM_ERROR_NONE); - formats[0] = TBM_FORMAT_ARGB8888; - formats[1] = TBM_FORMAT_XRGB8888; - ret = tdm_client_voutput_set_available_formats(this->voutput, formats, nformats); - ASSERT_EQ(ret, TDM_ERROR_NONE); - ret = tdm_client_output_connect(output); ASSERT_EQ(ret, TDM_ERROR_NONE); diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 3de2c0f..b1d6699 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -81,10 +81,6 @@ - - - - diff --git a/src/tdm_server.c b/src/tdm_server.c index b99980b..c86de65 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -79,11 +79,6 @@ typedef struct _tdm_server_voutput_info { int count; tdm_output_mode *modes; } available_modes; - struct - { - int count; - tbm_format *formats; - } available_formats; unsigned int mmwidth; unsigned int mmheight; @@ -754,31 +749,6 @@ _tdm_voutput_cb_set_available_modes(struct wl_client *client, } static void -_tdm_voutput_cb_set_available_formats(struct wl_client *client, - struct wl_resource *resource, - struct wl_array *formats) -{ - tdm_server_voutput_info *voutput_info; - tbm_format *f; - int count = 0, i = 0; - - voutput_info = wl_resource_get_user_data(resource); - - voutput_info->available_formats.count = 0; - if (voutput_info->available_formats.formats) - free(voutput_info->available_formats.formats); - - wl_array_for_each(f, formats) - count++; - - voutput_info->available_formats.formats = malloc(count * sizeof(tbm_format)); - voutput_info->available_formats.count = count; - - wl_array_for_each(f, formats) - voutput_info->available_formats.formats[i++] = *f; -} - -static void _tdm_voutput_cb_set_physical_size(struct wl_client *client, struct wl_resource *resource, unsigned int mmwidth, unsigned int mmheight) { @@ -837,7 +807,6 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { _tdm_voutput_cb_destroy, _tdm_voutput_cb_set_available_modes, - _tdm_voutput_cb_set_available_formats, _tdm_voutput_cb_set_physical_size, _tdm_voutput_cb_connect, _tdm_voutput_cb_disconnect, -- 2.7.4 From 52eca1efc87b46a754e8d0de7445d1e84061ced6 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 1 Aug 2018 21:34:57 +0900 Subject: [PATCH 03/16] 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 From 17a49e755585adc9926ebaa00b34ac39ed79bdd5 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Mon, 6 Aug 2018 13:39:36 +0900 Subject: [PATCH 04/16] move tbm_surface_internal.h file to c file. Change-Id: I71ad0dfdb2919f6dc9cba2f1eccc08009913b746 --- client/tdm_client.c | 1 + client/tdm_client.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 53434f1..32bdb52 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -54,6 +54,7 @@ #include "tdm_list.h" #include "tdm.h" #include "tdm_private.h" +#include #define TDM_ARRAY_NTH_DATA(array, type, n) (((type*)((array)->data)) + n) diff --git a/client/tdm_client.h b/client/tdm_client.h index 420c5e2..f431f1c 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -431,7 +431,6 @@ 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); -- 2.7.4 From 69e26b823f4c84b3f7a74d43176340d58f03f10f Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 26 Mar 2018 17:04:33 +0900 Subject: [PATCH 05/16] virtual: add output create/destroy interface Change-Id: I1ee25761ef62df057c4bbfa63408f47501cda380 --- include/tdm.h | 23 +++++++++++++++++++++++ include/tdm_backend.h | 9 +++++++++ include/tdm_common.h | 1 + 3 files changed, 33 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 7beccd0..979c35e 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -206,6 +206,16 @@ tdm_display_get_output_count(tdm_display *dpy, int *count); tdm_output * tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error); +tdm_error +tdm_display_add_output_create_handler(tdm_display *dpy, + tdm_output_create_handler func, + void *user_data); + +void +tdm_display_remove_output_create_handler(tdm_display *dpy, + tdm_output_create_handler func, + void *user_data); + /** * @brief Find a output object which has the given name. * @param[in] dpy A display object @@ -238,6 +248,16 @@ tdm_error tdm_module_get_info(tdm_module *module, const char **name, const char **vendor, int *major, int *minor); +tdm_error +tdm_output_add_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data); + +void +tdm_output_remove_destroy_handler(tdm_output *output, + tdm_output_destroy_handler func, + void *user_data); + /** * @brief Get a backend module object of the given output. * @param[in] output A output object @@ -761,6 +781,9 @@ tdm_layer_get_displaying_buffer(tdm_layer *layer, tdm_error *error); tdm_error tdm_layer_set_buffer_queue(tdm_layer *layer, tbm_surface_queue_h buffer_queue); +tdm_error +tdm_layer_get_own_buffer_queue(tdm_layer *layer, tbm_surface_queue_h *buffer_queue); + /** * @brief Unset a TBM surface_queue from a layer object * @details When this function is called, a current surface_queue will be diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 72136b1..a28654a 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -682,6 +682,15 @@ typedef struct _tdm_func_layer { */ tdm_error (*layer_get_buffer_flags)(tdm_layer *layer, unsigned int *flags); + /** + * @brief Get buffer queue which the layer offers. + * @param[in] layer A layer object + * @param[out] buffer_queue The buffer queue + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @since 2.0.0 + */ + tdm_error (*layer_get_buffer_queue)(tdm_layer *layer, tbm_surface_queue_h *buffer_queue); + void (*reserved1)(void); void (*reserved2)(void); void (*reserved3)(void); diff --git a/include/tdm_common.h b/include/tdm_common.h index 328f837..cc79e90 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -134,6 +134,7 @@ typedef enum { TDM_LAYER_CAPABILITY_SCANOUT = (1 << 10), /**< if a layer allows a scanout buffer only */ TDM_LAYER_CAPABILITY_RESEVED_MEMORY = (1 << 11), /**< if a layer allows a reserved buffer only */ TDM_LAYER_CAPABILITY_NO_CROP = (1 << 12), /**< if a layer has no cropping capability */ + TDM_LAYER_CAPABILITY_BUFFER_QUEUE = (1 << 13), /**< if a layer has an own buffer queue */ } tdm_layer_capability; /** -- 2.7.4 From 2151dd496cc649dbeabc2e180e5fb0f7bd99c91c Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 7 Aug 2018 16:53:51 +0900 Subject: [PATCH 06/16] virtual: erase unused code Change-Id: I53ad0cf81e1cda83af60f3e1139bd02c0a12c526 Signed-off-by: Junkyeong Kim --- backends/virtual/tdm_virtual.c | 8 --- backends/virtual/tdm_virtual_display.c | 113 +++------------------------------ src/tdm_server.c | 2 +- 3 files changed, 9 insertions(+), 114 deletions(-) diff --git a/backends/virtual/tdm_virtual.c b/backends/virtual/tdm_virtual.c index 1b96a4c..eaf44ad 100644 --- a/backends/virtual/tdm_virtual.c +++ b/backends/virtual/tdm_virtual.c @@ -107,15 +107,7 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error) ret = TDM_ERROR_OPERATION_FAILED; goto failed; } -#if 0 - ret = tdm_virtual_display_create_output_list(virtual_data); - if (ret != TDM_ERROR_NONE) - goto failed; - ret = tdm_virtual_display_create_layer_list(virtual_data); - if (ret != TDM_ERROR_NONE) - goto failed; -#endif if (error) *error = TDM_ERROR_NONE; diff --git a/backends/virtual/tdm_virtual_display.c b/backends/virtual/tdm_virtual_display.c index 14c1e62..ec2cec5 100644 --- a/backends/virtual/tdm_virtual_display.c +++ b/backends/virtual/tdm_virtual_display.c @@ -156,42 +156,6 @@ _tdm_virtual_display_destroy_layer_list(tdm_virtual_data *virtual_data) } } -tdm_error -tdm_virtual_display_create_layer_list(tdm_virtual_data *virtual_data) -{ - tdm_virtual_output_data *output_data = NULL; - tdm_error ret = TDM_ERROR_NONE; - - if (LIST_IS_EMPTY(&virtual_data->output_list)) { - TDM_ERR("no output"); - return TDM_ERROR_OPERATION_FAILED; - } - - /* The TDM virtual backend only support one output. */ - LIST_FOR_EACH_ENTRY(output_data, &virtual_data->output_list, link) { - tdm_virtual_layer_data *layer_data = calloc(1, sizeof(tdm_virtual_layer_data)); - if (!layer_data) { - TDM_ERR("alloc failed"); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed; - } - - layer_data->virtual_data = virtual_data; - layer_data->output_data = output_data; - layer_data->zpos = 0; - - layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC; - output_data->primary_layer = layer_data; - - LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); - } - - return TDM_ERROR_NONE; -failed: - _tdm_virtual_display_destroy_layer_list(virtual_data); - return ret; -} - void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data) { @@ -223,71 +187,6 @@ tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data) } tdm_error -tdm_virtual_display_create_output_list(tdm_virtual_data *virtual_data) -{ - tdm_virtual_output_data *output_data; - tdm_error ret; - - RETURN_VAL_IF_FAIL(LIST_IS_EMPTY(&virtual_data->output_list), TDM_ERROR_OPERATION_FAILED); - - output_data = calloc(1, sizeof(tdm_virtual_output_data)); - if (!output_data) { - TDM_ERR("alloc failed"); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - - LIST_INITHEAD(&output_data->layer_list); - - output_data->virtual_data = virtual_data; - output_data->pipe = 0; - output_data->connector_type = TDM_OUTPUT_TYPE_Unknown; - output_data->status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; - - output_data->output_modes = calloc(1, sizeof(tdm_output_mode)); - if (!output_data->output_modes) { - TDM_ERR("alloc failed"); - free(output_data); - ret = TDM_ERROR_OUT_OF_MEMORY; - goto failed_create; - } - - snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480"); - output_data->output_modes->vrefresh = 30; - output_data->output_modes->clock = 25200; - output_data->output_modes->hdisplay = 640; - output_data->output_modes->hsync_start = 656; - output_data->output_modes->hsync_end = 752; - output_data->output_modes->htotal = 800; - output_data->output_modes->hskew = 0; - output_data->output_modes->vdisplay = 480; - output_data->output_modes->vsync_start = 490; - output_data->output_modes->vsync_end = 492; - output_data->output_modes->vtotal = 525; - output_data->output_modes->vscan = 0; - output_data->output_modes->flags = 0; - output_data->output_modes->type = 0; - - output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy, - _tdm_virtual_display_cb_timeout, - output_data, - &ret); - if (!output_data->timer) { - free(output_data); - return ret; - } - - LIST_INITHEAD(&output_data->timer_event_list); - - LIST_ADDTAIL(&output_data->link, &virtual_data->output_list); - - return TDM_ERROR_NONE; -failed_create: - tdm_virtual_display_destroy_output_list(virtual_data); - return ret; -} - -tdm_error virtual_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps) { RETURN_VAL_IF_FAIL(caps, TDM_ERROR_INVALID_PARAMETER); @@ -392,7 +291,7 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err snprintf(output_data->name, TDM_NAME_LEN, "%s", name); else snprintf(output_data->name, TDM_NAME_LEN, "unknown"); -#if 0 + output_data->output_modes = calloc(1, sizeof(tdm_output_mode)); if (!output_data->output_modes) { TDM_ERR("alloc failed"); @@ -400,6 +299,7 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err goto create_fail; } + /* default mode */ snprintf(output_data->output_modes->name, TDM_NAME_LEN, "640x480"); output_data->output_modes->vrefresh = 30; output_data->output_modes->clock = 25200; @@ -415,9 +315,8 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err output_data->output_modes->vscan = 0; output_data->output_modes->flags = 0; output_data->output_modes->type = 0; - output_data->mode_count = 1; -#endif + output_data->timer = tdm_event_loop_add_timer_handler(virtual_data->dpy, _tdm_virtual_display_cb_timeout, output_data, @@ -441,10 +340,14 @@ virtual_display_output_create(tdm_backend_data *bdata, const char *name, tdm_err layer_data->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC; output_data->primary_layer = layer_data; + LIST_ADDTAIL(&output_data->link, &virtual_data->output_list); LIST_ADDTAIL(&layer_data->link, &output_data->layer_list); ret = tdm_backend_register_output(virtual_data->dpy, output_data); - GOTO_IF_FAIL(ret == TDM_ERROR_NONE, create_fail); + if (ret != TDM_ERROR_NONE) { + LIST_DEL(&output_data->link); + goto create_fail; + } *error = TDM_ERROR_NONE; diff --git a/src/tdm_server.c b/src/tdm_server.c index bf38211..e301ab3 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -1030,7 +1030,7 @@ _tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surfac return voutput_buffer; } -tdm_error +INTERN tdm_error tdm_output_send_buffer(tdm_output *output, tbm_surface_h surface) { tdm_private_server *private_server = keep_private_server; -- 2.7.4 From b86fd8a4f6e17ca00edd5345b862aa8c08756331 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 9 Aug 2018 11:22:07 +0900 Subject: [PATCH 07/16] virtual: add attach_buffer protocol Change-Id: I2af7410283e8f9d9e102294f368ed4d04a9cd0e4 --- client/tdm_client.c | 24 +++++++++++++++++++++++- protocol/tdm.xml | 4 ++++ src/tdm_server.c | 48 +++++++++++++++++++++++++++++------------------- 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 32bdb52..4e9edd4 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -117,7 +117,7 @@ typedef struct _tdm_private_client_voutput { struct list_head buffer_list; tbm_bufmgr bufmgr; - tdm_private_client_buffer *commit_buffer; + tdm_private_client_buffer *attach_buffer; } tdm_private_client_voutput; struct _tdm_private_client_vblank { @@ -1852,6 +1852,26 @@ tdm_client_voutput_cb_buffer_destroy(void *data, } void +tdm_client_voutput_cb_attach_buffer(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; + + 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) { + private_voutput->attach_buffer = cb; + break; + } + } + + return; +} + +void tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) { tdm_private_client_voutput *private_voutput; @@ -1890,6 +1910,7 @@ 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_attach_buffer, tdm_client_voutput_cb_commit, tdm_client_voutput_cb_ack_message }; @@ -2199,6 +2220,7 @@ tdm_client_voutput_commit_done(tdm_client_voutput *voutput) TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); private_voutput = (tdm_private_client_voutput *)voutput; + private_voutput->attach_buffer = NULL; wl_tdm_voutput_commit_done(private_voutput->wl_voutput); return TDM_ERROR_NONE; diff --git a/protocol/tdm.xml b/protocol/tdm.xml index 20ba4cd..a152c95 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -134,6 +134,10 @@ + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index e301ab3..aa546e6 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -71,7 +71,7 @@ typedef struct _tdm_server_output_info { typedef struct _tdm_server_voutput_buffer { struct list_head link; struct wl_resource *wl_buffer; - tbm_surface_h surface; + tbm_surface_h buffer; } tdm_server_voutput_buffer; typedef struct _tdm_server_voutput_info { @@ -93,6 +93,7 @@ typedef struct _tdm_server_voutput_info { struct list_head buffer_list; tdm_server_voutput_buffer *attach_buffer; + int committing; } tdm_server_voutput_info; typedef struct _tdm_server_vblank_info { @@ -813,6 +814,9 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour // handle error return; } +// tdm_output_commit_done(voutput_info->output, voutput_info->attach_buffer->buffer); + voutput_info->committing = 0; + voutput_info->attach_buffer = NULL; } static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { @@ -845,7 +849,7 @@ _tdm_voutput_buffer_destory(struct wl_resource *wl_buffer) LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { if (vb->wl_buffer == wl_buffer) { - tbm_surface_internal_unref(vb->surface); + tbm_surface_internal_unref(vb->buffer); wl_resource_set_user_data(wl_buffer, NULL); free(vb); } @@ -873,7 +877,7 @@ _tdm_voutput_create_wl_buffer(tdm_server_voutput_info *voutput_info) struct wl_resource * _tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, - tbm_surface_h surface) + tbm_surface_h buffer) { int bufs[TBM_SURF_PLANE_MAX] = { -1, -1, -1, -1}; struct wl_resource *wl_buffer = NULL; @@ -884,9 +888,9 @@ _tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, int *p; TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, NULL); - TDM_RETURN_VAL_IF_FAIL(surface != NULL, NULL); + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); - if (tbm_surface_get_info(surface, &info) != TBM_SURFACE_ERROR_NONE) { + if (tbm_surface_get_info(buffer, &info) != TBM_SURFACE_ERROR_NONE) { TDM_ERR("Failed to create buffer from surface"); return NULL; } @@ -896,14 +900,14 @@ _tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, return NULL; } - num_buf = tbm_surface_internal_get_num_bos(surface); + num_buf = tbm_surface_internal_get_num_bos(buffer); 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); + tbm_bo bo = tbm_surface_internal_get_bo(buffer, i); if (bo == NULL) { TDM_ERR("Failed to get bo from surface"); goto err; @@ -944,7 +948,7 @@ _tdm_voutput_export_buffer(tdm_server_voutput_info *voutput_info, 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 = tbm_surface_internal_get_plane_bo_idx(buffer, i); p = wl_array_add(&plane_offset, sizeof(int)); *p = info.planes[i].offset; p = wl_array_add(&plane_stride, sizeof(int)); @@ -991,47 +995,47 @@ err: } tdm_server_voutput_buffer * -_tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surface_h surface) +_tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surface_h buffer) { tdm_server_voutput_buffer *voutput_buffer = NULL, *vb = NULL; LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { - if (vb && vb->surface == surface) + if (vb && vb->buffer == buffer) return vb; } - tbm_surface_internal_ref(surface); + tbm_surface_internal_ref(buffer); voutput_buffer = calloc(1, sizeof *voutput_buffer); if (!voutput_buffer) { /* LCOV_EXCL_START */ TDM_ERR("fail calloc"); - tbm_surface_internal_unref(surface); + tbm_surface_internal_unref(buffer); return NULL; /* LCOV_EXCL_STOP */ } - voutput_buffer->wl_buffer = _tdm_voutput_export_buffer(voutput_info, surface); + voutput_buffer->wl_buffer = _tdm_voutput_export_buffer(voutput_info, buffer); if (!voutput_buffer->wl_buffer) { /* LCOV_EXCL_START */ TDM_ERR("fail export buffer"); free(voutput_buffer); - tbm_surface_internal_unref(surface); + tbm_surface_internal_unref(buffer); return NULL; /* LCOV_EXCL_STOP */ } - voutput_buffer->surface = surface; + voutput_buffer->buffer = buffer; LIST_ADDTAIL(&voutput_info->link, &voutput_info->buffer_list); return voutput_buffer; } INTERN tdm_error -tdm_output_send_buffer(tdm_output *output, tbm_surface_h surface) +tdm_output_send_buffer(tdm_output *output, tbm_surface_h buffer) { tdm_private_server *private_server = keep_private_server; tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; @@ -1046,16 +1050,19 @@ tdm_output_send_buffer(tdm_output *output, tbm_surface_h surface) } } TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer == NULL, TDM_ERROR_OPERATION_FAILED); - voutput_buffer = _tdm_output_get_voutput_buffer(voutput_info, surface); + voutput_buffer = _tdm_output_get_voutput_buffer(voutput_info, buffer); TDM_RETURN_VAL_IF_FAIL(voutput_buffer != NULL, TDM_ERROR_OUT_OF_MEMORY); voutput_info->attach_buffer = voutput_buffer; + wl_tdm_voutput_send_attach_buffer(voutput_info->resource, voutput_buffer->wl_buffer); + return TDM_ERROR_NONE; } -tdm_error +INTERN tdm_error tdm_output_commit_buffer(tdm_output *output) { tdm_private_server *private_server = keep_private_server; @@ -1070,7 +1077,10 @@ tdm_output_commit_buffer(tdm_output *output) } } 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); + TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer != NULL, TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(voutput_info->committing == 0, TDM_ERROR_OPERATION_FAILED); + + voutput_info->committing = 1; wl_tdm_voutput_send_commit(voutput_info->resource); -- 2.7.4 From 1fb5c4fd67583429dab4bfc2dea1e8892bc38405 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 9 Aug 2018 11:41:29 +0900 Subject: [PATCH 08/16] virtual: send set buffer to client when commit do not use virtual backend. send buffer from front end to client directly. cannot commit while commiting. Change-Id: Iae254500c19e428d3841d064a6fda9a94919f0a5 Signed-off-by: Junkyeong Kim --- src/tdm_backend.c | 2 +- src/tdm_output.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tdm_private.h | 6 +++- src/tdm_server.c | 2 +- 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/tdm_backend.c b/src/tdm_backend.c index 7d469d1..1a60673 100644 --- a/src/tdm_backend.c +++ b/src/tdm_backend.c @@ -238,7 +238,7 @@ tdm_backend_register_output(tdm_display *dpy, tdm_output *output) BACKEND_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED); - TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_OPERATION_FAILED); + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); /* this function is only for backend. if backend calls this function, it means * that it's triggered by frontend. frontend should set current_module before calling diff --git a/src/tdm_output.c b/src/tdm_output.c index 778dc6d..0185615 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1214,9 +1214,69 @@ tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler f return ret; } +tdm_error +_tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) +{ + tdm_private_output *private_output; + tdm_private_output_commit_handler *output_commit_handler = NULL; + tdm_private_layer *private_layer = NULL; + tbm_surface_h buffer; + tdm_error ret = TDM_ERROR_NONE; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + + if (!LIST_IS_EMPTY(&private_output->output_commit_handler_list)) { + /* support only 1 commit */ + TDM_ERR("voutput canot commit while commiting"); + return TDM_ERROR_OPERATION_FAILED; + } + + output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); + if (!output_commit_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list); + output_commit_handler->private_output = private_output; + output_commit_handler->func = func; + output_commit_handler->user_data = user_data; + output_commit_handler->owner_tid = syscall(SYS_gettid); + + /* voutput use only 1 layer */ + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + if (private_layer) break; + } + TDM_GOTO_IF_FAIL(private_layer, commit_failed); + TDM_GOTO_IF_FAIL(private_layer->committed_buffer, commit_failed); + + buffer = private_layer->committed_buffer->buffer; + + ret = tdm_output_send_buffer(private_output, buffer); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + ret = tdm_output_commit_buffer(private_output); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + + return ret; + +commit_failed: + /* LCOV_EXCL_START */ + if (output_commit_handler) { + LIST_DEL(&output_commit_handler->link); + free(output_commit_handler); + } + return ret; +/* LCOV_EXCL_STOP */ +} + INTERN tdm_error tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { + tdm_private_display *private_display; tdm_private_output *private_output; tdm_private_module *private_module; tdm_func_output *func_output; @@ -1229,8 +1289,12 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl private_output = (tdm_private_output*)output; private_module = private_output->private_module; + private_display = private_module->private_display; func_output = &private_module->func_output; + if (private_module == private_display->virtual_module) + return _tdm_output_commit_virtual(output, sync, func, user_data); + if (!func_output->output_commit) { /* LCOV_EXCL_START */ TDM_WRN("not implemented!!"); @@ -1811,4 +1875,34 @@ tdm_output_set_disconnect(tdm_output *output) return ret; } + +INTERN tdm_error +tdm_output_commit_done(tdm_output *output, tbm_surface_h buffer) +{ + tdm_private_layer *private_layer = NULL; + tdm_private_output_commit_handler *output_commit_handler = NULL; + static int sequence = 0; + tdm_private_output *private_output; + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \ + private_output = (tdm_private_output*)output; + + LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) { + if (private_layer) break; + } + + LIST_FOR_EACH_ENTRY(output_commit_handler, &private_output->output_commit_handler_list, link) { + if (output_commit_handler) break; + } + TDM_RETURN_VAL_IF_FAIL(output_commit_handler, TDM_ERROR_INVALID_PARAMETER); + + LIST_DEL(&output_commit_handler->link); + + output_commit_handler->func(private_output, + sequence++, + 0, 0, + output_commit_handler->user_data); + free(output_commit_handler); + + return TDM_ERROR_NONE; +} /* LCOV_EXCL_STOP */ diff --git a/src/tdm_private.h b/src/tdm_private.h index fea8715..3cfd101 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -269,7 +269,11 @@ 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); +tdm_output_send_buffer(tdm_output *output, tbm_surface_h buffer); +tdm_error +tdm_output_commit_buffer(tdm_output *output); +tdm_error +tdm_output_commit_done(tdm_output *output, tbm_surface_h buffer); #ifdef __cplusplus } diff --git a/src/tdm_server.c b/src/tdm_server.c index aa546e6..b4aede3 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -814,7 +814,7 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour // handle error return; } -// tdm_output_commit_done(voutput_info->output, voutput_info->attach_buffer->buffer); + tdm_output_commit_done(voutput_info->output, voutput_info->attach_buffer->buffer); voutput_info->committing = 0; voutput_info->attach_buffer = NULL; } -- 2.7.4 From 31b37b5e78a098b24d5ee45a74f297de2a710da3 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 9 Aug 2018 19:36:36 +0900 Subject: [PATCH 09/16] virtual: fix buffer management error Change-Id: I3c9a0c5dc79ed21b1871555d4abf7bec88bed6e9 Signed-off-by: Junkyeong Kim --- src/tdm_server.c | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/tdm_server.c b/src/tdm_server.c index b4aede3..09c6e3c 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -715,22 +715,6 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou static void _tdm_voutput_cb_destroy(struct wl_client *client, struct wl_resource *resource) { - tdm_server_voutput_info *voutput_info; - tdm_private_server *private_server; - tdm_output *output; - tdm_error ret = TDM_ERROR_NONE; - - voutput_info = wl_resource_get_user_data(resource); - - private_server = voutput_info->private_server; - output = voutput_info->output; - - if (output) - ret = tdm_display_destroy_output(private_server->private_loop->dpy, output); - - if (ret != TDM_ERROR_NONE) - TDM_ERR("_tdm_voutput_cb_destroy fail"); - wl_resource_destroy(resource); } @@ -807,6 +791,7 @@ static void _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resource) { tdm_server_voutput_info *voutput_info; + tbm_surface_h buffer; voutput_info = wl_resource_get_user_data(resource); if (voutput_info->status != TDM_OUTPUT_CONN_STATUS_CONNECTED) @@ -814,9 +799,14 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour // handle error return; } - tdm_output_commit_done(voutput_info->output, voutput_info->attach_buffer->buffer); + + buffer = voutput_info->attach_buffer->buffer; + tbm_surface_internal_unref(buffer); + voutput_info->committing = 0; voutput_info->attach_buffer = NULL; + + tdm_output_commit_done(voutput_info->output, buffer); } static const struct wl_tdm_voutput_interface tdm_voutput_implementation = { @@ -842,15 +832,16 @@ static void _tdm_voutput_buffer_destory(struct wl_resource *wl_buffer) { tdm_server_voutput_info *voutput_info = NULL; - tdm_server_voutput_buffer *vb = NULL; + tdm_server_voutput_buffer *vb = NULL, *vbb = 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) { + LIST_FOR_EACH_ENTRY_SAFE(vb, vbb, &voutput_info->buffer_list, link) { if (vb->wl_buffer == wl_buffer) { tbm_surface_internal_unref(vb->buffer); wl_resource_set_user_data(wl_buffer, NULL); + LIST_DEL(&vb->link); free(vb); } } @@ -1000,8 +991,10 @@ _tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surfac tdm_server_voutput_buffer *voutput_buffer = NULL, *vb = NULL; LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { - if (vb && vb->buffer == buffer) + if (vb && vb->buffer == buffer) { + tbm_surface_internal_ref(vb->buffer); return vb; + } } tbm_surface_internal_ref(buffer); @@ -1029,7 +1022,7 @@ _tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surfac } voutput_buffer->buffer = buffer; - LIST_ADDTAIL(&voutput_info->link, &voutput_info->buffer_list); + LIST_ADDTAIL(&voutput_buffer->link, &voutput_info->buffer_list); return voutput_buffer; } @@ -1091,13 +1084,23 @@ 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_server_voutput_buffer *vb; + tdm_private_server *private_server; + tdm_output *output; + tdm_error ret = TDM_ERROR_NONE; + TDM_RETURN_IF_FAIL(voutput_info != NULL); - LIST_FOR_EACH_ENTRY_SAFE(vb, vbb, &voutput_info->buffer_list, link) { - if (!vb) continue; + private_server = voutput_info->private_server; + output = voutput_info->output; - LIST_DEL(&vb->link); + if (output) + ret = tdm_display_destroy_output(private_server->private_loop->dpy, output); + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_voutput_cb_destroy fail"); + + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { + if (!vb) continue; if (vb->wl_buffer) wl_resource_destroy(vb->wl_buffer); -- 2.7.4 From ca91f10db2ce407718e436839fdf9501197edd15 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 16 Aug 2018 11:52:42 +0900 Subject: [PATCH 10/16] virtual: client get voutput's output by tdm_client_get_output voutput commit handler has tbm_surface. Change-Id: I4b2a5d8d0a313efd0a0f5050fa84e0413a95b3c3 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 120 ++++++++++++++++++++++++++++++++--------- client/tdm_client.h | 3 +- client/tdm_client_types.h | 3 ++ haltests/src/tc_tdm_client.cpp | 2 +- 4 files changed, 99 insertions(+), 29 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 4e9edd4..d94925a 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -59,6 +59,7 @@ #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_voutput tdm_private_client_voutput; typedef struct _tdm_private_client { pthread_mutex_t lock; @@ -68,6 +69,7 @@ typedef struct _tdm_private_client { struct wl_registry *registry; struct wl_tdm *tdm; struct list_head output_list; + struct list_head voutput_list; unsigned int enable_ttrace; unsigned int stamp; @@ -76,6 +78,8 @@ typedef struct _tdm_private_client { } tdm_private_client; typedef struct _tdm_private_client_output { + struct list_head link; + tdm_private_client *private_client; char name[TDM_NAME_LEN]; @@ -91,7 +95,7 @@ typedef struct _tdm_private_client_output { unsigned int req_id; unsigned int watch_output_changes; - struct list_head link; + tdm_private_client_voutput *voutput; } tdm_private_client_output; typedef struct _tdm_private_client_buffer { @@ -99,13 +103,12 @@ typedef struct _tdm_private_client_buffer { struct wl_buffer *wl_buffer; } tdm_private_client_buffer; -typedef struct _tdm_private_client_voutput { - tdm_private_client_output base; +struct _tdm_private_client_voutput { + struct list_head link; struct wl_tdm_voutput *wl_voutput; struct list_head commit_handler_list; - struct - { + struct { int count; tdm_client_output_mode *modes; } available_modes; @@ -118,7 +121,12 @@ typedef struct _tdm_private_client_voutput { struct list_head buffer_list; tbm_bufmgr bufmgr; tdm_private_client_buffer *attach_buffer; -} tdm_private_client_voutput; + + tdm_private_client *private_client; + tdm_private_client_output *private_output; + char name[TDM_NAME_LEN]; + int get_output; +}; struct _tdm_private_client_vblank { tdm_private_client_output *private_output; @@ -488,6 +496,7 @@ tdm_client_create(tdm_error *error) } LIST_INITHEAD(&private_client->output_list); + LIST_INITHEAD(&private_client->voutput_list); private_client->display = wl_display_connect("tdm-socket"); TDM_GOTO_IF_FAIL(private_client->display != NULL, create_failed); @@ -524,6 +533,7 @@ tdm_client_destroy(tdm_client *client) { tdm_private_client *private_client = (tdm_private_client*)client; tdm_private_client_output *o = NULL, *oo = NULL; + tdm_private_client_voutput *vo = NULL, *voo = NULL; if (!private_client) return; @@ -540,6 +550,10 @@ tdm_client_destroy(tdm_client *client) _tdm_client_output_destroy(o); } + LIST_FOR_EACH_ENTRY_SAFE(vo, voo, &private_client->voutput_list, link) { + tdm_client_voutput_destroy(vo); + } + if (private_client->tdm) wl_tdm_destroy(private_client->tdm); if (private_client->registry) @@ -814,11 +828,24 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) if (!name) { name = "primary"; - } else if (strncmp(name, "primary", 7) && strncmp(name, "default", 7)) { - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - pthread_mutex_unlock(&private_client->lock); - return NULL; + } else if (!strncmp(name, "primary", 7) || !strncmp(name, "default", 7)) { + TDM_DBG("get primary or default output"); + } else { + tdm_private_client_voutput *private_voutput = NULL; + int find = 0; + + LIST_FOR_EACH_ENTRY(private_voutput, &private_client->voutput_list, link) { + if (!strncmp(private_voutput->name, name, TDM_NAME_LEN)) { + find = 1; + break; + } + } + if (!find) { + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + pthread_mutex_unlock(&private_client->lock); + return NULL; + } } LIST_FOR_EACH_ENTRY(private_output, &private_client->output_list, link) { @@ -1876,13 +1903,20 @@ tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) { tdm_private_client_voutput *private_voutput; tdm_private_client *private_client; + tbm_surface_h buffer = NULL; tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; struct list_head call_list; private_voutput = (tdm_private_client_voutput *)data; TDM_RETURN_IF_FAIL(private_voutput != NULL); + TDM_RETURN_IF_FAIL(private_voutput->attach_buffer != NULL); + + buffer = (tbm_surface_h)wl_buffer_get_user_data(private_voutput->attach_buffer->wl_buffer); + TDM_RETURN_IF_FAIL(buffer != NULL); - private_client = private_voutput->base.private_client; + tbm_surface_internal_ref(buffer); + + private_client = private_voutput->private_client; LIST_INITHEAD(&call_list); @@ -1893,9 +1927,13 @@ tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) pthread_mutex_unlock(&private_client->lock); LIST_FOR_EACH_ENTRY_SAFE(h, hh, &call_list, call_link) { if (h->func) - h->func(private_voutput, h->user_data); + h->func(private_voutput, buffer, h->user_data); } pthread_mutex_lock(&private_client->lock); + + /* if no added commit_handler call commit done immediately */ + if (LIST_IS_EMPTY(&private_voutput->commit_handler_list)) + tdm_client_voutput_commit_done(private_voutput); } void @@ -1998,9 +2036,10 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error LIST_INITHEAD(&private_voutput->commit_handler_list); LIST_INITHEAD(&private_voutput->buffer_list); - private_voutput->base.private_client = private_client; + private_voutput->private_client = private_client; + strncpy(private_voutput->name, name, TDM_NAME_LEN); - private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, private_voutput->base.name); + private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, name); wl_proxy_wrapper_destroy(wrapper); if (!private_voutput->wl_voutput) { /* LCOV_EXCL_START */ @@ -2038,6 +2077,8 @@ tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error return NULL; } + LIST_ADDTAIL(&private_voutput->link, &private_client->voutput_list); + pthread_mutex_unlock(&private_client->lock); return (tdm_client_voutput *)private_voutput; @@ -2084,8 +2125,13 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) free(h); } + if (private_voutput->get_output) + _tdm_client_output_destroy(private_voutput->private_output); + wl_tdm_voutput_destroy(private_voutput->wl_voutput); + LIST_DEL(&private_voutput->link); + free(private_voutput); } @@ -2101,7 +2147,7 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl private_voutput = (tdm_private_client_voutput *)voutput; - if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + if (private_voutput->private_output->connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) return TDM_ERROR_BAD_REQUEST; if (private_voutput->available_modes.modes) @@ -2129,7 +2175,7 @@ tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int m private_voutput = (tdm_private_client_voutput *)voutput; - if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + if (private_voutput->private_output->connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) return TDM_ERROR_BAD_REQUEST; private_voutput->mmwidth = mmWidth; @@ -2151,7 +2197,7 @@ tdm_client_voutput_add_commit_handler(tdm_client_voutput *voutput, TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); private_voutput = (tdm_private_client_voutput *)voutput; - private_client = private_voutput->base.private_client; + private_client = private_voutput->private_client; LIST_FOR_EACH_ENTRY(h, &private_voutput->commit_handler_list, link) { if (h->func == func && h->user_data == user_data) { @@ -2195,7 +2241,7 @@ tdm_client_voutput_remove_commit_handler(tdm_client_voutput *voutput, TDM_RETURN_IF_FAIL(func != NULL); private_voutput = (tdm_private_client_voutput *)voutput; - private_client = private_voutput->base.private_client; + private_client = private_voutput->private_client; pthread_mutex_lock(&private_client->lock); @@ -2216,10 +2262,13 @@ tdm_error tdm_client_voutput_commit_done(tdm_client_voutput *voutput) { tdm_private_client_voutput *private_voutput; + tbm_surface_h buffer = NULL; TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); private_voutput = (tdm_private_client_voutput *)voutput; + buffer = (tbm_surface_h)wl_buffer_get_user_data(private_voutput->attach_buffer->wl_buffer); + tbm_surface_internal_unref(buffer); private_voutput->attach_buffer = NULL; wl_tdm_voutput_commit_done(private_voutput->wl_voutput); @@ -2230,12 +2279,13 @@ tdm_client_output * tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error) { tdm_private_client_voutput *private_voutput; + tdm_private_client_output *private_output = NULL; + tdm_error ret = TDM_ERROR_NONE; if (error) *error = TDM_ERROR_NONE; - if (!voutput) - { + if (!voutput) { TDM_ERR("'!voutput' failed"); if (error) *error = TDM_ERROR_INVALID_PARAMETER; @@ -2244,7 +2294,21 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err private_voutput = (tdm_private_client_voutput *)voutput; - return &private_voutput->base; + if (private_voutput->get_output) + return private_voutput->private_output; + + private_output = (tdm_private_client_output *)tdm_client_get_output(private_voutput->private_client, private_voutput->name, &ret); + if (!private_output) { + TDM_ERR("tdm_client_voutput_get_client_output get private_output fail"); + if (error) + *error = ret; + return NULL; + } + private_output->voutput = private_voutput; + private_voutput->private_output = private_output; + private_voutput->get_output = 1; + + return private_output; } tdm_error @@ -2289,12 +2353,13 @@ tdm_error tdm_client_output_connect(tdm_client_output *output) { tdm_private_client_output *private_output; - tdm_private_client_voutput *private_voutput; + tdm_private_client_voutput *private_voutput = NULL; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output *)output; - private_voutput = (tdm_private_client_voutput *)output; + if (!private_output->voutput) return TDM_ERROR_INVALID_PARAMETER; + private_voutput = private_output->voutput; TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_CONNECTED, TDM_ERROR_BAD_REQUEST); @@ -2305,6 +2370,7 @@ tdm_client_output_connect(tdm_client_output *output) wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight); + /* To Do : change voutput to output */ wl_tdm_voutput_connect(private_voutput->wl_voutput); return TDM_ERROR_NONE; @@ -2313,19 +2379,21 @@ tdm_client_output_connect(tdm_client_output *output) tdm_error tdm_client_output_disconnect(tdm_client_output *output) { - tdm_private_client_voutput *private_voutput; tdm_private_client_output *private_output; + tdm_private_client_voutput *private_voutput = NULL; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output *)output; - private_voutput = (tdm_private_client_voutput *)output; + if (!private_output->voutput) return TDM_ERROR_INVALID_PARAMETER; + private_voutput = private_output->voutput; TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BAD_REQUEST); private_output->connection = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + /* To Do : change voutput to output */ wl_tdm_voutput_disconnect(private_voutput->wl_voutput); return TDM_ERROR_NONE; diff --git a/client/tdm_client.h b/client/tdm_client.h index f431f1c..8c10ebe 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -429,9 +429,8 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, tdm unsigned int tdm_client_vblank_is_waiting(tdm_client_vblank *vblank); -/* Virtual Output */ -#include +/* Virtual Output */ tdm_client_voutput * tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error); diff --git a/client/tdm_client_types.h b/client/tdm_client_types.h index 096b44f..569cd1d 100644 --- a/client/tdm_client_types.h +++ b/client/tdm_client_types.h @@ -38,6 +38,8 @@ #include "tdm_common.h" +#include + #ifdef __cplusplus extern "C" { #endif @@ -124,6 +126,7 @@ typedef struct _tdm_client_output_mode { typedef void tdm_client_voutput; typedef void (*tdm_client_voutput_commit_handler)(tdm_client_voutput *voutput, + tbm_surface_h buffer, void *user_data); /* End of Virtual Output */ #ifdef __cplusplus diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 3d4aa47..01668cb 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -1584,7 +1584,7 @@ TEST_F(TDMVirtualOutput, FailTestSetPhysicalSize) } static void -_tc_tdm_client_voutput_commit_handler(tdm_client_voutput *voutput, void *user_data) +_tc_tdm_client_voutput_commit_handler(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_data) { int *flag; flag = (int *)user_data; -- 2.7.4 From 729ebaadb2cf64309af3064245486f7f5dfeba8b Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 16 Aug 2018 18:10:31 +0900 Subject: [PATCH 11/16] virtual: send voutput commit buffer to client cannot commit while commiting (after receive commit_done, can send next buffer) Change-Id: I522deef02429910b96ccf18e7a200fb79591e6bb Signed-off-by: Junkyeong Kim --- src/tdm_display.c | 15 ++++++++++++++- src/tdm_layer.c | 2 ++ src/tdm_output.c | 10 ++++++++-- src/tdm_private_types.h | 6 ++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/tdm_display.c b/src/tdm_display.c index 3373f88..9398a08 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -362,10 +362,12 @@ tdm_display_call_thread_cb_output_create(tdm_private_display *private_display, t tdm_thread_cb_display_output_create output_create; tdm_error ret; + if (LIST_IS_EMPTY(&private_display->output_create_handler_list)) return TDM_ERROR_NONE; + memset(&output_create, 0, sizeof output_create); output_create.base.type = TDM_THREAD_CB_DISPLAY_OUTPUT_CREATE; output_create.base.length = sizeof output_create; - output_create.base.object_stamp = 0; + output_create.base.object_stamp = tdm_helper_get_time(); output_create.base.data = NULL; output_create.base.sync = 1; output_create.output = output; @@ -810,6 +812,15 @@ tdm_display_find_output(tdm_display *dpy, const char *name, tdm_error *error) } } + if (private_display->virtual_module) { + private_module = private_display->virtual_module; + LIST_FOR_EACH_ENTRY(private_output, &private_module->output_list, link) { + if (strncmp(private_output->name, name, TDM_NAME_LEN)) + continue; + _pthread_mutex_unlock(&private_display->lock); + return private_output; + } + } _pthread_mutex_unlock(&private_display->lock); return NULL; @@ -855,6 +866,8 @@ tdm_display_create_output(tdm_display *dpy, const char *name, tdm_error *error) TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(output != NULL, ret, NULL); if (output_find != 1) private_output = NULL; + else + strncpy(private_output->name, name, TDM_NAME_LEN); return private_output; } diff --git a/src/tdm_layer.c b/src/tdm_layer.c index 429f885..ea70afa 100644 --- a/src/tdm_layer.c +++ b/src/tdm_layer.c @@ -949,6 +949,8 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da else private_layer->committing = 1; + private_layer->commiting_buffer = layer_commit_handler->committed_buffer->buffer; + if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("layer(%p,%d) waiting_buffer(%p) committed_buffer(%p)", private_layer, private_layer->index, private_layer->waiting_buffer, diff --git a/src/tdm_output.c b/src/tdm_output.c index 0185615..66ad21b 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1220,12 +1220,14 @@ _tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handl tdm_private_output *private_output; tdm_private_output_commit_handler *output_commit_handler = NULL; tdm_private_layer *private_layer = NULL; + tdm_private_display *private_display; tbm_surface_h buffer; tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_output*)output; + private_display = private_output->private_display; if (!LIST_IS_EMPTY(&private_output->output_commit_handler_list)) { /* support only 1 commit */ @@ -1252,14 +1254,16 @@ _tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handl if (private_layer) break; } TDM_GOTO_IF_FAIL(private_layer, commit_failed); - TDM_GOTO_IF_FAIL(private_layer->committed_buffer, commit_failed); - buffer = private_layer->committed_buffer->buffer; + buffer = private_layer->commiting_buffer; + TDM_GOTO_IF_FAIL(buffer != NULL, commit_failed); + _pthread_mutex_unlock(&private_display->lock); ret = tdm_output_send_buffer(private_output, buffer); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); ret = tdm_output_commit_buffer(private_output); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); + _pthread_mutex_lock(&private_display->lock); return ret; @@ -1890,6 +1894,8 @@ tdm_output_commit_done(tdm_output *output, tbm_surface_h buffer) if (private_layer) break; } + private_layer->commiting_buffer = NULL; + LIST_FOR_EACH_ENTRY(output_commit_handler, &private_output->output_commit_handler_list, link) { if (output_commit_handler) break; } diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index d74f4f2..743367b 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -233,6 +233,9 @@ struct _tdm_private_output { /* hwc */ int need_set_target_info; tdm_private_hwc *private_hwc; + + /* virtual */ + char name[TDM_NAME_LEN]; }; struct _tdm_private_layer { @@ -270,6 +273,9 @@ struct _tdm_private_layer { double fps_stamp; unsigned int fps_count; + + /* virtual */ + tbm_surface_h commiting_buffer; }; struct _tdm_private_hwc { -- 2.7.4 From ef9d531a0c44073ec79179e17280be66c9151f38 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 16 Aug 2018 21:00:23 +0900 Subject: [PATCH 12/16] virtual: add tdm virtual output test to tdm_test with V option 1. execute tdm-test-server with -V option 2. execute tdm-test-client with -V option after voutput connect from client, server send three differnt buffers to client. client make dump commit buffers untill 10 to /tmp/. Change-Id: I65775c8b28ef8d08c34aca9a706b770d99974a11 Signed-off-by: Junkyeong Kim --- tools/tdm_test_client.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++- tools/tdm_test_server.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 542 insertions(+), 1 deletion(-) diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index 1031685..bb0ba22 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -40,9 +40,11 @@ #include #include #include +#include #include "tdm_client.h" #include "tdm_macro.h" +#include "buffers.h" typedef struct _tdm_test_client_arg { char *output_name; @@ -60,6 +62,7 @@ typedef struct _tdm_test_client { int do_query; int do_vblank; + int do_voutput; int waiting; tdm_client *client; @@ -93,6 +96,7 @@ static struct typestrings typestrs[] = { static struct optstrings optstrs[] = { {OPT_QRY, "qo", "output objects info", "", "primary"}, {OPT_TST, "v", "vblank test", "[,][@][~][+][*fake][^vblank_name]", "primary,0@60~1+0*1^test"}, + {OPT_TST, "V", "virtual output test", NULL, NULL}, }; static void @@ -181,7 +185,7 @@ parse_args(tdm_test_client *data, int argc, char *argv[]) { int i; - if (argc < 3) { + if (argc < 2) { usage(argv[0]); exit(0); } @@ -196,6 +200,8 @@ parse_args(tdm_test_client *data, int argc, char *argv[]) } else if (!strncmp(argv[i] + 1, "v", 1)) { data->do_vblank = 1; parse_arg_v(data, argv[++i]); + } else if (!strncmp(argv[i] + 1, "V", 1)) { + data->do_voutput = 1; } else { usage(argv[0]); exit(0); @@ -374,6 +380,259 @@ done: tdm_client_vblank_destroy(vblank); } +#define PNG_DEPTH 8 + +void +_tdm_client_get_buffer_full_size(tbm_surface_h buffer, int *buffer_w, int *buffer_h) +{ + tbm_surface_info_s info; + int ret; + + TDM_RETURN_IF_FAIL(buffer != NULL); + + ret = tbm_surface_get_info(buffer, &info); + TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE); + + if (buffer_w) { + if (IS_RGB(info.format)) + *buffer_w = info.planes[0].stride >> 2; + else + *buffer_w = info.planes[0].stride; + } + + if (buffer_h) + *buffer_h = info.planes[0].size / info.planes[0].stride; +} + +static void +_tdm_client_dump_png(const char *file, const void *data, int width, + int height) +{ + FILE *fp; + + fp = fopen(file, "wb"); + TDM_RETURN_IF_FAIL(fp != NULL); + + png_structp pPngStruct = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!pPngStruct) { + fclose(fp); + return; + } + + png_infop pPngInfo = png_create_info_struct(pPngStruct); + if (!pPngInfo) { + png_destroy_write_struct(&pPngStruct, NULL); + fclose(fp); + return; + } + + png_init_io(pPngStruct, fp); + png_set_IHDR(pPngStruct, + pPngInfo, + width, + height, + PNG_DEPTH, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_set_bgr(pPngStruct); + png_write_info(pPngStruct, pPngInfo); + + const int pixel_size = 4; // RGBA + png_bytep *row_pointers = + png_malloc(pPngStruct, height * sizeof(png_byte *)); + if (!row_pointers) { + png_destroy_write_struct(&pPngStruct, &pPngInfo); + fclose(fp); + return; + } + + unsigned int *blocks = (unsigned int *)data; + int y = 0; + int x = 0; + + for (; y < height; ++y) { + png_bytep row = + png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size); + if (!row) { + for (x = 0; x < y; x++) + png_free(pPngStruct, row_pointers[x]); + png_free(pPngStruct, row_pointers); + png_destroy_write_struct(&pPngStruct, &pPngInfo); + fclose(fp); + return; + } + + row_pointers[y] = (png_bytep)row; + for (x = 0; x < width; ++x) { + unsigned int curBlock = blocks[y * width + x]; + row[x * pixel_size] = (curBlock & 0xFF); + row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF; + row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF; + row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF; + } + } + + png_write_image(pPngStruct, row_pointers); + png_write_end(pPngStruct, pPngInfo); + + for (y = 0; y < height; y++) + png_free(pPngStruct, row_pointers[y]); + png_free(pPngStruct, row_pointers); + + png_destroy_write_struct(&pPngStruct, &pPngInfo); + + fclose(fp); +} + +void +_tdm_client_dump_buffer(tbm_surface_h buffer, const char *file) +{ + char temp[TDM_PATH_LEN] = {0,}; + tbm_surface_info_s info; + int len, ret; + const char *ext; + int bo_cnt; + int bw, bh; + char *dot, *p = temp; + const char *file_exts[2] = {"png", "raw"}; + + TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_IF_FAIL(file != NULL); + + ret = tbm_surface_map(buffer, TBM_OPTION_READ, &info); + TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE); + + if (IS_RGB(info.format)) + ext = file_exts[0]; + else + ext = file_exts[1]; + + dot = strrchr(file, '.'); + if (!dot || strlen(dot + 1) != 3 || strncmp(dot + 1, ext, 3)) { + len = strnlen(file, TDM_PATH_LEN - 5); + strncat(p, file, len); + p += len; + *(p++) = '.'; + strncat(p, ext, 3); + p += 3; + *p = '\0'; + } else { + len = strnlen(file, TDM_PATH_LEN - 1); + strncat(p, file, len); + p += len; + *p = '\0'; + } + + _tdm_client_get_buffer_full_size(buffer, &bw, &bh); + + bo_cnt = tbm_surface_internal_get_num_bos(buffer); + TDM_DBG("buffer: bo_cnt(%d) %dx%d(%dx%d) %c%c%c%c, plane: (%p+%d, %d,%d) (%p+%d, %d,%d) (%p+%d, %d,%d)", + bo_cnt, bw, bh, info.width, info.height, FOURCC_STR(info.format), + info.planes[0].ptr, info.planes[0].offset, info.planes[0].stride, info.planes[0].size, + info.planes[1].ptr, info.planes[1].offset, info.planes[1].stride, info.planes[1].size, + info.planes[2].ptr, info.planes[2].offset, info.planes[2].stride, info.planes[2].size); + + _tdm_client_dump_png(temp, info.planes[0].ptr, bw, bh); + + tbm_surface_unmap(buffer); + + printf("dump %s", temp); +} + +static void +_dump_buffer(tbm_surface_h buffer, int count) +{ + char temp[TDM_PATH_LEN] = {0,}; + + snprintf(temp, TDM_PATH_LEN, "/tmp/%c%c%c%c_%dx%d_%d", + FOURCC_STR(tbm_surface_get_format(buffer)), + tbm_surface_get_width(buffer), + tbm_surface_get_height(buffer), + count); + _tdm_client_dump_buffer(buffer, temp); +} + +static void +_voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_data) +{ + tdm_test_client *data = (tdm_test_client *)user_data; + static int count = 0; + + TDM_EXIT_IF_FAIL(data != NULL); + TDM_EXIT_IF_FAIL(buffer != NULL); + + if (count < 11) + _dump_buffer(buffer, count); + count++; + + printf("client: %d commited(%p)\n", count, buffer); + tdm_client_voutput_commit_done(voutput); +} + + static void +_voutput_make_available_mode(tdm_client_output_mode *modes, int count) +{ + int i; + for (i = 0; i < count; i++) { + modes[i].clock = 25200; + modes[i].hdisplay = 640; + modes[i].hsync_start = 656; + modes[i].hsync_end = 752; + modes[i].htotal = 800; + modes[i].hskew = 0; + modes[i].vdisplay = 480; + modes[i].vsync_start = 490; + modes[i].vsync_end = 492; + modes[i].vtotal = 525; + modes[i].vscan = 0; + modes[i].vrefresh = 30; + modes[i].flags = 0; + modes[i].type = 0; + snprintf(modes[i].name, TDM_NAME_LEN, "%dx%d_%d", modes[i].hdisplay, modes[i].vdisplay, i); + } +} + +static void +do_voutput(tdm_test_client *data) +{ + tdm_client_voutput *voutput = NULL; + tdm_client_output *output = NULL; + tdm_client_output_mode modes[2]; + tdm_error ret = TDM_ERROR_NONE; + + printf("virtual output test - client\n"); + + voutput = tdm_client_create_voutput(data->client, "virtual-test", &ret); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + ret = tdm_client_voutput_add_commit_handler(voutput, _voutput_commit, data); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + output = tdm_client_voutput_get_client_output(voutput, &ret); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + ret = tdm_client_voutput_set_physical_size(voutput, 300, 200); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + _voutput_make_available_mode(modes, 2); + ret = tdm_client_voutput_set_available_modes(voutput, modes, 2); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + ret = tdm_client_output_connect(output); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + + while (1) { + tdm_client_handle_events_timeout(data->client, 1000); + } + +done: + if (voutput) + tdm_client_voutput_destroy(voutput); +} + static tdm_test_client ttc_data; int @@ -391,6 +650,16 @@ main(int argc, char *argv[]) if (ret != 0) exit(0); } + + /* for tbm_bufmgr_init */ + const char *s = (const char*)getenv("TBM_DISPLAY_SERVER"); + if (!s) { + char buf[32]; + snprintf(buf, sizeof(buf), "1"); + int ret = setenv("TBM_DISPLAY_SERVER", (const char*)buf, 1); + if (ret != 0) + exit(0); + } #endif parse_args(data, argc, argv); @@ -409,6 +678,8 @@ main(int argc, char *argv[]) do_query(data); if (data->do_vblank) do_vblank(data); + if (data->do_voutput) + do_voutput(data); done: if (data->args.output_name) diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index 535462f..b439540 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -108,6 +108,10 @@ static struct optstrings optstrs[] = { "[,]~x[++][,x][@][*][^stream]", NULL }, { + OPT_TST, "V", "virtual output test.\n\t\t'-l' is used to show the result on screen.", + NULL, NULL + }, + { OPT_GEN, "w", "set the property of a object", ":", NULL }, @@ -217,6 +221,7 @@ TDM_BIT_NAME_FB(buf_flag) typedef struct _tdm_test_server tdm_test_server; typedef struct _tdm_test_server_layer tdm_test_server_layer; typedef struct _tdm_test_server_capture tdm_test_server_capture; +typedef struct _tdm_test_server_voutput tdm_test_server_voutput; typedef struct _tdm_test_server_prop { /* args */ @@ -300,11 +305,21 @@ struct _tdm_test_server_layer { int buf_idx; }; +struct _tdm_test_server_voutput { + struct list_head link; + tdm_test_server *data; + tdm_output *output; + tdm_layer *layer; + tbm_surface_h bufs[3]; + int buf_idx; +}; + struct _tdm_test_server { /* args */ int do_query; int do_all; int do_vblank; + int do_voutput; int bflags; int b_fill; @@ -312,6 +327,7 @@ struct _tdm_test_server { struct list_head output_list; struct list_head pp_list; struct list_head capture_list; + struct list_head voutput_list; tdm_display *display; }; @@ -320,6 +336,7 @@ static void run_test(tdm_test_server *data); static void output_setup(tdm_test_server_output *o); static void layer_show_buffer(tdm_test_server_layer *l, tbm_surface_h b); static void capture_attach(tdm_test_server_capture *c, tbm_surface_h b); +static void _vlayer_show_buffer(tdm_test_server_voutput *voutput); static char* parse_size(tdm_size *size, char *arg) @@ -596,6 +613,8 @@ parse_args(tdm_test_server *data, int argc, char *argv[]) parse_arg_b(data, argv[++i]); } else if (!strncmp(argv[i] + 1, "v", 1)) { data->do_vblank = 1; + } else if (!strncmp(argv[i] + 1, "V", 1)) { + data->do_voutput = 1; } else { usage(argv[0]); destroy(data); @@ -790,6 +809,238 @@ get_tts_buffer(tbm_surface_h b) } static void +_vlayer_cb_commit(tdm_layer *layer, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + tdm_test_server_voutput *voutput = (tdm_test_server_voutput *)user_data; + TDM_EXIT_IF_FAIL(voutput != NULL); + tdm_output_conn_status status; + tdm_error ret; + + printf("voutput cb commit:\t %d: l(%p) b(%p)\n", voutput->buf_idx, voutput->layer, voutput->bufs[voutput->buf_idx]); + + ret = tdm_output_get_conn_status(voutput->output, &status); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) return; + + voutput->buf_idx++; + _vlayer_show_buffer(voutput); +} + +static void +_vlayer_show_buffer(tdm_test_server_voutput *voutput) +{ + tdm_error ret; + int index; + if (voutput->buf_idx == 3) + voutput->buf_idx = 0; + + index = voutput->buf_idx; + + ret = tdm_layer_set_buffer(voutput->layer, voutput->bufs[index]); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + ret = tdm_layer_commit(voutput->layer, _vlayer_cb_commit, voutput); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + printf("voutput show:\t %d: l(%p) b(%p)\n", index, voutput->layer, voutput->bufs[index]); +} + +static void +_voutput_buff_init(tdm_test_server_voutput *voutput) +{ + tdm_output *output = voutput->output; + const tdm_output_mode *mode; + tdm_error ret = TDM_ERROR_NONE; + int i; + + ret = tdm_output_get_mode(output, &mode); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + for (i = 0; i < 3; i++) { + tbm_surface_h b = tbm_surface_internal_create_with_flags(mode->hdisplay, mode->vdisplay, DEFAULT_FORMAT, 0); + TDM_EXIT_IF_FAIL(b != NULL); + tdm_test_buffer_fill(b, i); + voutput->bufs[i] = b; + } +} + +static void +_voutput_layer_init(tdm_test_server_voutput *voutput) +{ + tdm_output *output = voutput->output; + const tdm_output_mode *mode; + tdm_info_layer layer_info; + tbm_surface_info_s info; + tdm_error ret = TDM_ERROR_NONE; + + ret = tdm_output_get_mode(output, &mode); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + TDM_ERR("modeinfo : %dx%d %d", mode->hdisplay, mode->vdisplay, mode->vrefresh); + + voutput->layer = tdm_output_get_layer(output, 0, &ret); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + _voutput_buff_init(voutput); + + tbm_surface_get_info(voutput->bufs[0], &info); + memset(&layer_info, 0x0, sizeof(tdm_info_layer)); + if (IS_RGB(info.format)) { + layer_info.src_config.size.h = info.planes[0].stride >> 2; + layer_info.src_config.size.v = info.height; + } else { + layer_info.src_config.size.h = info.planes[0].stride; + layer_info.src_config.size.v = info.height; + } + layer_info.src_config.format = info.format; + + layer_info.src_config.size.h = mode->hdisplay; + layer_info.src_config.size.v = mode->vdisplay; + layer_info.src_config.pos.x = 0; + layer_info.src_config.pos.y = 0; + layer_info.src_config.pos.w = mode->hdisplay; + layer_info.src_config.pos.h = mode->vdisplay; + layer_info.dst_pos.x = 0; + layer_info.dst_pos.y = 0; + layer_info.dst_pos.w = mode->hdisplay; + layer_info.dst_pos.h = mode->vdisplay; + layer_info.transform = TDM_TRANSFORM_NORMAL; + + ret = tdm_layer_set_info(voutput->layer, &layer_info); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void +_voutput_connect(tdm_test_server_voutput *voutput) +{ + tdm_output *output; + const tdm_output_mode *modes, *found = NULL, *best = NULL, *prefer = NULL; + int i, count; + tdm_error ret; + + output = voutput->output; + + ret = tdm_output_get_available_modes(output, &modes, &count); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + for (i = 0; i < count; i++) { + if (!best) + best = &modes[i]; + if (modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) + prefer = &modes[i]; + } + if (prefer) { + found = prefer; + printf("found prefer mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh); + } + if (!found && best) { + found = best; + printf("found best mode: %dx%d %d\n", found->hdisplay, found->vdisplay, found->vrefresh); + } + if (!found) { + printf("couldn't find any mode\n"); + exit(0); + } + + ret = tdm_output_set_mode(output, found); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + printf("output: %s %d\n", found->name, found->vrefresh); + + ret = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void +_voutput_disconnect(tdm_test_server_voutput *voutput) +{ + tdm_output *output; + tdm_error ret; + + output = voutput->output; + + ret = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); +} + +static void +_tdm_test_server_cb_output_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data) +{ + tdm_test_server_voutput *voutput = NULL; + tdm_output_conn_status status; + + voutput = (tdm_test_server_voutput *)user_data; + TDM_EXIT_IF_FAIL(voutput != NULL); + + switch (type) { + case TDM_OUTPUT_CHANGE_CONNECTION: + status = (tdm_output_conn_status)value.u32; + if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) { + _voutput_connect(voutput); + _voutput_layer_init(voutput); + _vlayer_show_buffer(voutput); + } else if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + _voutput_disconnect(voutput); + } + break; + default: + break; + } +} + +static void +_tdm_output_cb_destroy_handler(tdm_output *output, void *user_data) +{ + tdm_test_server_voutput *voutput = NULL; + int i; + + voutput = (tdm_test_server_voutput *)user_data; + TDM_EXIT_IF_FAIL(voutput != NULL); + + tdm_output_remove_change_handler(output, _tdm_test_server_cb_output_change, voutput); + tdm_output_remove_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput); + + LIST_DEL(&voutput->link); + + for (i = 0; i < 3; i++) { + tbm_surface_destroy(voutput->bufs[i]); + } + + free(voutput); +} + +static void +_tdm_output_cb_create_handler(tdm_display *dpy, tdm_output *output, void *user_data) +{ + tdm_test_server *data; + tdm_test_server_voutput *voutput = NULL; + tdm_error ret = TDM_ERROR_NONE; + + printf("voutput create call\n"); + + data = (tdm_test_server *)user_data; + TDM_EXIT_IF_FAIL(data != NULL); + + voutput = calloc(1, sizeof *voutput); + TDM_EXIT_IF_FAIL(voutput != NULL); + + ret = tdm_output_add_change_handler(output, _tdm_test_server_cb_output_change, voutput); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + ret = tdm_output_add_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + voutput->output = output; + voutput->data = data; + + printf("voutput create done\n"); + + LIST_ADDTAIL(&voutput->link, &data->voutput_list); +} + +static void destroy(tdm_test_server *data) { tdm_test_server_output *o = NULL, *oo = NULL; @@ -797,6 +1048,7 @@ destroy(tdm_test_server *data) tdm_test_server_pp *p = NULL, *pp = NULL; tdm_test_server_capture *c = NULL, *cc = NULL; tdm_test_server_prop *w = NULL, *ww = NULL; + tdm_test_server_voutput *v = NULL, *vv = NULL; tdm_error ret; int i; @@ -850,6 +1102,17 @@ destroy(tdm_test_server *data) free(o); } + LIST_FOR_EACH_ENTRY_SAFE(v, vv, &data->voutput_list, link) { + for (int i = 0; i < 3; i++) { + tbm_surface_destroy(v->bufs[i]); + } + LIST_DEL(&v->link); + free(v); + } + + if (data->do_voutput) + tdm_display_remove_output_create_handler(data->display, _tdm_output_cb_create_handler, data); + if (data->display) tdm_display_deinit(data->display); @@ -888,6 +1151,7 @@ main(int argc, char *argv[]) LIST_INITHEAD(&data->output_list); LIST_INITHEAD(&data->pp_list); LIST_INITHEAD(&data->capture_list); + LIST_INITHEAD(&data->voutput_list); /* init value */ data->bflags = TBM_BO_SCANOUT; @@ -905,6 +1169,12 @@ main(int argc, char *argv[]) goto done; } + if (data->do_voutput) { + printf("support virtual output - server\n"); + ret = tdm_display_add_output_create_handler(data->display, _tdm_output_cb_create_handler, data); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + } + run_test(data); done: -- 2.7.4 From 7a73695132cffbca3953d44f42ad8987b69e468a Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Tue, 21 Aug 2018 17:48:31 +0900 Subject: [PATCH 13/16] virtual: add voutput disconnect and destroy test to tdm_test change function name to tdm_output_attach_buffer. fix voutput buffer handling error of tdm_server. Change-Id: I081e9a1e0c562df1b31513f2161240ba422cb4d1 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 6 ++++-- src/tdm_output.c | 2 +- src/tdm_private.h | 2 +- src/tdm_server.c | 25 +++++++++++++++++++------ tools/tdm_test_client.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- tools/tdm_test_server.c | 6 +++++- 6 files changed, 75 insertions(+), 13 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index d94925a..a187cb6 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -2364,7 +2364,8 @@ tdm_client_output_connect(tdm_client_output *output) TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_CONNECTED, TDM_ERROR_BAD_REQUEST); - private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; + if (!private_output->watch_output_changes) + private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; _tdm_client_voutput_send_available_modes(private_voutput); @@ -2391,7 +2392,8 @@ tdm_client_output_disconnect(tdm_client_output *output) TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED, TDM_ERROR_BAD_REQUEST); - private_output->connection = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + if (!private_output->watch_output_changes) + private_output->connection = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; /* To Do : change voutput to output */ wl_tdm_voutput_disconnect(private_voutput->wl_voutput); diff --git a/src/tdm_output.c b/src/tdm_output.c index 66ad21b..902543e 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1259,7 +1259,7 @@ _tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handl TDM_GOTO_IF_FAIL(buffer != NULL, commit_failed); _pthread_mutex_unlock(&private_display->lock); - ret = tdm_output_send_buffer(private_output, buffer); + ret = tdm_output_attach_buffer(private_output, buffer); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); ret = tdm_output_commit_buffer(private_output); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed); diff --git a/src/tdm_private.h b/src/tdm_private.h index 3cfd101..a5c59e3 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -269,7 +269,7 @@ 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 buffer); +tdm_output_attach_buffer(tdm_output *output, tbm_surface_h buffer); tdm_error tdm_output_commit_buffer(tdm_output *output); tdm_error diff --git a/src/tdm_server.c b/src/tdm_server.c index 09c6e3c..e51d868 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -214,7 +214,7 @@ _tdm_server_cb_output_change(tdm_output *output, tdm_output_change_type type, return; } - TDM_DBG("send the output changes: %d", (unsigned int)pid); + TDM_DBG("send the output changes: %d, type:%d, value:%d", (unsigned int)pid, type, value.u32); switch (type) { case TDM_OUTPUT_CHANGE_DPMS: @@ -784,6 +784,13 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc voutput_info->mmwidth = 0; voutput_info->mmheight = 0; + if (voutput_info->attach_buffer) { + tbm_surface_h buffer = voutput_info->attach_buffer->buffer; + tbm_surface_internal_unref(buffer); + voutput_info->committing = 0; + voutput_info->attach_buffer = NULL; + } + tdm_output_set_disconnect(voutput_info->output); } @@ -794,15 +801,13 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour tbm_surface_h buffer; voutput_info = wl_resource_get_user_data(resource); - if (voutput_info->status != TDM_OUTPUT_CONN_STATUS_CONNECTED) - { - // handle error + if (voutput_info->status != TDM_OUTPUT_CONN_STATUS_CONNECTED) { + TDM_DBG("not connected."); return; } buffer = voutput_info->attach_buffer->buffer; tbm_surface_internal_unref(buffer); - voutput_info->committing = 0; voutput_info->attach_buffer = NULL; @@ -1028,7 +1033,7 @@ _tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surfac } INTERN tdm_error -tdm_output_send_buffer(tdm_output *output, tbm_surface_h buffer) +tdm_output_attach_buffer(tdm_output *output, tbm_surface_h buffer) { tdm_private_server *private_server = keep_private_server; tdm_server_voutput_info *voutput_info = NULL, *vo = NULL; @@ -1073,6 +1078,7 @@ tdm_output_commit_buffer(tdm_output *output) TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer != NULL, TDM_ERROR_OPERATION_FAILED); TDM_RETURN_VAL_IF_FAIL(voutput_info->committing == 0, TDM_ERROR_OPERATION_FAILED); + tbm_surface_internal_ref(voutput_info->attach_buffer->buffer); voutput_info->committing = 1; wl_tdm_voutput_send_commit(voutput_info->resource); @@ -1099,6 +1105,13 @@ tdm_voutput_cb_resource_destroy(struct wl_resource *resource) if (ret != TDM_ERROR_NONE) TDM_ERR("_tdm_voutput_cb_destroy fail"); + if (voutput_info->attach_buffer) { + tbm_surface_h buffer = voutput_info->attach_buffer->buffer; + tbm_surface_internal_unref(buffer); + voutput_info->committing = 0; + voutput_info->attach_buffer = NULL; + } + LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) { if (!vb) continue; diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index bb0ba22..cac60a8 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -66,6 +66,8 @@ typedef struct _tdm_test_client { int waiting; tdm_client *client; + tdm_client_voutput *voutput; + tdm_client_output *output; } tdm_test_client; struct typestrings { @@ -564,14 +566,49 @@ _voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_da TDM_EXIT_IF_FAIL(data != NULL); TDM_EXIT_IF_FAIL(buffer != NULL); - if (count < 11) + if (count < 10) _dump_buffer(buffer, count); count++; - printf("client: %d commited(%p)\n", count, buffer); + if (count == 70) { + printf("client: %d commited(%p), disconnect\n", count, buffer); + tdm_client_output_disconnect(data->output); + } else { + printf("client: %d commited(%p)\n", count, buffer); + } + tdm_client_voutput_commit_done(voutput); } +static void +_voutput_output_handler(tdm_client_output *output, tdm_output_change_type type, + tdm_value value, void *user_data) +{ + tdm_client_voutput *voutput = NULL; + tdm_output_conn_status status; + tdm_test_client *data; + + data = (tdm_test_client *) user_data; + TDM_RETURN_IF_FAIL(data != NULL); + voutput = data->voutput; + TDM_RETURN_IF_FAIL(voutput != NULL); + + if (type == TDM_OUTPUT_CHANGE_CONNECTION) { + status = (tdm_output_conn_status)value.u32; + printf("output %s.\n", conn_str[value.u32]); + + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + printf("client: disconnected, destroy voutput\n"); + tdm_client_output_remove_change_handler(output, _voutput_output_handler, data); + tdm_client_voutput_destroy(voutput); + } else if (status == TDM_OUTPUT_CONN_STATUS_CONNECTED) { + printf("client: connected\n"); + } + } else if (type == TDM_OUTPUT_CHANGE_DPMS) { + printf("output %s.\n", dpms_str[value.u32]); + } +} + static void _voutput_make_available_mode(tdm_client_output_mode *modes, int count) { @@ -614,6 +651,9 @@ do_voutput(tdm_test_client *data) output = tdm_client_voutput_get_client_output(voutput, &ret); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + ret = tdm_client_output_add_change_handler(output, _voutput_output_handler, data); + TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + ret = tdm_client_voutput_set_physical_size(voutput, 300, 200); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); @@ -624,6 +664,9 @@ do_voutput(tdm_test_client *data) ret = tdm_client_output_connect(output); TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, done); + data->voutput = voutput; + data->output = output; + while (1) { tdm_client_handle_events_timeout(data->client, 1000); } diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index b439540..98b10db 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -961,6 +961,8 @@ _voutput_disconnect(tdm_test_server_voutput *voutput) output = voutput->output; + printf("output: %p disconnect\n", voutput); + ret = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF); TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); } @@ -1008,6 +1010,8 @@ _tdm_output_cb_destroy_handler(tdm_output *output, void *user_data) tbm_surface_destroy(voutput->bufs[i]); } + printf("voutput: %p destroy\n", voutput); + free(voutput); } @@ -1035,7 +1039,7 @@ _tdm_output_cb_create_handler(tdm_display *dpy, tdm_output *output, void *user_d voutput->output = output; voutput->data = data; - printf("voutput create done\n"); + printf("voutput %p create done\n", voutput); LIST_ADDTAIL(&voutput->link, &data->voutput_list); } -- 2.7.4 From e21703af4902508822f6c9942b94496da4e4342e Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Thu, 23 Aug 2018 18:02:10 +0900 Subject: [PATCH 14/16] virtual: add get_available_modes and set_mode protocol. add tc for tdm_client_output_get_available_modes. Change-Id: Id5a4616b89ecf0c4b8a3f853f6a37fd27049f3e1 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 121 ++++++++++++++++++++++++++++++++++------- client/tdm_client.h | 2 +- haltests/src/tc_tdm_client.cpp | 39 +++++++++++++ protocol/tdm.xml | 11 ++++ src/tdm_server.c | 49 +++++++++++++++++ 5 files changed, 202 insertions(+), 20 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index a187cb6..f5c69db 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -95,6 +95,11 @@ typedef struct _tdm_private_client_output { unsigned int req_id; unsigned int watch_output_changes; + struct { + int count; + tdm_client_output_mode *modes; + } available_modes; + tdm_private_client_voutput *voutput; } tdm_private_client_output; @@ -436,10 +441,41 @@ _tdm_client_output_cb_dpms(void *data, struct wl_tdm_output *wl_tdm_output, uint pthread_mutex_lock(&private_client->lock); } +static void +_tdm_client_output_cb_availablie_modes(void *data, struct wl_tdm_output *wl_tdm_output, struct wl_array *modes, uint32_t error) +{ + tdm_private_client_output *private_output = (tdm_private_client_output*)data; + tdm_output_mode *mode; + int size, count = 0, i = 0; + + if (error != TDM_ERROR_NONE) + TDM_INFO("get availablie_modes event error: %d", error); + + private_output->available_modes.count = 0; + if (private_output->available_modes.modes) + free(private_output->available_modes.modes); + + wl_array_for_each(mode, modes) + count++; + if (count == 0) { + TDM_INFO("no output mode"); + return; + } + + size = sizeof(tdm_output_mode); + + private_output->available_modes.modes = malloc(count * size); + private_output->available_modes.count = count; + + wl_array_for_each(mode, modes) + memcpy(&private_output->available_modes.modes[i++], mode, size); +} + static const struct wl_tdm_output_listener tdm_client_output_listener = { _tdm_client_output_cb_mode, _tdm_client_output_cb_connection, _tdm_client_output_cb_dpms, + _tdm_client_output_cb_availablie_modes, }; static void @@ -1144,6 +1180,72 @@ tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms) return TDM_ERROR_NONE; } +tdm_error +tdm_client_output_get_available_modes(tdm_client_output *output, tdm_client_output_mode **modes, int *count) +{ + tdm_private_client_output *private_output; + tdm_private_client *private_client; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); + + + private_output = (tdm_private_client_output *)output; + private_client = private_output->private_client; + if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + *modes = NULL; + *count = 0; + return TDM_ERROR_NONE; + } + + pthread_mutex_lock(&private_client->lock); + + if (CHECK_WL_PROTOCOL_ERROR(private_client)) { + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_PROTOCOL_ERROR; + } + + wl_proxy_set_queue((struct wl_proxy *)private_output->output, private_client->queue); + wl_tdm_output_get_available_modes(private_output->output); + wl_display_roundtrip_queue(private_client->display, private_client->queue); + wl_proxy_set_queue((struct wl_proxy *)private_output->output, NULL); + + if (CHECK_WL_PROTOCOL_ERROR(private_client)) { + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_PROTOCOL_ERROR; + } + + *modes = (tdm_client_output_mode *)private_output->available_modes.modes; + *count = private_output->available_modes.count; + + pthread_mutex_unlock(&private_client->lock); + + return TDM_ERROR_NONE; +} + +tdm_error +tdm_client_output_set_mode(tdm_client_output *output, int index) +{ + tdm_private_client_output *private_output; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(index < 0, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_client_output*)output; + + if (private_output->available_modes.count - 1 < index) + return TDM_ERROR_INVALID_PARAMETER; + + if ((private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) || + (private_output->available_modes.count == 0)) + return TDM_ERROR_BAD_REQUEST; + + wl_tdm_output_set_mode(private_output->output, index); + + return TDM_ERROR_NONE; +} + tdm_client_vblank* tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) { @@ -2311,25 +2413,6 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err return private_output; } -tdm_error -tdm_client_output_get_available_modes(tdm_client_output *output, tdm_client_output_mode **modes, int *count) -{ - TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER); - - return TDM_ERROR_NONE; -} - -tdm_error -tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mode *mode) -{ - TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(mode != NULL, TDM_ERROR_INVALID_PARAMETER); - - return TDM_ERROR_NONE; -} - void _tdm_client_voutput_send_available_modes(tdm_private_client_voutput *private_voutput) { diff --git a/client/tdm_client.h b/client/tdm_client.h index 8c10ebe..b52785a 100644 --- a/client/tdm_client.h +++ b/client/tdm_client.h @@ -462,7 +462,7 @@ tdm_error tdm_client_output_get_available_modes(tdm_client_output *output, tdm_client_output_mode **modes, int *count); tdm_error -tdm_client_output_set_mode(tdm_client_output *output, const tdm_client_output_mode *mode); +tdm_client_output_set_mode(tdm_client_output *output, int index); tdm_error tdm_client_output_connect(tdm_client_output *output); diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 01668cb..883ac5c 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -802,6 +802,45 @@ TEST_P(TDMClient, ClientOutputGetDpmsNullOther) ASSERT_EQ(tdm_client_output_get_dpms(output, NULL), TDM_ERROR_INVALID_PARAMETER); } +TEST_P(TDMClient, ClientOutputGetAvailableModes) +{ + tdm_client_output_mode *modes; + int i, count = 0; + + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_get_available_modes(output, &modes, &count), TDM_ERROR_NONE); + ASSERT_GT(count, 0); + + for (i = 0; i < count; i++) { + tdm_client_output_mode *mode = (tdm_client_output_mode *)&modes[i]; + ASSERT_GT(mode->hdisplay, 0); + ASSERT_GT(mode->vdisplay, 0); + ASSERT_GT(mode->vrefresh, 0); + } +} + +TEST_P(TDMClient, ClientOutputGetAvailableModesNullObject) +{ + tdm_client_output_mode *modes; + int count = TDM_UT_INVALID_VALUE; + + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_get_available_modes(NULL, &modes, &count), TDM_ERROR_INVALID_PARAMETER); + ASSERT_EQ(count, TDM_UT_INVALID_VALUE); +} + +TEST_P(TDMClient, ClientOutputGetAvailableModesNullOther) +{ + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_get_available_modes(output, NULL, NULL), TDM_ERROR_INVALID_PARAMETER); +} + /* tdm_client_output_create_vblank */ TEST_P(TDMClient, ClientOutputCreateVblank) { diff --git a/protocol/tdm.xml b/protocol/tdm.xml index a152c95..8272eec 100644 --- a/protocol/tdm.xml +++ b/protocol/tdm.xml @@ -53,6 +53,11 @@ + + + + + @@ -69,6 +74,12 @@ + + + + + + diff --git a/src/tdm_server.c b/src/tdm_server.c index e51d868..a71eb0e 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -596,6 +596,53 @@ failed: wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF, ret); } +static void +_tdm_server_output_cb_get_available_modes(struct wl_client *client, struct wl_resource *resource) +{ + tdm_server_output_info *output_info = wl_resource_get_user_data(resource); + const tdm_output_mode *modes; + tdm_output_mode *mode; + struct wl_array array; + int i, size, count = 0; + tdm_error ret; + + ret = tdm_output_get_available_modes(output_info->output, &modes, &count); + + if ((ret != TDM_ERROR_NONE) || (count == 0)) { + wl_tdm_output_send_available_modes(output_info->resource, NULL, ret); + return; + } + + size = sizeof(tdm_output_mode); + wl_array_init(&array); + for (i = 0; i < count; i++) { + mode = wl_array_add(&array, size); + memcpy(mode, &modes[i], size); + } + + wl_tdm_output_send_available_modes(output_info->resource, &array, ret); + + wl_array_release(&array); +} + +static void +_tdm_server_output_cb_set_mode(struct wl_client *client, struct wl_resource *resource, unsigned int index) +{ + 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_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_RETURN_IF_FAIL(status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED); + + //To do + + return; +} + static const struct wl_tdm_output_interface tdm_output_implementation = { _tdm_server_output_cb_destroy, _tdm_server_output_cb_create_vblank, @@ -603,6 +650,8 @@ static const struct wl_tdm_output_interface tdm_output_implementation = { _tdm_server_output_cb_get_connection, _tdm_server_output_cb_get_mode, _tdm_server_output_cb_get_dpms, + _tdm_server_output_cb_get_available_modes, + _tdm_server_output_cb_set_mode, }; static void -- 2.7.4 From fed869744d5e1d1939c39a8fda793aa0caee6cc1 Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 24 Aug 2018 18:36:59 +0900 Subject: [PATCH 15/16] virtual: support tdm_client output_set_mode use mode index.(server and client know both full mode list) tdm server must set mode_change_request_handler if output mode change from client is possible. add tc for output_set_mode Change-Id: I1767e6a6a561cb396b708769b90cfeac16bdf47f Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 8 +++- haltests/src/tc_tdm_client.cpp | 31 +++++++++++++ include/tdm.h | 10 +++++ include/tdm_types.h | 6 +++ src/tdm.c | 1 + src/tdm_output.c | 98 +++++++++++++++++++++++++++++++++++++++++- src/tdm_private.h | 4 ++ src/tdm_private_types.h | 10 +++++ src/tdm_server.c | 8 +++- 9 files changed, 172 insertions(+), 4 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index f5c69db..136a08a 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1228,11 +1228,15 @@ tdm_error tdm_client_output_set_mode(tdm_client_output *output, int index) { tdm_private_client_output *private_output; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(index < 0, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(index >= 0, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output*)output; + private_client = private_output->private_client; + + pthread_mutex_lock(&private_client->lock); if (private_output->available_modes.count - 1 < index) return TDM_ERROR_INVALID_PARAMETER; @@ -1243,6 +1247,8 @@ tdm_client_output_set_mode(tdm_client_output *output, int index) wl_tdm_output_set_mode(private_output->output, index); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index 883ac5c..c2b2c20 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -841,6 +841,37 @@ TEST_P(TDMClient, ClientOutputGetAvailableModesNullOther) ASSERT_EQ(tdm_client_output_get_available_modes(output, NULL, NULL), TDM_ERROR_INVALID_PARAMETER); } +TEST_P(TDMClient, ClientOutputSetMode) +{ + tdm_client_output_mode *modes; + int count = 0; + + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_get_available_modes(output, &modes, &count), TDM_ERROR_NONE); + + printf("count:%d\n", count); + + ASSERT_EQ(tdm_client_output_set_mode(output, count - 1), TDM_ERROR_NONE); +} + +TEST_P(TDMClient, ClientOutputSetModeiNullObject) +{ + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_set_mode(NULL, 0), TDM_ERROR_INVALID_PARAMETER); +} + +TEST_P(TDMClient, ClientOutputSetModeInvalidIndex) +{ + ASSERT_EQ(PrepareClient(), true); + ASSERT_EQ(PrepareOutput(), true); + + ASSERT_EQ(tdm_client_output_set_mode(output, -1), TDM_ERROR_INVALID_PARAMETER); +} + /* tdm_client_output_create_vblank */ TEST_P(TDMClient, ClientOutputCreateVblank) { diff --git a/include/tdm.h b/include/tdm.h index 979c35e..6df3508 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -324,6 +324,16 @@ tdm_output_remove_change_handler(tdm_output *output, tdm_output_change_handler func, void *user_data); +tdm_error +tdm_output_add_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data); + +tdm_error +tdm_output_remove_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data); + /** * @brief Get the connection type of a output object. * @param[in] output A output object diff --git a/include/tdm_types.h b/include/tdm_types.h index 7c0f311..72edcb9 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -297,6 +297,12 @@ typedef void (*tdm_output_commit_handler)(tdm_output *output, unsigned int seque void *user_data); /** + * @brief The output mode change request handler + */ +typedef void (*tdm_output_mode_change_request_handler)(tdm_output *output, + unsigned int index, void *user_data); + +/** * @brief The layer commit handler */ typedef void (*tdm_layer_commit_handler)(tdm_layer *layer, unsigned int sequence, diff --git a/src/tdm.c b/src/tdm.c index 6999b9e..1761e9a 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -530,6 +530,7 @@ tdm_display_update_output(tdm_private_module *private_module, tdm_output *output LIST_INITHEAD(&private_output->pending_commit_handler_list); LIST_INITHEAD(&private_output->destroy_handler_list); LIST_INITHEAD(&private_output->change_handler_list); + LIST_INITHEAD(&private_output->mode_change_request_handler_list); if (func_output->output_set_status_handler) { func_output->output_set_status_handler(private_output->output_backend, diff --git a/src/tdm_output.c b/src/tdm_output.c index 902543e..7d73c1d 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -508,6 +508,85 @@ tdm_output_add_change_handler(tdm_output *output, return ret; } +EXTERN tdm_error +tdm_output_add_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func == func && mode_change_handler->user_data == user_data) { + TDM_ERR("can't add twice"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_BAD_REQUEST; + } + } + + mode_change_handler = calloc(1, sizeof(tdm_private_output_change_handler)); + if (!mode_change_handler) { + /* LCOV_EXCL_START */ + TDM_ERR("failed: alloc memory"); + _pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ + } + + mode_change_handler->private_output = private_output; + mode_change_handler->func = func; + mode_change_handler->user_data = user_data; + + LIST_ADDTAIL(&mode_change_handler->link, &private_output->mode_change_request_handler_list); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; +} + +EXTERN tdm_error +tdm_output_remove_mode_change_request_handler(tdm_output *output, + tdm_output_mode_change_request_handler func, + void *user_data) +{ + tdm_private_display *private_display; + tdm_private_output *private_output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL, *hh = NULL; + + TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + private_output = (tdm_private_output*)output; + private_display = private_output->private_display; + + _pthread_mutex_lock(&private_display->lock); + + LIST_FOR_EACH_ENTRY_SAFE(mode_change_handler, hh, &private_output->mode_change_request_handler_list, link) { + if (mode_change_handler->func != func || mode_change_handler->user_data != user_data) + continue; + + LIST_DEL(&mode_change_handler->link); + free(mode_change_handler); + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_NONE; + } + + _pthread_mutex_unlock(&private_display->lock); + + return TDM_ERROR_INVALID_PARAMETER; +} + EXTERN void tdm_output_remove_change_handler(tdm_output *output, tdm_output_change_handler func, @@ -579,7 +658,7 @@ tdm_output_get_layer_count(tdm_output *output, int *count) *count = 0; LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) - (*count)++; + (*count)++; if (*count == 0) { _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_NONE; @@ -1214,6 +1293,23 @@ tdm_output_remove_commit_handler(tdm_output *output, tdm_output_commit_handler f return ret; } +INTERN void +tdm_output_call_mode_set_request(tdm_output *output, unsigned int index) +{ + tdm_private_output *private_output = (tdm_private_output*)output; + tdm_private_output_mode_change_handler *mode_change_handler = NULL; + + TDM_RETURN_IF_FAIL(private_output != NULL); + TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); + + if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list)) + return; + + LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) { + mode_change_handler->func(mode_change_handler->private_output, index, mode_change_handler->user_data); + } +} + tdm_error _tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data) { diff --git a/src/tdm_private.h b/src/tdm_private.h index a5c59e3..2acf467 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -138,6 +138,10 @@ void tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data); void tdm_output_remove_commit_handler_internal(tdm_output *output, tdm_output_commit_handler func, void *user_data); + +void +tdm_output_call_mode_set_request(tdm_output *output, unsigned int index); + void tdm_layer_remove_commit_handler_internal(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data); diff --git a/src/tdm_private_types.h b/src/tdm_private_types.h index 743367b..0ef71bd 100644 --- a/src/tdm_private_types.h +++ b/src/tdm_private_types.h @@ -112,6 +112,7 @@ typedef struct _tdm_private_output_destroy_handler tdm_private_output_destroy_ha typedef struct _tdm_private_output_change_handler tdm_private_output_change_handler; typedef struct _tdm_private_output_commit_handler tdm_private_output_commit_handler; typedef struct _tdm_private_output_vblank_handler tdm_private_output_vblank_handler; +typedef struct _tdm_private_output_mode_change_handler tdm_private_output_mode_change_handler; typedef struct _tdm_private_layer_commit_handler tdm_private_layer_commit_handler; typedef struct _tdm_private_hwc_commit_handler tdm_private_hwc_commit_handler; @@ -236,6 +237,7 @@ struct _tdm_private_output { /* virtual */ char name[TDM_NAME_LEN]; + struct list_head mode_change_request_handler_list; }; struct _tdm_private_layer { @@ -437,6 +439,14 @@ struct _tdm_private_output_commit_handler { pid_t owner_tid; }; +struct _tdm_private_output_mode_change_handler { + struct list_head link; + + tdm_private_output *private_output; + tdm_output_mode_change_request_handler func; + void *user_data; +}; + struct _tdm_private_hwc_commit_handler { struct list_head link; diff --git a/src/tdm_server.c b/src/tdm_server.c index a71eb0e..453e10e 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -607,7 +607,6 @@ _tdm_server_output_cb_get_available_modes(struct wl_client *client, struct wl_re tdm_error ret; ret = tdm_output_get_available_modes(output_info->output, &modes, &count); - if ((ret != TDM_ERROR_NONE) || (count == 0)) { wl_tdm_output_send_available_modes(output_info->resource, NULL, ret); return; @@ -630,6 +629,8 @@ _tdm_server_output_cb_set_mode(struct wl_client *client, struct wl_resource *res { tdm_server_output_info *output_info = wl_resource_get_user_data(resource); tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; + const tdm_output_mode *modes; + int count = 0; tdm_error ret; TDM_RETURN_IF_FAIL(output_info != NULL); @@ -638,7 +639,10 @@ _tdm_server_output_cb_set_mode(struct wl_client *client, struct wl_resource *res TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); TDM_RETURN_IF_FAIL(status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED); - //To do + ret = tdm_output_get_available_modes(output_info->output, &modes, &count); + TDM_RETURN_IF_FAIL(index < count); + + tdm_output_call_mode_set_request(output_info->output, index); return; } -- 2.7.4 From 53d274a1d6c5f5ebb3fd41efe7ecf14a52e5f65b Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Wed, 29 Aug 2018 15:49:05 +0900 Subject: [PATCH 16/16] virtual: add virtual output mode set test to tdm_test fix mutex set error Change-Id: I29a3867022fb2e68d4810528ea038ff69726dcf7 Signed-off-by: Junkyeong Kim --- client/tdm_client.c | 96 +++++++++++++++++++++++++++++---- haltests/src/tc_tdm_client.cpp | 1 + src/tdm_output.c | 1 - src/tdm_server.c | 4 +- tools/tdm_test_client.c | 17 ++++-- tools/tdm_test_server.c | 118 +++++++++++++++++++++++++++++++---------- 6 files changed, 192 insertions(+), 45 deletions(-) diff --git a/client/tdm_client.c b/client/tdm_client.c index 136a08a..0edcc0e 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -1238,12 +1238,18 @@ tdm_client_output_set_mode(tdm_client_output *output, int index) pthread_mutex_lock(&private_client->lock); - if (private_output->available_modes.count - 1 < index) + if (private_output->available_modes.count - 1 < index) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_INVALID_PARAMETER; + } if ((private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) || - (private_output->available_modes.count == 0)) + (private_output->available_modes.count == 0)) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_BAD_REQUEST; + } + + TDM_DBG("mode_set request : %d", index); wl_tdm_output_set_mode(private_output->output, index); @@ -2037,11 +2043,12 @@ tdm_client_voutput_cb_commit(void *data, struct wl_tdm_voutput *wl_voutput) if (h->func) h->func(private_voutput, buffer, h->user_data); } - pthread_mutex_lock(&private_client->lock); /* if no added commit_handler call commit done immediately */ if (LIST_IS_EMPTY(&private_voutput->commit_handler_list)) tdm_client_voutput_commit_done(private_voutput); + + pthread_mutex_lock(&private_client->lock); } void @@ -2196,10 +2203,14 @@ void tdm_client_voutput_destroy(tdm_client_voutput *voutput) { tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)voutput; + tdm_private_client *private_client; tdm_client_voutput_commit_handler_info *h = NULL, *hh = NULL; if (!private_voutput) return; + private_client = private_voutput->private_client; + + pthread_mutex_lock(&private_client->lock); if (!(LIST_IS_EMPTY(&private_voutput->buffer_list))) { tdm_private_client_buffer *cb = NULL, *cbb = NULL; @@ -2241,12 +2252,16 @@ tdm_client_voutput_destroy(tdm_client_voutput *voutput) LIST_DEL(&private_voutput->link); free(private_voutput); + + pthread_mutex_unlock(&private_client->lock); } tdm_error tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_client_output_mode *modes, int count) { tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -2254,9 +2269,19 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl return TDM_ERROR_INVALID_PARAMETER; private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->private_client; + + if (!private_voutput->private_output) { + private_voutput->private_output = tdm_client_voutput_get_client_output(private_voutput, &ret); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, TDM_ERROR_OPERATION_FAILED); + } - if (private_voutput->private_output->connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + pthread_mutex_lock(&private_client->lock); + + if (private_voutput->private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_BAD_REQUEST; + } if (private_voutput->available_modes.modes) free(private_voutput->available_modes.modes); @@ -2269,6 +2294,8 @@ tdm_client_voutput_set_available_modes(tdm_client_voutput *voutput, const tdm_cl memcpy(private_voutput->available_modes.modes, modes, sizeof(tdm_client_output_mode) * count); } + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -2276,19 +2303,33 @@ tdm_error tdm_client_voutput_set_physical_size(tdm_client_voutput *voutput, unsigned int mmWidth, unsigned int mmHeight) { tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; + tdm_error ret = TDM_ERROR_NONE; TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(mmWidth != 0, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(mmHeight != 0, TDM_ERROR_INVALID_PARAMETER); private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->private_client; - if (private_voutput->private_output->connection == TDM_OUTPUT_CONN_STATUS_CONNECTED) + if (!private_voutput->private_output) { + private_voutput->private_output = tdm_client_voutput_get_client_output(private_voutput, &ret); + TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, TDM_ERROR_OPERATION_FAILED); + } + + pthread_mutex_lock(&private_client->lock); + + if (private_voutput->private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + pthread_mutex_unlock(&private_client->lock); return TDM_ERROR_BAD_REQUEST; + } private_voutput->mmwidth = mmWidth; private_voutput->mmheight = mmHeight; + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -2370,16 +2411,25 @@ tdm_error tdm_client_voutput_commit_done(tdm_client_voutput *voutput) { tdm_private_client_voutput *private_voutput; + tdm_private_client *private_client; tbm_surface_h buffer = NULL; TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER); private_voutput = (tdm_private_client_voutput *)voutput; + TDM_RETURN_VAL_IF_FAIL(private_voutput->attach_buffer != NULL, TDM_ERROR_NONE); + + private_client = private_voutput->private_client; + + pthread_mutex_lock(&private_client->lock); + buffer = (tbm_surface_h)wl_buffer_get_user_data(private_voutput->attach_buffer->wl_buffer); tbm_surface_internal_unref(buffer); private_voutput->attach_buffer = NULL; wl_tdm_voutput_commit_done(private_voutput->wl_voutput); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -2388,6 +2438,7 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err { tdm_private_client_voutput *private_voutput; tdm_private_client_output *private_output = NULL; + tdm_private_client *private_client; tdm_error ret = TDM_ERROR_NONE; if (error) @@ -2401,10 +2452,16 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err } private_voutput = (tdm_private_client_voutput *)voutput; + private_client = private_voutput->private_client; - if (private_voutput->get_output) + pthread_mutex_lock(&private_client->lock); + + if (private_voutput->get_output) { + pthread_mutex_unlock(&private_client->lock); return private_voutput->private_output; + } + pthread_mutex_unlock(&private_client->lock); private_output = (tdm_private_client_output *)tdm_client_get_output(private_voutput->private_client, private_voutput->name, &ret); if (!private_output) { TDM_ERR("tdm_client_voutput_get_client_output get private_output fail"); @@ -2412,10 +2469,13 @@ tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *err *error = ret; return NULL; } + pthread_mutex_lock(&private_client->lock); private_output->voutput = private_voutput; private_voutput->private_output = private_output; private_voutput->get_output = 1; + pthread_mutex_unlock(&private_client->lock); + return private_output; } @@ -2443,15 +2503,21 @@ tdm_client_output_connect(tdm_client_output *output) { tdm_private_client_output *private_output; tdm_private_client_voutput *private_voutput = NULL; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output *)output; if (!private_output->voutput) return TDM_ERROR_INVALID_PARAMETER; private_voutput = private_output->voutput; + private_client = private_voutput->private_client; - TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_CONNECTED, - TDM_ERROR_BAD_REQUEST); + pthread_mutex_lock(&private_client->lock); + + if (private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; + } if (!private_output->watch_output_changes) private_output->connection = TDM_OUTPUT_CONN_STATUS_CONNECTED; @@ -2463,6 +2529,8 @@ tdm_client_output_connect(tdm_client_output *output) /* To Do : change voutput to output */ wl_tdm_voutput_connect(private_voutput->wl_voutput); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } @@ -2471,15 +2539,21 @@ tdm_client_output_disconnect(tdm_client_output *output) { tdm_private_client_output *private_output; tdm_private_client_voutput *private_voutput = NULL; + tdm_private_client *private_client; TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); private_output = (tdm_private_client_output *)output; if (!private_output->voutput) return TDM_ERROR_INVALID_PARAMETER; private_voutput = private_output->voutput; + private_client = private_voutput->private_client; - TDM_RETURN_VAL_IF_FAIL(private_output->connection != TDM_OUTPUT_CONN_STATUS_DISCONNECTED, - TDM_ERROR_BAD_REQUEST); + pthread_mutex_lock(&private_client->lock); + + if (private_output->connection == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) { + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; + } if (!private_output->watch_output_changes) private_output->connection = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; @@ -2487,5 +2561,7 @@ tdm_client_output_disconnect(tdm_client_output *output) /* To Do : change voutput to output */ wl_tdm_voutput_disconnect(private_voutput->wl_voutput); + pthread_mutex_unlock(&private_client->lock); + return TDM_ERROR_NONE; } diff --git a/haltests/src/tc_tdm_client.cpp b/haltests/src/tc_tdm_client.cpp index c2b2c20..3d609ef 100644 --- a/haltests/src/tc_tdm_client.cpp +++ b/haltests/src/tc_tdm_client.cpp @@ -850,6 +850,7 @@ TEST_P(TDMClient, ClientOutputSetMode) ASSERT_EQ(PrepareOutput(), true); ASSERT_EQ(tdm_client_output_get_available_modes(output, &modes, &count), TDM_ERROR_NONE); + ASSERT_GT(count, -1); printf("count:%d\n", count); diff --git a/src/tdm_output.c b/src/tdm_output.c index 7d73c1d..4430a80 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1300,7 +1300,6 @@ tdm_output_call_mode_set_request(tdm_output *output, unsigned int index) tdm_private_output_mode_change_handler *mode_change_handler = NULL; TDM_RETURN_IF_FAIL(private_output != NULL); - TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list)) return; diff --git a/src/tdm_server.c b/src/tdm_server.c index 453e10e..66a0d76 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -642,9 +642,9 @@ _tdm_server_output_cb_set_mode(struct wl_client *client, struct wl_resource *res ret = tdm_output_get_available_modes(output_info->output, &modes, &count); TDM_RETURN_IF_FAIL(index < count); - tdm_output_call_mode_set_request(output_info->output, index); + TDM_DBG("mode set request to index:%d", index); - return; + tdm_output_call_mode_set_request(output_info->output, index); } static const struct wl_tdm_output_interface tdm_output_implementation = { diff --git a/tools/tdm_test_client.c b/tools/tdm_test_client.c index cac60a8..d780eb1 100644 --- a/tools/tdm_test_client.c +++ b/tools/tdm_test_client.c @@ -566,11 +566,18 @@ _voutput_commit(tdm_client_voutput *voutput, tbm_surface_h buffer, void *user_da TDM_EXIT_IF_FAIL(data != NULL); TDM_EXIT_IF_FAIL(buffer != NULL); - if (count < 10) + if ((count < 10) || (count >=51 && count < 60)) _dump_buffer(buffer, count); count++; - if (count == 70) { + if (count == 50) { + tdm_client_output_mode *modes; + int count = 0; + + printf("client: %d commited(%p), mode change request to index 1\n", count, buffer); + tdm_client_output_get_available_modes(data->output, &modes, &count); + tdm_client_output_set_mode(data->output, count - 1); + } else if (count == 70) { printf("client: %d commited(%p), disconnect\n", count, buffer); tdm_client_output_disconnect(data->output); } else { @@ -613,14 +620,14 @@ _voutput_output_handler(tdm_client_output *output, tdm_output_change_type type, _voutput_make_available_mode(tdm_client_output_mode *modes, int count) { int i; - for (i = 0; i < count; i++) { + for (i = 0 ; i < count; i++) { modes[i].clock = 25200; - modes[i].hdisplay = 640; + modes[i].hdisplay = 640 * (count - i); modes[i].hsync_start = 656; modes[i].hsync_end = 752; modes[i].htotal = 800; modes[i].hskew = 0; - modes[i].vdisplay = 480; + modes[i].vdisplay = 480 * (count - i); modes[i].vsync_start = 490; modes[i].vsync_end = 492; modes[i].vtotal = 525; diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index 98b10db..af48e5c 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -312,6 +312,8 @@ struct _tdm_test_server_voutput { tdm_layer *layer; tbm_surface_h bufs[3]; int buf_idx; + int need_mode_change; + int index; }; struct _tdm_test_server { @@ -337,6 +339,7 @@ static void output_setup(tdm_test_server_output *o); static void layer_show_buffer(tdm_test_server_layer *l, tbm_surface_h b); static void capture_attach(tdm_test_server_capture *c, tbm_surface_h b); static void _vlayer_show_buffer(tdm_test_server_voutput *voutput); +static void _voutput_layer_init(tdm_test_server_voutput *voutput); static char* parse_size(tdm_size *size, char *arg) @@ -809,6 +812,37 @@ get_tts_buffer(tbm_surface_h b) } static void +_voutput_buff_deinit(tdm_test_server_voutput *voutput) +{ + int i; + + for (i = 0; i < 3; i++) { + if (!voutput->bufs[i]) continue; + + tbm_surface_destroy(voutput->bufs[i]); + voutput->bufs[i] = NULL; + } +} + +static void +_voutput_buff_init(tdm_test_server_voutput *voutput) +{ + tdm_output *output = voutput->output; + const tdm_output_mode *mode; + tdm_error ret = TDM_ERROR_NONE; + int i; + + ret = tdm_output_get_mode(output, &mode); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + for (i = 0; i < 3; i++) { + tbm_surface_h b = tbm_surface_internal_create_with_flags(mode->hdisplay, mode->vdisplay, DEFAULT_FORMAT, 0); + TDM_EXIT_IF_FAIL(b != NULL); + tdm_test_buffer_fill(b, i); + voutput->bufs[i] = b; + } +} +static void _vlayer_cb_commit(tdm_layer *layer, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { @@ -817,13 +851,42 @@ _vlayer_cb_commit(tdm_layer *layer, unsigned int sequence, tdm_output_conn_status status; tdm_error ret; - printf("voutput cb commit:\t %d: l(%p) b(%p)\n", voutput->buf_idx, voutput->layer, voutput->bufs[voutput->buf_idx]); + printf("voutput cb:\t %d: l(%p) b(%p)\n", voutput->buf_idx, voutput->layer, voutput->bufs[voutput->buf_idx]); ret = tdm_output_get_conn_status(voutput->output, &status); TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) return; + if (voutput->need_mode_change) { + const tdm_output_mode *modes; + int count = 0; + + tdm_output_get_available_modes(voutput->output, &modes, &count); + if (count > voutput->index) { + const tdm_output_mode *mode, *current; + + ret = tdm_output_get_mode(voutput->output, ¤t); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + mode = &modes[voutput->index]; + + if (mode != current) { + printf("mode change to %d (%dx%d, %d)\n", + voutput->index, mode->hdisplay, mode->vdisplay, mode->vrefresh); + _voutput_buff_deinit(voutput); + _voutput_buff_init(voutput); + + ret = tdm_output_set_mode(voutput->output, mode); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + + _voutput_layer_init(voutput); + voutput->buf_idx = 2; + } + } + voutput->need_mode_change = 0; + } + voutput->buf_idx++; _vlayer_show_buffer(voutput); } @@ -848,25 +911,6 @@ _vlayer_show_buffer(tdm_test_server_voutput *voutput) } static void -_voutput_buff_init(tdm_test_server_voutput *voutput) -{ - tdm_output *output = voutput->output; - const tdm_output_mode *mode; - tdm_error ret = TDM_ERROR_NONE; - int i; - - ret = tdm_output_get_mode(output, &mode); - TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); - - for (i = 0; i < 3; i++) { - tbm_surface_h b = tbm_surface_internal_create_with_flags(mode->hdisplay, mode->vdisplay, DEFAULT_FORMAT, 0); - TDM_EXIT_IF_FAIL(b != NULL); - tdm_test_buffer_fill(b, i); - voutput->bufs[i] = b; - } -} - -static void _voutput_layer_init(tdm_test_server_voutput *voutput) { tdm_output *output = voutput->output; @@ -993,22 +1037,41 @@ _tdm_test_server_cb_output_change(tdm_output *output, tdm_output_change_type typ } static void +_tdm_test_server_cb_output_mode_change(tdm_output *output, unsigned int index, void *user_data) +{ + tdm_test_server_voutput *voutput = NULL; + const tdm_output_mode *modes; + int count = 0; + tdm_error ret; + + voutput = (tdm_test_server_voutput *)user_data; + TDM_EXIT_IF_FAIL(voutput != NULL); + + ret = tdm_output_get_available_modes(output, &modes, &count); + TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE); + TDM_RETURN_IF_FAIL(index < count); + + voutput->need_mode_change = 1; + voutput->index = index; + + printf("mode change request. index:%d\n", index); +} + +static void _tdm_output_cb_destroy_handler(tdm_output *output, void *user_data) { tdm_test_server_voutput *voutput = NULL; - int i; voutput = (tdm_test_server_voutput *)user_data; TDM_EXIT_IF_FAIL(voutput != NULL); + tdm_output_remove_mode_change_request_handler(output, _tdm_test_server_cb_output_mode_change, voutput); tdm_output_remove_change_handler(output, _tdm_test_server_cb_output_change, voutput); tdm_output_remove_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput); LIST_DEL(&voutput->link); - for (i = 0; i < 3; i++) { - tbm_surface_destroy(voutput->bufs[i]); - } + _voutput_buff_deinit(voutput); printf("voutput: %p destroy\n", voutput); @@ -1033,6 +1096,9 @@ _tdm_output_cb_create_handler(tdm_display *dpy, tdm_output *output, void *user_d ret = tdm_output_add_change_handler(output, _tdm_test_server_cb_output_change, voutput); TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + ret = tdm_output_add_mode_change_request_handler(output, _tdm_test_server_cb_output_mode_change, voutput); + TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); + ret = tdm_output_add_destroy_handler(output, _tdm_output_cb_destroy_handler, voutput); TDM_EXIT_IF_FAIL(ret == TDM_ERROR_NONE); @@ -1107,9 +1173,7 @@ destroy(tdm_test_server *data) } LIST_FOR_EACH_ENTRY_SAFE(v, vv, &data->voutput_list, link) { - for (int i = 0; i < 3; i++) { - tbm_surface_destroy(v->bufs[i]); - } + _voutput_buff_deinit(v); LIST_DEL(&v->link); free(v); } -- 2.7.4