virtual: fix voutput commit buffer send fail 98/195198/4
authorJunkyeong Kim <jk0430.kim@samsung.com>
Tue, 11 Dec 2018 12:22:03 +0000 (21:22 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Wed, 26 Dec 2018 23:36:42 +0000 (23:36 +0000)
add tdm_output_set_voutput_commit / tdm_output_unset_voutput_commit
execute set_voutput_commit when connect.
execute unset_voutput_commit when disconnect.

cause of tdm thread, the voutput commit request has to be set by client.
before code the voutput commit was set from server(main thread),
client cannot get buffer attach and commit event from server.

Change-Id: I244d9b8b93b3994cba760b9aa8b1ebdfa3102e68
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
backends/virtual/tdm_virtual_display.c
src/tdm_output.c
src/tdm_private.h
src/tdm_private_types.h
src/tdm_server.c

index 875dce4..2d407fe 100644 (file)
@@ -457,8 +457,9 @@ virtual_output_commit(tdm_output *output, int sync, void *user_data)
                                                                         output_data->status_user_data);
        }
 
+       layer_data = output_data->primary_layer;
+
        if (voutput_data->vcommit_func) {
-               layer_data = output_data->primary_layer;
                if (layer_data->display_buffer_changed) {
                        output_data->commit_user_data = user_data;
                        event_data = calloc(1, sizeof(tdm_virtual_event_data));
@@ -495,6 +496,8 @@ virtual_output_commit(tdm_output *output, int sync, void *user_data)
                }
        }
 
+       layer_data->display_buffer_changed = 0;
+
        return TDM_ERROR_NONE;
 }
 
@@ -940,7 +943,6 @@ virtual_output_set_commit_func(tdm_voutput *voutput,  tdm_voutput_commit_handler
        tdm_virtual_voutput_data *voutput_data = voutput;
 
        RETURN_VAL_IF_FAIL(voutput_data, TDM_ERROR_INVALID_PARAMETER);
-       RETURN_VAL_IF_FAIL(commit_func, TDM_ERROR_INVALID_PARAMETER);
 
        voutput_data->vcommit_func = commit_func;
 
index e043569..dfc96ee 100644 (file)
@@ -1101,7 +1101,7 @@ _tdm_voutput_thread_cb_commit(tdm_private_display *private_display, void *object
                TDM_INFO("handler(%p)", voutput_commit_handler);
        }
 
-       if (voutput_commit_handler->func) {
+       if (voutput_commit_handler->func && private_voutput->set_voutput_commit != 0) {
                _pthread_mutex_unlock(&private_display->lock);
                voutput_commit_handler->func(private_voutput, voutput_commit_handler->user_data);
                _pthread_mutex_lock(&private_display->lock);
@@ -1137,9 +1137,9 @@ _tdm_voutput_cb_commit(tdm_voutput *voutput_backend, unsigned int sequence,
                return;
        }
 
-       LIST_FOR_EACH_ENTRY(voutput_commit_handler, &private_voutput->voutput_commit_handler_list, link) {
-               if (voutput_commit_handler) break;
-       }
+       if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) return;
+
+       voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
 
        private_output = private_voutput->private_output;
 
@@ -1401,6 +1401,119 @@ _voutput_commit_func(tdm_voutput *voutput, tbm_surface_h buffer)
 }
 
 INTERN tdm_error
+tdm_output_set_voutput_commit(tdm_voutput *voutput)
+{
+       tdm_private_display *private_display;
+       tdm_private_output *private_output;
+       tdm_private_voutput *private_voutput;
+       tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       private_voutput = (tdm_private_voutput *)voutput;
+       private_display = private_voutput->private_display;
+       private_output = (tdm_private_output *)private_voutput->private_output;
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
+               _pthread_mutex_unlock(&private_display->lock);
+               return ret;
+       }
+
+       if (!private_voutput->regist_commit_cb) {
+               private_voutput->regist_commit_cb = 1;
+               ret = tdm_voutput_set_commit_func(private_voutput, _tdm_voutput_cb_commit);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("failed: tdm_voutput_set_commit_func");
+                       return ret;
+               }
+       }
+
+       voutput_commit_handler = calloc(1, sizeof(tdm_private_voutput_commit_handler));
+       if (!voutput_commit_handler) {
+               /* LCOV_EXCL_START */
+               TDM_ERR("failed: alloc memory");
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
+       }
+
+       ret = tdm_thread_cb_add(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("tdm_thread_cb_add failed");
+               free(voutput_commit_handler);
+               _pthread_mutex_unlock(&private_display->lock);
+               return ret;
+       }
+
+       LIST_ADDTAIL(&voutput_commit_handler->link, &private_voutput->voutput_commit_handler_list);
+       voutput_commit_handler->private_voutput = private_voutput;
+       voutput_commit_handler->func = _voutput_commit_func;
+       voutput_commit_handler->owner_tid = syscall(SYS_gettid);
+
+       private_voutput->set_voutput_commit = 1;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+INTERN tdm_error
+tdm_output_unset_voutput_commit(tdm_voutput *voutput)
+{
+       tdm_private_display *private_display;
+       tdm_private_output *private_output;
+       tdm_private_voutput *private_voutput;
+       tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       TDM_RETURN_VAL_IF_FAIL(voutput != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       private_voutput = (tdm_private_voutput *)voutput;
+       private_display = private_voutput->private_display;
+       private_output = (tdm_private_output *)private_voutput->private_output;
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       private_voutput->set_voutput_commit = 0;
+
+       if (private_voutput->regist_commit_cb) {
+               private_voutput->regist_commit_cb = 0;
+               ret = tdm_voutput_set_commit_func(private_voutput, NULL);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("failed: tdm_voutput_set_commit_func");
+                       return ret;
+               }
+       }
+
+       if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) == 0) {
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
+       if (LIST_LENGTH(&private_output->output_commit_handler_list) != 0) {
+               //commiting. don't remove voutput commit thread here
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
+       if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
+               voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
+       } else {
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_NONE;
+       }
+
+       tdm_thread_cb_remove(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return TDM_ERROR_NONE;
+}
+
+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;
@@ -1452,38 +1565,12 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl
                                free(output_commit_handler);
                                return TDM_ERROR_BAD_MODULE;
                        }
