use vblank instead of the output commit handler in case of tdm_layer_commit 89/110889/1
authorBoram Park <boram1288.park@samsung.com>
Tue, 17 Jan 2017 11:51:31 +0000 (20:51 +0900)
committerBoram Park <boram1288.park@samsung.com>
Wed, 18 Jan 2017 10:58:31 +0000 (19:58 +0900)
Change-Id: Ib2a29cc331b8243922d43325265891119c809510

src/tdm_display.c
src/tdm_private.h
src/tdm_vblank.c

index f3a4e05..4a317b9 100644 (file)
        private_display = private_output->private_display
 
 static void _tdm_layer_committed(tdm_private_layer *private_layer);
-static void _tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
-                                                                               unsigned int tv_sec, unsigned int tv_usec, void *user_data);
 static void _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
                                                                          unsigned int tv_sec, unsigned int tv_usec, void *user_data);
 
@@ -990,7 +988,7 @@ tdm_output_cb_vblank(tdm_output *output_backend, unsigned int sequence,
                        continue;
 
                LIST_DEL(&v->link);
-               LIST_ADD(&v->link, &clone_list);
+               LIST_ADDTAIL(&v->link, &clone_list);
        }
 
        _pthread_mutex_unlock(&private_display->lock);
@@ -1013,7 +1011,9 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
        tdm_private_layer *private_layer = NULL;
 
        TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
-       TDM_RETURN_IF_FAIL(output_commit_handler);
+
+       if (!output_commit_handler)
+               return;
 
        private_output = output_commit_handler->private_output;
        private_display = private_output->private_display;
@@ -1054,9 +1054,14 @@ tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence,
        free(output_commit_handler);
 }
 
+/* add_front: To distinguish between the user vblank handlers and the layer
+ *            commit vblank handlers. The layer commit handlers will be called
+ *            before calling the user vblank handlers.
+ */
 static tdm_error
 _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
-                                               tdm_output_vblank_handler func, void *user_data)
+                                               tdm_output_vblank_handler func, void *user_data,
+                                               unsigned int add_front)
 {
        tdm_func_output *func_output;
        tdm_private_vblank_handler *vblank_handler = NULL, *v = NULL;
@@ -1067,6 +1072,10 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
 
        func_output = &private_display->func_output;
 
+       /* interval SHOULD be at least 1 */
+       if (interval <= 0)
+               interval = 1;
+
        if (!func_output->output_wait_vblank) {
                TDM_ERR("not implemented!!");
                return TDM_ERROR_NOT_IMPLEMENTED;
@@ -1091,7 +1100,11 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
                }
        }
 
-       LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
+       if (add_front)
+               LIST_ADD(&vblank_handler->link, &private_output->vblank_handler_list);
+       else
+               LIST_ADDTAIL(&vblank_handler->link, &private_output->vblank_handler_list);
+
        vblank_handler->private_output = private_output;
        vblank_handler->interval = interval;
        vblank_handler->sync = sync;
@@ -1131,7 +1144,29 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync,
                return TDM_ERROR_DPMS_OFF;
        }
 
-       ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data);
+       ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 0);
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
+tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
+                                                                tdm_output_vblank_handler func, void *user_data)
+{
+       OUTPUT_FUNC_ENTRY();
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
+               TDM_WRN("output(%d) dpms: %s", private_output->pipe,
+                               tdm_dpms_str(private_output->current_dpms_value));
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_DPMS_OFF;
+       }
+
+       ret = _tdm_output_wait_vblank(output, interval, sync, func, user_data, 1);
 
        _pthread_mutex_unlock(&private_display->lock);
 
@@ -1153,24 +1188,26 @@ _tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func,
                return TDM_ERROR_NOT_IMPLEMENTED;
        }
 
