tdm_hwc: make hwc_vblank set/unset function
[platform/core/uifw/libtdm.git] / src / tdm_hwc.c
index f6d1808..3131ebd 100644 (file)
@@ -70,6 +70,8 @@
        TDM_RETURN_IF_FAIL(private_output != NULL); \
        private_display = private_output->private_display
 
+static int hwc_use_vblank;
+static unsigned int hwc_vblank_fps;
 
 static tdm_private_hwc_window *
 _tdm_hwc_find_private_hwc_window(tdm_private_hwc *private_hwc, tdm_hwc_window *hwc_window_backend)
@@ -152,6 +154,9 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence,
        tdm_thread_cb_hwc_commit hwc_commit;
        tdm_error ret;
 
+       if (hwc_commit_handler && hwc_commit_handler->use_vblank)
+               return;
+
        if (hwc_commit_handler)
                private_hwc = hwc_commit_handler->private_hwc;
        else
@@ -171,6 +176,96 @@ _tdm_hwc_cb_commit(tdm_hwc *hwc_backend, unsigned int sequence,
        TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
 }
 
+static void
+_tdm_hwc_got_wait_vblank(unsigned int sequence,
+                                                unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+       tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
+       tdm_private_hwc *private_hwc;
+       tdm_thread_cb_hwc_commit hwc_commit;
+
+       private_hwc = hwc_commit_handler->private_hwc;
+       private_hwc->private_output->layer_waiting_vblank = 0;
+
+       memset(&hwc_commit, 0, sizeof hwc_commit);
+       hwc_commit.base.type = TDM_THREAD_CB_HWC_COMMIT;
+       hwc_commit.base.length = sizeof hwc_commit;
+       hwc_commit.base.object_stamp = private_hwc->stamp;
+       hwc_commit.base.data = hwc_commit_handler;
+       hwc_commit.base.sync = 0;
+       hwc_commit.sequence = sequence;
+       hwc_commit.tv_sec = tv_sec;
+       hwc_commit.tv_usec = tv_usec;
+
+       _tdm_hwc_thread_cb_commit(private_hwc->private_output->private_display, private_hwc, &hwc_commit.base, user_data);
+}
+
+static void
+_tdm_hwc_cb_wait_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence,
+                                               unsigned int tv_sec, unsigned int tv_usec, void *user_data)
+{
+       tdm_private_hwc_commit_handler *hwc_commit_handler = user_data;
+       tdm_private_output *private_output = NULL;
+       tdm_private_display *private_display;
+
+       if (!hwc_commit_handler->use_vblank)
+               return;
+
+       TDM_RETURN_IF_FAIL(hwc_commit_handler != NULL);
+
+       private_output = hwc_commit_handler->private_hwc->private_output;
+       TDM_RETURN_IF_FAIL(private_output != NULL);
+
+       private_display = private_output->private_display;
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       _tdm_hwc_got_wait_vblank(sequence, tv_sec, tv_usec, user_data);
+
+       _pthread_mutex_unlock(&private_display->lock);
+}
+
+static tdm_error
+_tdm_hwc_vblank(tdm_private_hwc *private_hwc, tdm_private_hwc_commit_handler *hwc_commit_handler)
+{
+       tdm_private_display *private_display;
+       tdm_private_output *private_output;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       private_output = private_hwc->private_output;
+       TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       private_display = private_output->private_display;
+
+       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_RETURN_VAL_IF_FAIL(private_output->vblank != NULL, TDM_ERROR_OPERATION_FAILED);
+       }
+
+       if (!private_output->layer_waiting_vblank) {
+               ret = tdm_vblank_set_fps(private_output->vblank, hwc_vblank_fps);
+               if (ret != TDM_ERROR_NONE)
+                       goto done;
+
+               /* 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_hwc_cb_wait_vblank, hwc_commit_handler);
+               _pthread_mutex_lock(&private_display->lock);
+               if (ret != TDM_ERROR_NONE) {
+                       if (!TDM_OUTPUT_DPMS_VSYNC_IS_OFF(private_output->current_dpms_value))
+                               goto done;
+               }
+
+               hwc_commit_handler->use_vblank = 1;
+               private_output->layer_waiting_vblank = 1;
+       }
+
+done:
+       return ret;
+}
+
 INTERN tdm_error
 tdm_hwc_init(tdm_private_display *private_display)
 {
@@ -179,6 +274,20 @@ tdm_hwc_init(tdm_private_display *private_display)
        return TDM_ERROR_NONE;
 }
 
+INTERN void
+tdm_hwc_set_vblank(unsigned int fps)
+{
+       hwc_use_vblank = 1;
+       hwc_vblank_fps = fps;
+}
+
+INTERN void
+tdm_hwc_unset_vblank(void)
+{
+       hwc_use_vblank = 0;
+       hwc_vblank_fps = 0;
+}
+
 EXTERN tdm_hwc_window *
 tdm_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
 {
@@ -635,9 +744,19 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d
        ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler);
        TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
 
-       if (tdm_debug_module & TDM_DEBUG_COMMIT)
-               TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)",
-                               private_hwc->index, hwc_commit_handler, func, user_data);
+       if (hwc_use_vblank) {
+               ret = _tdm_hwc_vblank(private_hwc, hwc_commit_handler);
+               if (ret == TDM_ERROR_NONE) {
+                       if (tdm_debug_module & TDM_DEBUG_COMMIT)
+                               TDM_INFO("hwc(%d) backend commit: wait vblank handle(%p) func(%p) user_data(%p)",
+                                       private_hwc->index, hwc_commit_handler, func, user_data);
+               } else
+                       goto commit_failed;
+       } else {
+               if (tdm_debug_module & TDM_DEBUG_COMMIT)
+                       TDM_INFO("hwc(%d) backend commit: handle(%p) func(%p) user_data(%p)",
+                                       private_hwc->index, hwc_commit_handler, func, user_data);
+       }
 
        _pthread_mutex_unlock(&private_display->lock);