-                       private_voutput = private_output->private_voutput;
-
-                       if (!private_voutput->regist_commit_cb) {
-                               private_voutput->regist_commit_cb = 1;
-                               ret = tdm_voutput_set_commit_func(private_voutput, _tdm_voutput_cb_commit);
-                               TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
-                       }
-
-                       voutput_commit_handler = calloc(1, sizeof(tdm_private_voutput_commit_handler));
-                       if (!voutput_commit_handler) {
-                               /* LCOV_EXCL_START */
-                               TDM_ERR("failed: alloc memory");
-                               free(output_commit_handler);
-                               return TDM_ERROR_OUT_OF_MEMORY;
-                               /* LCOV_EXCL_STOP */
-                       }
-
-                       ret = tdm_thread_cb_add(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
-                       if (ret != TDM_ERROR_NONE) {
-                               TDM_ERR("tdm_thread_cb_add failed");
-                               free(voutput_commit_handler);
-                               free(output_commit_handler);
-                               return ret;
-                       }
                }
 
                ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_COMMIT, output_commit_handler, _tdm_output_thread_cb_commit, NULL);
                if (ret != TDM_ERROR_NONE) {
                        TDM_ERR("tdm_thread_cb_add failed");
                        free(output_commit_handler);
-                       if (voutput_commit_handler)
-                               free(voutput_commit_handler);
                        return ret;
                }
 
@@ -1493,17 +1580,16 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl
                output_commit_handler->user_data = user_data;
                output_commit_handler->owner_tid = syscall(SYS_gettid);
 
-               if (voutput_commit_handler) {
+               if (private_module == private_display->virtual_module) {
+                       private_voutput = private_output->private_voutput;
+
                        /* voutput use only 1 layer */
-                       LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
-                               if (private_layer) break;
-                       }
+                       private_layer = LIST_FIRST_ENTRY(&private_output->layer_list, tdm_private_layer, link);
 
-                       LIST_ADDTAIL(&voutput_commit_handler->link, &private_voutput->voutput_commit_handler_list);
-                       voutput_commit_handler->private_voutput = private_voutput;
-                       voutput_commit_handler->func = _voutput_commit_func;
-                       voutput_commit_handler->user_data = private_layer->commiting_buffer;
-                       voutput_commit_handler->owner_tid = syscall(SYS_gettid);
+                       if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
+                               voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
+                               voutput_commit_handler->user_data = private_layer->commiting_buffer;
+                       }
                }
 
                ret = func_output->output_commit(private_output->output_backend, sync,
@@ -1555,11 +1641,7 @@ commit_failed:
                LIST_DEL(&output_commit_handler->link);
                free(output_commit_handler);
        }