-       if (!private_output->regist_commit_cb) {
-               private_output->regist_commit_cb = 1;
-               ret = func_output->output_set_commit_handler(private_output->output_backend,
-                               tdm_output_cb_commit);
-               TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
-       }
+       if (func) {
+               if (!private_output->regist_commit_cb) {
+                       private_output->regist_commit_cb = 1;
+                       ret = func_output->output_set_commit_handler(private_output->output_backend,
+                                       tdm_output_cb_commit);
+                       TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
+               }
 
-       output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
-       if (!output_commit_handler) {
-               TDM_ERR("failed: alloc memory");
-               return TDM_ERROR_OUT_OF_MEMORY;
-       }
+               output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
+               if (!output_commit_handler) {
+                       TDM_ERR("failed: alloc memory");
+                       return TDM_ERROR_OUT_OF_MEMORY;
+               }
 
-       LIST_ADD(&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);
+               LIST_ADD(&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);
+       }
 
        ret = func_output->output_commit(private_output->output_backend, sync,
                                                                         output_commit_handler);
@@ -1883,45 +1920,47 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se
 {
        tdm_private_layer_commit_handler *lm = NULL, *lmm = NULL;
        tdm_private_display *private_display;
+       struct list_head clone_list, pending_clone_list;
        tdm_error ret;
 
        private_display = private_output->private_display;
 
        private_output->waiting_vblank = 0;
 
+       LIST_INITHEAD(&clone_list);
+       LIST_INITHEAD(&pending_clone_list);
+
        LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->layer_commit_handler_list, link) {
-               _tdm_layer_committed(lm->private_layer);
+               LIST_DEL(&lm->link);
+               LIST_ADDTAIL(&lm->link, &clone_list);
+       }
 
-               if (lm->func) {
-                       _pthread_mutex_unlock(&private_display->lock);
-                       lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
-                       _pthread_mutex_lock(&private_display->lock);
-               }
+       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
+               LIST_DEL(&lm->link);
+               LIST_ADDTAIL(&lm->link, &pending_clone_list);
+       }
 
+       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &clone_list, link) {
+               _tdm_layer_committed(lm->private_layer);
+               _pthread_mutex_unlock(&private_display->lock);
+               if (lm->func)
+                       lm->func(lm->private_layer, sequence, tv_sec, tv_usec, lm->user_data);
+               _pthread_mutex_lock(&private_display->lock);
                LIST_DEL(&lm->link);
                free(lm);
        }
 
-       if (LIST_IS_EMPTY(&private_output->pending_commit_handler_list))
+       if (LIST_IS_EMPTY(&pending_clone_list))
                return;
 
-#if 1
-       ret = _tdm_output_commit(private_output, 0, _tdm_layer_cb_output_commit, NULL);
-       TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
-
-       if (tdm_debug_module & TDM_DEBUG_COMMIT)
-               TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
+       TDM_GOTO_IF_FAIL(private_output->vblank != NULL, wait_failed);
 
-       private_output->waiting_vblank = 1;
-#else
        ret = _tdm_output_commit(private_output, 0, NULL, NULL);
        TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, wait_failed);
 
        if (tdm_debug_module & TDM_DEBUG_COMMIT)
                TDM_INFO("layer commit: output(%d) commit", private_output->pipe);
 
-       TDM_RETURN_IF_FAIL(private_output->vblank != NULL);
-
        /* tdm_vblank APIs is for server. it should be called in unlock status*/
        _pthread_mutex_unlock(&private_display->lock);
        ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
@@ -1931,16 +1970,15 @@ _tdm_layer_got_output_vblank(tdm_private_output *private_output, unsigned int se
 
        if (tdm_debug_module & TDM_DEBUG_COMMIT)
                TDM_INFO("layer commit: output(%d) wait vblank", private_output->pipe);
-#endif
 
-       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
+       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
                LIST_DEL(&lm->link);
-               LIST_ADD(&lm->link, &private_output->layer_commit_handler_list);
+               LIST_ADDTAIL(&lm->link, &private_output->layer_commit_handler_list);
        }
 
        return;
 wait_failed:
-       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &private_output->pending_commit_handler_list, link) {
+       LIST_FOR_EACH_ENTRY_SAFE(lm, lmm, &pending_clone_list, link) {
                LIST_DEL(&lm->link);
                free(lm);
        }
@@ -1948,58 +1986,6 @@ wait_failed:
 }
 
 static void
