add get_dpms, get_connection, get_mode request 88/148588/1
authorBoram Park <boram1288.park@samsung.com>
Fri, 8 Sep 2017 02:07:43 +0000 (11:07 +0900)
committerBoram Park <boram1288.park@samsung.com>
Fri, 8 Sep 2017 02:54:56 +0000 (11:54 +0900)
If a client adds the change_handler, we might be able to guess that
the client will watch the tdm client's fd and handle tdm events in
event loop. Otherwise, we CAN'T make sure if a client has event loop
which handles tdm events.

Change-Id: I49685d7eb3b88cda59b167f5ae66a7e9501a2315

client/tdm_client.c
protocol/tdm.xml
src/tdm_server.c

index 858e4f5..04c9d2f 100644 (file)
@@ -76,6 +76,7 @@ typedef struct _tdm_private_client_output {
        struct list_head change_handler_list;
 
        unsigned int req_id;
+       unsigned int watch_output_changes;
 
        struct list_head link;
 } tdm_private_client_output;
@@ -508,9 +509,18 @@ tdm_client_output_add_change_handler(tdm_client_output *output,
        h = calloc(1, sizeof *h);
        TDM_RETURN_VAL_IF_FAIL(h != NULL, TDM_ERROR_OUT_OF_MEMORY);
 
-       if (LIST_IS_EMPTY(&private_output->change_handler_list))
+       if (LIST_IS_EMPTY(&private_output->change_handler_list)) {
                wl_tdm_output_watch_output_changes(private_output->output, 1);
 
+               /* TODO: this is very tricky.
+                * If a client adds the change_handler, we might be able to guess that
+                * the client will watch the tdm client's fd and handle tdm events in
+                * event loop. Otherwise, we CAN'T make sure if a client has event loop
+                * which handles tdm events.
+                */
+               private_output->watch_output_changes = 1;
+       }
+
        h->private_output = private_output;
        h->func = func;
        h->user_data = user_data;
@@ -550,12 +560,24 @@ tdm_error
 tdm_client_output_get_refresh_rate(tdm_client_output *output, unsigned int *refresh)
 {
        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(refresh != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        private_output = (tdm_private_client_output*)output;
 
+       if (private_output->watch_output_changes) {
+               *refresh = private_output->refresh;
+               return TDM_ERROR_NONE;
+       }
+
+       private_client = private_output->private_client;
+       TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       wl_tdm_output_get_mode(private_output->output);
+       wl_display_roundtrip(private_client->display);
+
        *refresh = private_output->refresh;
 
        return TDM_ERROR_NONE;
@@ -565,12 +587,24 @@ tdm_error
 tdm_client_output_get_conn_status(tdm_client_output *output, tdm_output_conn_status *status)
 {
        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(status != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        private_output = (tdm_private_client_output*)output;
 
+       if (private_output->watch_output_changes) {
+               *status = private_output->connection;
+               return TDM_ERROR_NONE;
+       }
+
+       private_client = private_output->private_client;
+       TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       wl_tdm_output_get_connection(private_output->output);
+       wl_display_roundtrip(private_client->display);
+
        *status = private_output->connection;
 
        return TDM_ERROR_NONE;
@@ -580,12 +614,24 @@ tdm_error
 tdm_client_output_get_dpms(tdm_client_output *output, tdm_output_dpms *dpms)
 {
        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(dpms != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        private_output = (tdm_private_client_output*)output;
 
+       if (private_output->watch_output_changes) {
+               *dpms = private_output->dpms;
+               return TDM_ERROR_NONE;
+       }
+
+       private_client = private_output->private_client;
+       TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       wl_tdm_output_get_dpms(private_output->output);
+       wl_display_roundtrip(private_client->display);
+
        *dpms = private_output->dpms;
 
        return TDM_ERROR_NONE;
@@ -778,10 +824,11 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli
        if (!private_vblank->started)
                private_vblank->started = 1;
 
-       if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
-               TDM_INFO("dpms off");
-               return TDM_ERROR_DPMS_OFF;
-       }
+       if (private_output->watch_output_changes)
+               if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
+                       TDM_INFO("dpms off");
+                       return TDM_ERROR_DPMS_OFF;
+               }
 
        w = calloc(1, sizeof *w);
        if (!w) {
@@ -854,10 +901,11 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence,
        if (!private_vblank->started)
                private_vblank->started = 1;
 
-       if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
-               TDM_INFO("dpms off");
-               return TDM_ERROR_DPMS_OFF;
-       }
+       if (private_output->watch_output_changes)
+               if (private_output->dpms != TDM_OUTPUT_DPMS_ON && !private_vblank->enable_fake) {
+                       TDM_INFO("dpms off");
+                       return TDM_ERROR_DPMS_OFF;
+               }
 
        w = calloc(1, sizeof *w);
        if (!w) {
index 47e6536..dcd99ed 100644 (file)
             <arg name="enable" type="uint"/>
         </request>
 
+        <request name="get_connection"/>
+
+        <request name="get_mode"/>
+
+        <request name="get_dpms"/>
+
     </interface>
 
     <interface name="wl_tdm_vblank" version="1">
index b69926b..c49e9db 100644 (file)
@@ -451,10 +451,94 @@ _tdm_server_output_cb_watch_output_changes(struct wl_client *client, struct wl_r
        output_info->watch_output_changes = enable;
 }
 
+static void
+_tdm_server_output_cb_get_connection(struct wl_client *client, struct wl_resource *resource)
+{
+       tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+       tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+       tdm_error ret;
+
+       TDM_RETURN_IF_FAIL(output_info != NULL);
+
+       ret = tdm_output_get_conn_status(output_info->output, &status);
+       TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+       wl_tdm_output_send_connection(output_info->resource, status);
+
+       return;
+
+failed:
+       wl_tdm_output_send_connection(output_info->resource, TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+}
+
+static void
+_tdm_server_output_cb_get_mode(struct wl_client *client, struct wl_resource *resource)
+{
+       tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+       tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+       tdm_error ret;
+
+       TDM_RETURN_IF_FAIL(output_info != NULL);
+
+       ret = tdm_output_get_conn_status(output_info->output, &status);
+       TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+       if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+               const tdm_output_mode *mode = NULL;
+               unsigned int hdisplay, vdisplay, vrefresh;
+
+               ret = tdm_output_get_mode(output_info->output, &mode);
+               TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+               hdisplay = (mode) ? mode->hdisplay : 0;
+               vdisplay = (mode) ? mode->vdisplay : 0;
+               vrefresh = (mode) ? mode->vrefresh : 0;
+
+               wl_tdm_output_send_mode(output_info->resource, hdisplay, vdisplay, vrefresh);
+       } else {
+               wl_tdm_output_send_mode(output_info->resource, 0, 0, 0);
+       }
+
+       return;
+failed:
+       wl_tdm_output_send_mode(output_info->resource, 0, 0, 0);
+}
+
+static void
+_tdm_server_output_cb_get_dpms(struct wl_client *client, struct wl_resource *resource)
+{
+       tdm_server_output_info *output_info = wl_resource_get_user_data(resource);
+       tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+       tdm_error ret;
+
+       TDM_RETURN_IF_FAIL(output_info != NULL);
+
+       ret = tdm_output_get_conn_status(output_info->output, &status);
+       TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+       if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+               tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF;
+
+               ret = tdm_output_get_dpms(output_info->output, &dpms_value);
+               TDM_GOTO_IF_FAIL(ret != TDM_ERROR_NONE, failed);
+
+               wl_tdm_output_send_dpms(output_info->resource, dpms_value);
+       } else {
+               wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF);
+       }
+
+       return;
+failed:
+       wl_tdm_output_send_dpms(output_info->resource, TDM_OUTPUT_DPMS_OFF);
+}
+
 static const struct wl_tdm_output_interface tdm_output_implementation = {
        _tdm_server_output_cb_destroy,
        _tdm_server_output_cb_create_vblank,
        _tdm_server_output_cb_watch_output_changes,
+       _tdm_server_output_cb_get_connection,
+       _tdm_server_output_cb_get_mode,
+       _tdm_server_output_cb_get_dpms,
 };
 
 static void
@@ -484,9 +568,7 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou
        tdm_server_output_info *output_info;
        struct wl_resource *output_resource = NULL;
        tdm_output *output;
-       const tdm_output_mode *mode = NULL;
-       tdm_output_dpms dpms_value;
-       tdm_output_conn_status status;
+       tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
 
        output = _tdm_server_find_output(private_server, name);
        if (!output) {
@@ -496,17 +578,6 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou
                return;
        }
 
-       tdm_output_get_mode(output, &mode);
-       if (!mode) {
-               TDM_ERR("no mode for '%s' output", name);
-               wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
-                                                          "no mode for '%s' output", name);
-               return;
-       }
-
-       tdm_output_get_dpms(output, &dpms_value);
-       tdm_output_get_conn_status(output, &status);
-
        output_resource =
                wl_resource_create(client, &wl_tdm_output_interface,
                                                   wl_resource_get_version(resource), id);
@@ -535,9 +606,26 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou
        wl_resource_set_implementation(output_resource, &tdm_output_implementation,
                                                                   output_info, destroy_output_callback);
 
-       wl_tdm_output_send_mode(output_resource, mode->hdisplay, mode->vdisplay, mode->vrefresh);
-       wl_tdm_output_send_dpms(output_resource, dpms_value);
+       tdm_output_get_conn_status(output, &status);
        wl_tdm_output_send_connection(output_resource, status);
+
+       if (status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) {
+               tdm_output_dpms dpms_value = TDM_OUTPUT_DPMS_OFF;
+               const tdm_output_mode *mode = NULL;
+               unsigned int hdisplay, vdisplay, vrefresh;
+
+               tdm_output_get_mode(output, &mode);
+               hdisplay = (mode) ? mode->hdisplay : 0;
+               vdisplay = (mode) ? mode->vdisplay : 0;
+               vrefresh = (mode) ? mode->vrefresh : 0;
+               wl_tdm_output_send_mode(output_resource, hdisplay, vdisplay, vrefresh);
+
+               tdm_output_get_dpms(output, &dpms_value);
+               wl_tdm_output_send_dpms(output_resource, dpms_value);
+       } else {
+               wl_tdm_output_send_mode(output_resource, 0, 0, 0);
+               wl_tdm_output_send_dpms(output_resource, TDM_OUTPUT_DPMS_OFF);
+       }
 }
 
 static void