Merge branch 'tizen' into sandbox/cyeon/devel
[platform/core/uifw/libtdm.git] / src / tdm_pp.c
index 3be10d3..a53531a 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
 #include "config.h"
 #endif
 
-#include "tdm.h"
-#include "tdm_backend.h"
 #include "tdm_private.h"
-#include "tdm_helper.h"
 
 #define PP_FUNC_ENTRY() \
+       tdm_private_module *private_module; \
        tdm_func_pp *func_pp; \
        tdm_private_display *private_display; \
        tdm_private_pp *private_pp; \
@@ -50,7 +48,8 @@
        TDM_RETURN_VAL_IF_FAIL(pp != NULL, TDM_ERROR_INVALID_PARAMETER); \
        private_pp = (tdm_private_pp*)pp; \
        private_display = private_pp->private_display; \
-       func_pp = &private_display->func_pp
+       private_module = private_pp->private_module; \
+       func_pp = &private_module->func_pp
 
 static void
 _tdm_pp_print_list(struct list_head *list)
@@ -61,17 +60,23 @@ _tdm_pp_print_list(struct list_head *list)
 
        TDM_RETURN_IF_FAIL(list != NULL);
 
+       str[0] = '\0';
        p = str;
        LIST_FOR_EACH_ENTRY(b, list, link) {
                if (len > 0) {
-                       int l = snprintf(p, len, " (%p,%p)", b->src, b->dst);
+                       tbm_bo src_bo = tbm_surface_internal_get_bo(b->src, 0);
+                       tbm_bo dst_bo = tbm_surface_internal_get_bo(b->dst, 0);
+                       int src_flags = tbm_bo_get_flags(src_bo);
+                       int dst_flags = tbm_bo_get_flags(dst_bo);
+                       int l = snprintf(p, len, " (%p[bo_flags:%x], %p[bo_flags:%x])",
+                                                        b->src, src_flags, b->dst, dst_flags);
                        p += l;
                        len -= l;
                } else
                        break;
        }
 
-       TDM_WRN("\t %s", str);
+       TDM_INFO("\t %s", str);
 }
 
 static tdm_pp_private_buffer *
@@ -100,46 +105,31 @@ _tdm_pp_find_buffer(struct list_head *list, tdm_pp_private_buffer *pp_buffer)
        return NULL;
 }
 