-_tdm_layer_cb_output_commit(tdm_output *output, unsigned int sequence,
-                                                       unsigned int tv_sec, unsigned int tv_usec, void *user_data)
-{
-       tdm_private_layer_commit_handler *layer_commit_handler = user_data;
-       tdm_private_display *private_display;
-       tdm_private_output *private_output = output;
-       tdm_private_layer *private_layer;
-
-       private_display = private_output->private_display;
-
-       _pthread_mutex_lock(&private_display->lock);
-
-       if (layer_commit_handler) {
-               tdm_private_layer_commit_handler *lm = NULL;
-               int found = 0;
-
-               LIST_FOR_EACH_ENTRY(lm, &private_output->layer_commit_handler_list, link) {
-                       if (layer_commit_handler == lm) {
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (found) {
-                       private_layer = layer_commit_handler->private_layer;
-
-                       if (tdm_debug_module & TDM_DEBUG_COMMIT)
-                               TDM_INFO("layer(%p) commit: output(%d) committed", private_layer, private_output->pipe);
-
-                       _tdm_layer_committed(private_layer);
-
-                       if (layer_commit_handler->func) {
-                               _pthread_mutex_unlock(&private_display->lock);
-                               layer_commit_handler->func(private_output, sequence,
-                                                                                  tv_sec, tv_usec, layer_commit_handler->user_data);
-                               _pthread_mutex_lock(&private_display->lock);
-                       }
-
-                       LIST_DEL(&layer_commit_handler->link);
-                       free(layer_commit_handler);
-               }
-       } else {
-               if (tdm_debug_module & TDM_DEBUG_COMMIT)
-                       TDM_INFO("layer commit: output(%d) committed", private_output->pipe);
-
-               _tdm_layer_got_output_vblank(private_output, sequence, tv_sec, tv_usec);
-       }
-
-       _pthread_mutex_unlock(&private_display->lock);
-}
-
-static void
 _tdm_layer_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
                                                  unsigned int tv_sec, unsigned int tv_usec, void *user_data)
 {
@@ -2050,9 +2036,14 @@ _tdm_layer_commit_possible(tdm_private_layer *private_layer)
 static tdm_error
 _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_data)
 {
-       tdm_private_layer_commit_handler *layer_commit_handler;
+       tdm_private_layer_commit_handler *layer_commit_handler = NULL;
        LAYER_FUNC_ENTRY();
 
+       if (private_layer->committing)
+               TDM_WRN("layer(%d) too many commit", private_layer->index);
+       else
+               private_layer->committing = 1;
+
        layer_commit_handler = calloc(1, sizeof(tdm_private_layer_commit_handler));
        if (!layer_commit_handler) {
                TDM_ERR("failed: alloc memory");
@@ -2065,47 +2056,42 @@ _tdm_layer_commit(tdm_layer *layer, tdm_layer_commit_handler func, void *user_da
        layer_commit_handler->user_data = user_data;
 
        if (_tdm_layer_commit_possible(private_layer)) {
-               if (private_layer->committing)
-                       TDM_WRN("layer(%d) too many commit", private_layer->index);
-               else
-                       private_layer->committing = 1;
-
+               /* add to layer_commit_handler_list */
                LIST_ADD(&layer_commit_handler->link, &private_output->layer_commit_handler_list);
-               ret = _tdm_output_commit(private_layer->private_output, 0, _tdm_layer_cb_output_commit, layer_commit_handler);
+
+               ret = _tdm_output_commit(private_layer->private_output, 0, NULL, NULL);
                TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
 
                if (tdm_debug_module & TDM_DEBUG_COMMIT)
                        TDM_INFO("layer(%p) commit: output", private_layer);
        } else {
-               if (private_layer->committing)
-                       TDM_WRN("layer(%d) too many commit", private_layer->index);
-               else
-                       private_layer->committing = 1;
-
+               /* add to pending_commit_handler_list. It will be commited when a vblank occurs */
                LIST_ADD(&layer_commit_handler->link, &private_output->pending_commit_handler_list);
 
                if (tdm_debug_module & TDM_DEBUG_COMMIT)
                        TDM_INFO("layer(%p) commit: pending", private_layer);
+       }
 
-               if (!private_output->vblank) {
-                       /* tdm_vblank APIs is for server. it should be called in unlock status*/
-                       _pthread_mutex_unlock(&private_display->lock);
-                       private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
-                       _pthread_mutex_lock(&private_display->lock);
-                       TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
-               }
+       if (!private_output->vblank) {
+               /* tdm_vblank APIs is for server. it should be called in unlock status*/
+               _pthread_mutex_unlock(&private_display->lock);
+               private_output->vblank = tdm_vblank_create(private_display, private_output, NULL);
+               _pthread_mutex_lock(&private_display->lock);
+               TDM_GOTO_IF_FAIL(private_output->vblank != NULL, commit_failed);
 
-               if (!private_output->waiting_vblank) {
-                       /* tdm_vblank APIs is for server. it should be called in unlock status*/
-                       _pthread_mutex_unlock(&private_display->lock);
-                       ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
-                       _pthread_mutex_lock(&private_display->lock);
-                       TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
-                       private_output->waiting_vblank = 1;
+               tdm_vblank_set_add_front(private_output->vblank, 1);
+       }
 
-                       if (tdm_debug_module & TDM_DEBUG_COMMIT)
-                               TDM_INFO("layer(%p) commit: wait vblank", private_layer);
-               }
+       if (!private_output->waiting_vblank) {
+               /* tdm_vblank APIs is for server. it should be called in unlock status*/
+               _pthread_mutex_unlock(&private_display->lock);
+               ret = tdm_vblank_wait(private_output->vblank, 0, 0, 1, _tdm_layer_cb_wait_vblank, private_output);
+               _pthread_mutex_lock(&private_display->lock);
+               TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
+               private_output->waiting_vblank = 1;
+
+               if (tdm_debug_module & TDM_DEBUG_COMMIT)
+                       TDM_INFO("layer(%p) commit: wait vblank", private_layer);
        }
 
        return ret;
index badde95..0d4cfda 100644 (file)
@@ -406,6 +406,10 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
 void
 tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms,
                                   void *user_data);
+tdm_error
+tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync,
+                                                                tdm_output_vblank_handler func, void *user_data);
+
 void
 tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
                           void *user_data);
@@ -414,6 +418,8 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer,
                                        void *user_data);
 tdm_error
 tdm_vblank_cb_vblank_SW(tdm_vblank *vblank, double vblank_stamp);
