virtual: support tdm_client output_set_mode 80/187580/2
authorJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 24 Aug 2018 09:36:59 +0000 (18:36 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Mon, 27 Aug 2018 06:05:35 +0000 (15:05 +0900)
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 <jk0430.kim@samsung.com>
client/tdm_client.c
haltests/src/tc_tdm_client.cpp
include/tdm.h
include/tdm_types.h
src/tdm.c
src/tdm_output.c
src/tdm_private.h
src/tdm_private_types.h
src/tdm_server.c

index f5c69db..136a08a 100644 (file)
@@ -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;
 }
 
index 883ac5c..c2b2c20 100644 (file)
@@ -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)
 {
index 979c35e..6df3508 100644 (file)
@@ -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
index 7c0f311..72edcb9 100644 (file)
@@ -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,
index 6999b9e..1761e9a 100644 (file)
--- 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,
index 902543e..7d73c1d 100644 (file)
@@ -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)
 {
index a5c59e3..2acf467 100644 (file)
@@ -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);
 
index 743367b..0ef71bd 100644 (file)
@@ -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;
 
index a71eb0e..453e10e 100644 (file)
@@ -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;
 }