-INTERN void
-tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
-                          void *user_data)
+static void
+_tdm_pp_thread_cb_done(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
 {
-       tdm_private_pp *private_pp = user_data;
-       tdm_private_display *private_display = private_pp->private_display;
+       tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done *)cb_base;
+       tdm_private_pp *private_pp = object;
        tdm_pp_private_buffer *pp_buffer = NULL, *first_entry = NULL;
+       tbm_surface_h src;
+       tbm_surface_h dst;
 
        TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
 
-       if (private_pp->owner_tid != syscall(SYS_gettid)) {
-               tdm_thread_cb_pp_done pp_done;
-               tdm_error ret;
-
-               pp_done.base.type = TDM_THREAD_CB_PP_DONE;
-               pp_done.base.length = sizeof pp_done;
-               pp_done.pp_stamp = private_pp->stamp;
-               pp_done.src = src;
-               pp_done.dst = dst;
-               pp_done.user_data = user_data;
-
-               ret = tdm_thread_send_cb(private_display->private_loop, &pp_done.base);
-               TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
-
-               return;
-       }
+       assert(private_pp->owner_tid == syscall(SYS_gettid));
 
-       if (private_pp->owner_tid != syscall(SYS_gettid))
-               TDM_NEVER_GET_HERE();
+       src = pp_done->src;
+       dst = pp_done->dst;
 
        if (tdm_debug_dump & TDM_DUMP_FLAG_PP) {
+               /* LCOV_EXCL_START */
                char str[TDM_PATH_LEN];
                static int i;
                snprintf(str, TDM_PATH_LEN, "pp_dst_%03d", i++);
                tdm_helper_dump_buffer_str(dst, tdm_debug_dump_dir, str);
+               /* LCOV_EXCL_STOP */
        }
 
-       if (tdm_debug_module & TDM_DEBUG_BUFFER)
-               TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
-
        if (!LIST_IS_EMPTY(&private_pp->buffer_list)) {
                first_entry = container_of((&private_pp->buffer_list)->next, pp_buffer, link);
                if (first_entry->src != src || first_entry->dst != dst)
@@ -150,6 +140,15 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
 
        if ((pp_buffer = _tdm_pp_find_tbm_buffers(&private_pp->buffer_list, src, dst))) {
                LIST_DEL(&pp_buffer->link);
+               LIST_DELINIT(&pp_buffer->commit_link);
+
+               if (tdm_debug_module & TDM_DEBUG_BUFFER)
+                       TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
+
+               if (tdm_ttrace_module & TDM_TTRACE_PP) {
+                       tbm_bo bo = tbm_surface_internal_get_bo(dst, 0);
+                       TDM_TRACE_ASYNC_END((intptr_t)private_pp, "[PP] %d", tbm_bo_export(bo));
+               }
 
                _pthread_mutex_unlock(&private_display->lock);
                if (private_pp->done_func)
@@ -162,74 +161,130 @@ tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
        }
 }
 
-INTERN tdm_private_pp *
-tdm_pp_find_stamp(tdm_private_display *private_display, double stamp)
+static void
+_tdm_pp_cb_done(tdm_pp *pp_module, tbm_surface_h src, tbm_surface_h dst, void *user_data)
+{
+       tdm_thread_cb_pp_done pp_done;
+       tdm_private_pp *private_pp = user_data;
+       tdm_error ret;
+
+       TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
+       memset(&pp_done, 0, sizeof pp_done);
+       pp_done.base.type = TDM_THREAD_CB_PP_DONE;
+       pp_done.base.length = sizeof pp_done;
+       pp_done.base.object_stamp = private_pp->stamp;
+       pp_done.base.data = NULL;
+       pp_done.base.sync = 0;
+       pp_done.src = src;
+       pp_done.dst = dst;
+
+       ret = tdm_thread_cb_call(private_pp, &pp_done.base, 1);
+       TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+}
+
+static void *
+_tdm_pp_find_object(tdm_private_display *private_display, double stamp)
 {
+       tdm_private_module *private_module = NULL;
        tdm_private_pp *private_pp = NULL;
 
        TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
 
-       LIST_FOR_EACH_ENTRY(private_pp, &private_display->pp_list, link) {
-               if (private_pp->stamp == stamp)
-                       return private_pp;
+       LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
+               LIST_FOR_EACH_ENTRY(private_pp, &private_module->pp_list, link) {
+                       if (private_pp->stamp == stamp)
+                               return private_pp;
+               }
        }
 
        return NULL;
 }
 
+INTERN tdm_error
+tdm_pp_init(tdm_private_display *private_display)
+{
+       tdm_thread_cb_set_find_func(TDM_THREAD_CB_PP_DONE, _tdm_pp_find_object);
+
+       return TDM_ERROR_NONE;
+}
+
 INTERN tdm_private_pp *
-tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error)
+tdm_pp_create_internal(tdm_private_module *private_module, tdm_error *error)
 {
+       tdm_private_display *private_display;
        tdm_func_display *func_display;
        tdm_func_pp *func_pp;
        tdm_private_pp *private_pp = NULL;
-       tdm_pp *pp_backend = NULL;
+       tdm_pp *pp_module = NULL;
        tdm_error ret = TDM_ERROR_NONE;
 
        TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
+       TDM_RETURN_VAL_IF_FAIL(private_module != NULL, NULL);
 
-       func_display = &private_display->func_display;
-       func_pp = &private_display->func_pp;
+       private_display = private_module->private_display;
+       func_display = &private_module->func_display;
+       func_pp = &private_module->func_pp;
 
-       if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
-               TDM_ERR("no pp capability");
+       if (!(private_module->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
+               /* LCOV_EXCL_START */
+               TDM_ERR("backedn(%s) no pp capability", private_module->module_data->name);
                if (error)
                        *error = TDM_ERROR_NO_CAPABILITY;
                return NULL;
+               /* LCOV_EXCL_STOP */
        }
 
-       pp_backend = func_display->display_create_pp(private_display->bdata, &ret);
+       pp_module = func_display->display_create_pp(private_module->bdata, &ret);
        if (ret != TDM_ERROR_NONE) {
+               /* LCOV_EXCL_START */
                if (error)
                        *error = ret;
                return NULL;
+               /* LCOV_EXCL_STOP */
        }
 
        private_pp = calloc(1, sizeof(tdm_private_pp));
        if (!private_pp) {
+               /* LCOV_EXCL_START */
                TDM_ERR("failed: alloc memory");
-               func_pp->pp_destroy(pp_backend);
+               func_pp->pp_destroy(pp_module);
                if (error)
                        *error = TDM_ERROR_OUT_OF_MEMORY;
                return NULL;
+               /* LCOV_EXCL_STOP */
        }
 
-       ret = func_pp->pp_set_done_handler(pp_backend, tdm_pp_cb_done, private_pp);
+       ret = tdm_thread_cb_add(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL);
        if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("pp tdm_thread_cb_add failed");
+               func_pp->pp_destroy(pp_module);
+               free(private_pp);
+               if (error)
+                       *error = ret;
+               return NULL;
+       }
+
+       ret = func_pp->pp_set_done_handler(pp_module, _tdm_pp_cb_done, private_pp);
+       if (ret != TDM_ERROR_NONE) {
+               /* LCOV_EXCL_START */
                TDM_ERR("spp(%p) et pp_done_handler failed", private_pp);
-               func_pp->pp_destroy(pp_backend);
+               func_pp->pp_destroy(pp_module);
+               free(private_pp);
                if (error)
                        *error = ret;
                return NULL;
+               /* LCOV_EXCL_STOP */
        }
 
        private_pp->stamp = tdm_helper_get_time();
-       while (tdm_pp_find_stamp(private_display, private_pp->stamp))
+       while (_tdm_pp_find_object(private_display, private_pp->stamp))
                private_pp->stamp++;
 
-       LIST_ADD(&private_pp->link, &private_display->pp_list);
-       private_pp->private_display = private_display;
-       private_pp->pp_backend = pp_backend;
+       LIST_ADD(&private_pp->link, &private_module->pp_list);
+       private_pp->private_display = private_module->private_display;
+       private_pp->private_module = private_module;
+       private_pp->pp_module = pp_module;
        private_pp->owner_tid = syscall(SYS_gettid);
 
        LIST_INITHEAD(&private_pp->pending_buffer_list);
@@ -245,6 +300,7 @@ INTERN void
 tdm_pp_destroy_internal(tdm_private_pp *private_pp)
 {
        tdm_private_display *private_display;
+       tdm_private_module *private_module;
        tdm_func_pp *func_pp;
        tdm_pp_private_buffer *b = NULL, *bb = NULL;
        struct list_head clone_list;
@@ -254,12 +310,15 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp)
        if (!private_pp)
                return;
 
+       tdm_thread_cb_remove(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL);
+
        private_display = private_pp->private_display;
-       func_pp = &private_display->func_pp;
+       private_module = private_pp->private_module;
+       func_pp = &private_module->func_pp;
 
        LIST_DEL(&private_pp->link);
 
-       func_pp->pp_destroy(private_pp->pp_backend);
+       func_pp->pp_destroy(private_pp->pp_module);
 
        if (!LIST_IS_EMPTY(&private_pp->pending_buffer_list)) {
                TDM_WRN("pp(%p) not finished:", private_pp);
@@ -274,6 +333,12 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp)
                _pthread_mutex_unlock(&private_display->lock);
                LIST_FOR_EACH_ENTRY_SAFE(b, bb, &clone_list, link) {
                        LIST_DEL(&b->link);
+
+                       if (tdm_ttrace_module & TDM_TTRACE_PP) {
+                               tbm_bo bo = tbm_surface_internal_get_bo(b->dst, 0);
+                               TDM_TRACE_ASYNC_END((intptr_t)private_pp, "[PP] %d", tbm_bo_export(bo));
+                       }
+
                        tdm_buffer_unref_backend(b->src);
                        tdm_buffer_unref_backend(b->dst);
                        free(b);
@@ -294,6 +359,12 @@ tdm_pp_destroy_internal(tdm_private_pp *private_pp)
                _pthread_mutex_unlock(&private_display->lock);
                LIST_FOR_EACH_ENTRY_SAFE(b, bb, &clone_list, link) {
                        LIST_DEL(&b->link);
+
+                       if (tdm_ttrace_module & TDM_TTRACE_PP) {
+                               tbm_bo bo = tbm_surface_internal_get_bo(b->dst, 0);
+                               TDM_TRACE_ASYNC_END((intptr_t)private_pp, "[PP] %d", tbm_bo_export(bo));
+                       }
+
                        tdm_buffer_unref_backend(b->src);
                        tdm_buffer_unref_backend(b->dst);
                        free(b);
@@ -331,12 +402,14 @@ tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
        _pthread_mutex_lock(&private_display->lock);
 
        if (!func_pp->pp_set_info) {
+               /* LCOV_EXCL_START */
                _pthread_mutex_unlock(&private_display->lock);
                TDM_DBG("failed: not implemented!!");
                return TDM_ERROR_NOT_IMPLEMENTED;
+               /* LCOV_EXCL_STOP */
        }
 
-       TDM_INFO("pp(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%dx%d %d,%d %dx%d %c%c%c%c) trans(%d) sync(%d) flags(%x)",
+       TDM_INFO("pp(%p) info: src(%ux%u %u,%u %ux%u %c%c%c%c) dst(%ux%u %u,%u %ux%u %c%c%c%c) trans(%d) sync(%d) flags(%x)",
                         private_pp, info->src_config.size.h, info->src_config.size.v,
                         info->src_config.pos.x, info->src_config.pos.y,
                         info->src_config.pos.w, info->src_config.pos.h,
@@ -347,7 +420,7 @@ tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
                         FOURCC_STR(info->dst_config.format),
                         info->transform, info->sync, info->flags);
 
-       ret = func_pp->pp_set_info(private_pp->pp_backend, info);
+       ret = func_pp->pp_set_info(private_pp->pp_module, info);
        TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
 
        private_pp->info = *info;
@@ -394,45 +467,55 @@ tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
        _pthread_mutex_lock(&private_display->lock);
 
        if (!func_pp->pp_attach) {
+               /* LCOV_EXCL_START */
                _pthread_mutex_unlock(&private_display->lock);
                TDM_DBG("failed: not implemented!!");
                return TDM_ERROR_NOT_IMPLEMENTED;
+               /* LCOV_EXCL_STOP */
        }
 
-       if (tdm_display_check_module_abi(private_display, 1, 2) &&
-               private_display->caps_pp.max_attach_count > 0) {
+       if (tdm_module_check_abi(private_module, 1, 2) &&
+               private_module->caps_pp.max_attach_count > 0) {
+               /* LCOV_EXCL_START */
                int length = LIST_LENGTH(&private_pp->pending_buffer_list) +
                                         LIST_LENGTH(&private_pp->buffer_list);
-               if (length >= private_display->caps_pp.max_attach_count) {
+               if (length >= private_module->caps_pp.max_attach_count) {
                        _pthread_mutex_unlock(&private_display->lock);
-                       TDM_DBG("failed: too many attached!! max_attach_count(%d)",
-                                       private_display->caps_pp.max_attach_count);
+                       TDM_DBG("failed: backend(%s) too many attached!! max_attach_count(%d)",
+                                       private_module->module_data->name, private_module->caps_pp.max_attach_count);
                        return TDM_ERROR_BAD_REQUEST;
                }
+               /* LCOV_EXCL_STOP */
        }
 
        if (tdm_debug_dump & TDM_DUMP_FLAG_PP) {
+               /* LCOV_EXCL_START */
                char str[TDM_PATH_LEN];
                static int i;
                snprintf(str, TDM_PATH_LEN, "pp_src_%03d", i++);
                tdm_helper_dump_buffer_str(src, tdm_debug_dump_dir, str);
+               /* LCOV_EXCL_STOP */
        }
 
-       pp_buffer = calloc(1, sizeof *pp_buffer);
+       pp_buffer = calloc(1, sizeof * pp_buffer);
        if (!pp_buffer) {
+               /* LCOV_EXCL_START */
                _pthread_mutex_unlock(&private_display->lock);
                TDM_ERR("alloc failed");
                return TDM_ERROR_OUT_OF_MEMORY;
+               /* LCOV_EXCL_STOP */
        }
 
-       ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
+       ret = func_pp->pp_attach(private_pp->pp_module, src, dst);
        TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
 
        if (ret != TDM_ERROR_NONE) {
+               /* LCOV_EXCL_START */
                free(pp_buffer);
                _pthread_mutex_unlock(&private_display->lock);
                TDM_ERR("attach failed");
                return ret;
+               /* LCOV_EXCL_STOP */
        }
 
        LIST_ADDTAIL(&pp_buffer->link, &private_pp->pending_buffer_list);
@@ -444,6 +527,11 @@ tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
                _tdm_pp_print_list(&private_pp->pending_buffer_list);
        }
 
+       if (tdm_ttrace_module & TDM_TTRACE_PP) {
+               tbm_bo bo = tbm_surface_internal_get_bo(dst, 0);
+               TDM_TRACE_ASYNC_BEGIN((intptr_t)pp, "[PP] %d", tbm_bo_export(bo));
+       }
+
        _pthread_mutex_unlock(&private_display->lock);
 
        return ret;
@@ -460,9 +548,11 @@ tdm_pp_commit(tdm_pp *pp)
        _pthread_mutex_lock(&private_display->lock);
 
        if (!func_pp->pp_commit) {
+               /* LCOV_EXCL_START */
                _pthread_mutex_unlock(&private_display->lock);
                TDM_DBG("failed: not implemented!!");
                return TDM_ERROR_NOT_IMPLEMENTED;
+               /* LCOV_EXCL_STOP */
        }
 
        LIST_INITHEAD(&commit_buffer_list);
@@ -473,29 +563,23 @@ tdm_pp_commit(tdm_pp *pp)
                LIST_ADDTAIL(&b->commit_link, &commit_buffer_list);
        }
 
-       ret = func_pp->pp_commit(private_pp->pp_backend);
+       ret = func_pp->pp_commit(private_pp->pp_module);
        TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
 
        LIST_FOR_EACH_ENTRY_SAFE(b, bb, &commit_buffer_list, commit_link) {
-               LIST_DEL(&b->commit_link);
+               LIST_DELINIT(&b->commit_link);
 
                if (!_tdm_pp_find_buffer(&private_pp->buffer_list, b))
                        continue;
 
                if (ret != TDM_ERROR_NONE) {
-                       /* Not to call the user release handler when failed.
-                        * Do we have to call this function here really?
-                        * User better use set_done_handler to know when pp is done. Using
-                        * buffer_release_handler is not good.
-                        */
-                       tdm_buffer_remove_release_handler_internal(b->src);
-                       tdm_buffer_remove_release_handler_internal(b->dst);
-
                        _pthread_mutex_unlock(&private_display->lock);
                        tdm_buffer_unref_backend(b->src);
                        tdm_buffer_unref_backend(b->dst);
                        _pthread_mutex_lock(&private_display->lock);
                        LIST_DEL(&b->link);
+
+                       free(b);
                }
        }