-       if (voutput_commit_handler) {
-               tdm_thread_cb_remove(private_output->private_voutput, TDM_THREAD_CB_VOUTPUT_COMMIT, voutput_commit_handler, _tdm_voutput_thread_cb_commit, NULL);
-               LIST_DEL(&voutput_commit_handler->link);
-               free(voutput_commit_handler);
-       }
+
        return ret;
        /* LCOV_EXCL_STOP */
 }
index 9e10713..b65c01e 100644 (file)
@@ -279,6 +279,10 @@ tdm_voutput_attach_buffer(tdm_voutput *voutput, tbm_surface_h buffer);
 tdm_error
 tdm_voutput_commit_buffer(tdm_voutput *voutput);
 tdm_error
+tdm_output_set_voutput_commit(tdm_voutput *voutput);
+tdm_error
+tdm_output_unset_voutput_commit(tdm_voutput *voutput);
+tdm_error
 tdm_voutput_commit_done(tdm_voutput *voutput);
 void *
 tdm_display_find_private_voutput(tdm_private_display *private_display, double stamp);
index 993be0e..80d867f 100644 (file)
@@ -267,6 +267,8 @@ struct _tdm_private_voutput {
        unsigned int mmwidth;
        unsigned int mmheight;
        int connect_status;
+
+       int set_voutput_commit;
 };
 
 struct _tdm_private_layer {
index 31ddf14..dc4f25a 100644 (file)
@@ -93,6 +93,7 @@ typedef struct _tdm_server_voutput_info {
        struct list_head buffer_list;
        tdm_server_voutput_buffer *attach_buffer;
        int committing;
+       unsigned int request_commit;
 } tdm_server_voutput_info;
 
 typedef struct _tdm_server_vblank_info {
@@ -902,9 +903,12 @@ _tdm_voutput_cb_connect(struct wl_client *client, struct wl_resource *resource)
        voutput_info = wl_resource_get_user_data(resource);
        voutput_info->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
 
+       voutput_info->request_commit = 1;
+
        tdm_voutput_set_physical_size(voutput_info->voutput, voutput_info->mmwidth, voutput_info->mmheight);
        tdm_voutput_set_available_mode(voutput_info->voutput, voutput_info->available_modes.modes, voutput_info->available_modes.count);
        tdm_voutput_connect(voutput_info->voutput);
+       tdm_output_set_voutput_commit(voutput_info->voutput);
 }
 
 static void
@@ -929,6 +933,11 @@ _tdm_voutput_cb_disconnect(struct wl_client *client, struct wl_resource *resourc
                voutput_info->attach_buffer = NULL;
        }
 
+       if (voutput_info->request_commit == 1) {
+               tdm_output_unset_voutput_commit(voutput_info->voutput);
+               voutput_info->request_commit = 0;
+       }
+
        tdm_voutput_disconnect(voutput_info->voutput);
 }
 
@@ -949,6 +958,9 @@ _tdm_voutput_cb_commit_done(struct wl_client *client, struct wl_resource *resour
        voutput_info->committing = 0;
        voutput_info->attach_buffer = NULL;
 
+       if (voutput_info->request_commit == 1)
+               tdm_output_set_voutput_commit(voutput_info->voutput);
+
        tdm_voutput_commit_done(voutput_info->voutput);
 }
 
@@ -1237,10 +1249,14 @@ tdm_voutput_cb_resource_destroy(struct wl_resource *resource)
 
        voutput = voutput_info->voutput;
 
-       if (voutput)
+       if (voutput_info->request_commit)
+               tdm_output_unset_voutput_commit(voutput_info->voutput);
+
+       if (voutput) {
                ret = tdm_voutput_destroy(voutput);
-       if (ret != TDM_ERROR_NONE)
-               TDM_ERR("_tdm_voutput_cb_destroy fail");
+               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;