virtual: send set_physical_size when voutput connect
[platform/core/uifw/libtdm.git] / client / tdm_client.c
index 81998e6..9fa0ab5 100644 (file)
@@ -9,7 +9,7 @@
  *          Taeheon Kim <th908.kim@samsung.com>,
  *          YoungJun Cho <yj44.cho@samsung.com>,
  *          SooChan Lim <sc1.lim@samsung.com>,
- *          Boram Park <sc1.lim@samsung.com>
+ *          Boram Park <boram1288.park@samsung.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
@@ -89,6 +89,22 @@ typedef struct _tdm_private_client_output {
        struct list_head link;
 } tdm_private_client_output;
 
+typedef struct _tdm_private_client_voutput {
+    tdm_private_client_output base;
+       struct wl_tdm_voutput *wl_voutput;
+
+       struct
+       {
+               int count;
+               tdm_client_output_mode *modes;
+       } available_modes;
+
+       unsigned int mmwidth;
+       unsigned int mmheight;
+
+       uint32_t msg;
+} tdm_private_client_voutput;
+
 struct _tdm_private_client_vblank {
        tdm_private_client_output *private_output;
 
@@ -935,6 +951,7 @@ tdm_client_output_remove_change_handler(tdm_client_output *output,
                free(h);
 
                if (LIST_IS_EMPTY(&private_output->change_handler_list)) {
+                       private_output->watch_output_changes = 0;
                        if (!CHECK_WL_PROTOCOL_ERROR(private_client)) {
                                wl_tdm_output_watch_output_changes(private_output->output, 0);
                                wl_display_roundtrip_queue(private_client->display, private_client->queue);
@@ -1590,3 +1607,287 @@ tdm_client_vblank_is_waiting(tdm_client_vblank *vblank)
 
        return (LIST_LENGTH(&private_vblank->wait_list) > 0) ? 1 : 0;
 }
+
+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;
+
+       private_voutput->msg = msg;
+}
+
+static const struct wl_tdm_voutput_listener tdm_client_voutput_lisntener = {
+       tdm_client_voutput_cb_ack_message
+};
+
+tdm_client_voutput *
+tdm_client_create_voutput(tdm_client *client, const char *name, tdm_error *error)
+{
+       tdm_private_client *private_client;
+       tdm_private_client_output *private_output;
+       tdm_private_client_voutput *private_voutput;
+       struct wl_proxy *wrapper;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       if (!client) {
+               TDM_ERR("'!client' failed");
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       if (!name) {
+               TDM_ERR("'!name' failed");
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       private_client = (tdm_private_client *)client;
+
+       pthread_mutex_lock(&private_client->lock);
+
+       if (CHECK_WL_PROTOCOL_ERROR(private_client)) {
+               if (error)
+                       *error = TDM_ERROR_PROTOCOL_ERROR;
+               pthread_mutex_unlock(&private_client->lock);
+               return NULL;
+       }
+
+       LIST_FOR_EACH_ENTRY(private_output, &private_client->output_list, link) {
+               if (!strncmp(private_output->name, name, TDM_NAME_LEN)) {
+                       if (error)
+                               *error = TDM_ERROR_INVALID_PARAMETER; // FIXME define new error type.
+                       pthread_mutex_unlock(&private_client->lock);
+                       return NULL;
+               }
+       }
+
+       wrapper = wl_proxy_create_wrapper(private_client->tdm);
+       if (!wrapper) {
+               TDM_ERR("create virtual output wrapper failed");
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               pthread_mutex_unlock(&private_client->lock);
+               return NULL;
+       }
+
+       wl_proxy_set_queue(wrapper, private_client->queue);
+
+       private_voutput = calloc(1, sizeof *private_voutput);
+       if (!private_voutput) {
+               /* LOCV_EXCL_START */
+               wl_proxy_wrapper_destroy(wrapper);
+               TDM_ERR("alloc failed");
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               return NULL;
+               /* LOCV_EXCL_STOP */
+       }
+
+       private_voutput->base.private_client = private_client;
+
+       private_voutput->wl_voutput = wl_tdm_create_voutput((struct wl_tdm *)wrapper, private_voutput->base.name);
+       wl_proxy_wrapper_destroy(wrapper);
+       if (!private_voutput->wl_voutput) {
+               /* LCOV_EXCL_START */
+               TDM_ERR("couldn't create voutput resource");
+               free(private_voutput);
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               pthread_mutex_unlock(&private_client->lock);
+               return NULL;
+               /* LCOV_EXCL_STOP */
+       }
+
+       wl_tdm_voutput_add_listener(private_voutput->wl_voutput,
+                                                               &tdm_client_voutput_lisntener, private_voutput);
+       wl_display_roundtrip_queue(private_client->display, private_client->queue);
+
+       wl_proxy_set_queue((struct wl_proxy *)private_voutput->wl_voutput, NULL);
+
+       if (CHECK_WL_PROTOCOL_ERROR(private_client)) {
+               wl_tdm_voutput_destroy(private_voutput->wl_voutput);
+               free(private_voutput);
+               if (error)
+                       *error = TDM_ERROR_PROTOCOL_ERROR;
+               pthread_mutex_unlock(&private_client->lock);
+               return NULL;
+       }
+
+       if (private_voutput->msg != WL_TDM_VOUTPUT_MESSAGE_ADDED)
+       {
+               wl_tdm_voutput_destroy(private_voutput->wl_voutput);
+               free(private_voutput);
+               if (error)
+                       *error = TDM_ERROR_PROTOCOL_ERROR;      // FIXME add new error type.
+               pthread_mutex_unlock(&private_client->lock);
+               return NULL;
+       }
+
+       pthread_mutex_unlock(&private_client->lock);
+
+       return (tdm_client_voutput *)private_voutput;
+}
+
+void
+tdm_client_voutput_destroy(tdm_client_voutput *voutput)
+{
+       tdm_private_client_voutput *private_voutput = (tdm_private_client_voutput *)voutput;
+
+       if (!private_voutput)
+               return;
+
+       wl_tdm_voutput_destroy(private_voutput->wl_voutput);
+
+       free(private_voutput);
+}
+
+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_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if ((count > 0) && (modes == 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_modes.modes)
+               free(private_voutput->available_modes.modes);
+
+       private_voutput->available_modes.count = count;
+
+       if (count != 0)
+       {
+               private_voutput->available_modes.modes = calloc(count, sizeof(tdm_client_output_mode));
+               memcpy(private_voutput->available_modes.modes, modes, sizeof(tdm_client_output_mode) * 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;
+
+       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;
+
+       if (private_voutput->base.connection == TDM_OUTPUT_CONN_STATUS_CONNECTED)
+               return TDM_ERROR_BAD_REQUEST;
+
+       private_voutput->mmwidth = mmWidth;
+       private_voutput->mmheight = mmHeight;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_client_output *
+tdm_client_voutput_get_client_output(tdm_client_voutput *voutput, tdm_error *error)
+{
+       tdm_private_client_voutput *private_voutput;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       if (!voutput)
+       {
+               TDM_ERR("'!voutput' failed");
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       private_voutput = (tdm_private_client_voutput *)voutput;
+
+       return &private_voutput->base;
+}
+
+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;
+}
+
+tdm_error
+tdm_client_output_connect(tdm_client_output *output)
+{
+       tdm_private_client_output *private_output;
+       tdm_private_client_voutput *private_voutput;
+       tdm_client_output_mode *modes;
+       int i;
+
+       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;
+
+       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;
+
+       modes = private_voutput->available_modes.modes;
+       for (i = 0; i < private_voutput->available_modes.count; i++) {
+               wl_tdm_voutput_set_available_modes(private_voutput->wl_voutput, i,
+                                                                                  modes[i].clock, modes[i].hdisplay,
+                                                                                  modes[i].hsync_start, modes[i].hsync_end,
+                                                                                  modes[i].htotal, modes[i].hskew,
+                                                                                  modes[i].vdisplay, modes[i].vsync_start,
+                                                                                  modes[i].vsync_end, modes[i].vtotal,
+                                                                                  modes[i].vscan, modes[i].vrefresh,
+                                                                                  modes[i].flags, modes[i].type,
+                                                                                  modes[i].name);
+       }
+       wl_tdm_voutput_set_physical_size(private_voutput->wl_voutput, private_voutput->mmwidth, private_voutput->mmheight);
+
+       wl_tdm_voutput_connect(private_voutput->wl_voutput);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+tdm_client_output_disconnect(tdm_client_output *output)
+{
+       tdm_private_client_voutput *private_voutput;
+       tdm_private_client_output *private_output;
+
+       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;
+
+       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;
+
+       wl_tdm_voutput_disconnect(private_voutput->wl_voutput);
+
+       return TDM_ERROR_NONE;
+}