+tdm_error
+tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front);
 
 void
 tdm_output_call_change_handler_internal(tdm_private_output *private_output,
index 114e743..8e3f7db 100644 (file)
@@ -101,6 +101,8 @@ typedef struct _tdm_private_vblank {
        unsigned int last_seq;
        double last_time;
 
+       unsigned int add_front;
+
        /* for HW */
        double HW_vblank_gap;
        struct list_head HW_wait_list;
@@ -652,8 +654,12 @@ _tdm_vblank_wait_HW(tdm_vblank_wait_info *wait_info)
                                skip, hw_interval, wait_info->target_seq);
        }
 
-       ret = tdm_output_wait_vblank(private_vblank->output, hw_interval, 0,
-                                                                _tdm_vblank_cb_vblank_HW, wait_info);
+       if (private_vblank->add_front)
+               ret = tdm_output_wait_vblank_add_front(private_vblank->output, hw_interval, 0,
+                                                                                          _tdm_vblank_cb_vblank_HW, wait_info);
+       else
+               ret = tdm_output_wait_vblank(private_vblank->output, hw_interval, 0,
+                                                                        _tdm_vblank_cb_vblank_HW, wait_info);
 
        if (ret != TDM_ERROR_NONE) {
                LIST_DEL(&wait_info->link);
@@ -936,3 +942,21 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u
 
        return tdm_vblank_wait(vblank, req_sec, req_usec, interval, func, user_data);
 }
+
+INTERN tdm_error
+tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front)
+{
+       tdm_private_vblank *private_vblank = vblank;
+
+       TDM_RETURN_VAL_IF_FAIL(private_vblank != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
+
+       if (private_vblank->add_front == add_front)
+               return TDM_ERROR_NONE;
+
+       private_vblank->add_front = add_front;
+
+       return TDM_ERROR_NONE;
+}
+