get version in configuration time
[platform/core/uifw/libtdm.git] / src / tdm.c
index 1d279f3..f073d21 100644 (file)
--- a/src/tdm.c
+++ b/src/tdm.c
@@ -42,6 +42,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "tdm_private.h"
 #include "tdm_helper.h"
 
+pthread_mutex_t tdm_mutex_check_lock = PTHREAD_MUTEX_INITIALIZER;
+int tdm_mutex_locked;
+
 static tdm_private_layer *
 _tdm_display_find_private_layer(tdm_private_output *private_output,
                                 tdm_layer *layer_backend)
@@ -87,30 +90,42 @@ tdm_display_find_output_stamp(tdm_private_display *private_display,
 static void
 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
 {
-       free(caps_pp->formats);
+       if (caps_pp->formats)
+               free(caps_pp->formats);
+
        memset(caps_pp, 0, sizeof(tdm_caps_pp));
 }
 
 static void
 _tdm_display_destroy_caps_capture(tdm_caps_capture *caps_capture)
 {
-       free(caps_capture->formats);
+       if (caps_capture->formats)
+               free(caps_capture->formats);
+
        memset(caps_capture, 0, sizeof(tdm_caps_capture));
 }
 
 static void
 _tdm_display_destroy_caps_layer(tdm_caps_layer *caps_layer)
 {
-       free(caps_layer->formats);
-       free(caps_layer->props);
+       if (caps_layer->formats)
+               free(caps_layer->formats);
+
+       if (caps_layer->props)
+               free(caps_layer->props);
+
        memset(caps_layer, 0, sizeof(tdm_caps_layer));
 }
 
 static void
 _tdm_display_destroy_caps_output(tdm_caps_output *caps_output)
 {
-       free(caps_output->modes);
-       free(caps_output->props);
+       if (caps_output->modes)
+               free(caps_output->modes);
+
+       if (caps_output->props)
+               free(caps_output->props);
+
        memset(caps_output, 0, sizeof(tdm_caps_output));
 }
 
@@ -152,7 +167,12 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
                free(m);
        }
 
-       LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list, link) {
+       LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_main, link) {
+               LIST_DEL(&h->link);
+               free(h);
+       }
+
+       LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
                LIST_DEL(&h->link);
                free(h);
        }
@@ -299,10 +319,11 @@ _tdm_display_update_caps_layer(tdm_private_display *private_display,
 }
 
 static tdm_error
-_tdm_display_update_caps_output(tdm_private_display *private_display,
+_tdm_display_update_caps_output(tdm_private_display *private_display, int pipe,
                                 tdm_output *output_backend, tdm_caps_output *caps)
 {
        tdm_func_output *func_output = &private_display->func_output;
+       char temp[TDM_NAME_LEN];
        int i;
        tdm_error ret;
 
@@ -317,6 +338,10 @@ _tdm_display_update_caps_output(tdm_private_display *private_display,
                return TDM_ERROR_BAD_MODULE;
        }
 
+       /* FIXME: Use model for tdm client to distinguish amoung outputs */
+       snprintf(temp, TDM_NAME_LEN, "%s-%d", caps->model, pipe);
+       snprintf(caps->model, TDM_NAME_LEN, "%s", temp);
+
        TDM_DBG("output maker: %s", caps->maker);
        TDM_DBG("output model: %s", caps->model);
        TDM_DBG("output name: %s", caps->name);
@@ -377,40 +402,6 @@ failed_update:
        return ret;
 }
 
-INTERN void
-tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
-                     void *user_data)
-{
-       tdm_private_display *private_display;
-       tdm_private_output *private_output = user_data;
-       tdm_value value;
-
-       TDM_RETURN_IF_FAIL(private_output);
-
-       private_display = private_output->private_display;
-
-       if (!tdm_thread_in_display_thread(private_display)) {
-               tdm_thread_cb_output_status output_status;
-               tdm_error ret;
-
-               output_status.base.type = TDM_THREAD_CB_OUTPUT_STATUS;
-               output_status.base.length = sizeof output_status;
-               output_status.output_stamp = private_output->stamp;
-               output_status.status = status;
-               output_status.user_data = user_data;
-
-               ret = tdm_thread_send_cb(private_display, &output_status.base);
-               TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
-
-               return;
-       }
-
-       value.u32 = status;
-       tdm_output_call_change_handler_internal(private_output,
-                                               TDM_OUTPUT_CHANGE_CONNECTION,
-                                               value);
-}
-
 static tdm_error
 _tdm_display_update_output(tdm_private_display *private_display,
                            tdm_output *output_backend, int pipe)
@@ -431,9 +422,10 @@ _tdm_display_update_output(tdm_private_display *private_display,
                while (tdm_display_find_output_stamp(private_display, private_output->stamp))
                        private_output->stamp++;
 
-               LIST_ADD(&private_output->link, &private_display->output_list);
+               LIST_ADDTAIL(&private_output->link, &private_display->output_list);
 
                private_output->private_display = private_display;
+               private_output->current_dpms_value = TDM_OUTPUT_DPMS_OFF;
                private_output->output_backend = output_backend;
                private_output->pipe = pipe;
 
@@ -441,20 +433,18 @@ _tdm_display_update_output(tdm_private_display *private_display,
                LIST_INITHEAD(&private_output->capture_list);
                LIST_INITHEAD(&private_output->vblank_handler_list);
                LIST_INITHEAD(&private_output->commit_handler_list);
-               LIST_INITHEAD(&private_output->change_handler_list);
-
-               if (func_output->output_set_status_handler) {
-                       private_output->regist_change_cb = 1;
-                       ret = func_output->output_set_status_handler(output_backend,
-                                                                    tdm_output_cb_status,
-                                                                    private_output);
-                       if (ret != TDM_ERROR_NONE)
-                               goto failed_update;
-               }
+               LIST_INITHEAD(&private_output->change_handler_list_main);
+               LIST_INITHEAD(&private_output->change_handler_list_sub);
+
+               if (func_output->output_set_status_handler)
+                       func_output->output_set_status_handler(private_output->output_backend,
+                                                              tdm_output_cb_status,
+                                                              private_output);
+
        } else
                _tdm_display_destroy_caps_output(&private_output->caps);
 
-       ret = _tdm_display_update_caps_output(private_display, output_backend,
+       ret = _tdm_display_update_caps_output(private_display, pipe, output_backend,
                                              &private_output->caps);
        if (ret != TDM_ERROR_NONE)
                return ret;
@@ -478,11 +468,139 @@ failed_update:
        return ret;
 }
 
+static tdm_output **
+_tdm_display_set_main_first(tdm_output **outputs, int index)
+{
+       tdm_output *output_tmp = NULL;
+
+       if (index == 0)
+               return outputs;
+
+       output_tmp = outputs[0];
+       outputs[0] = outputs[index];
+       outputs[index] = output_tmp;
+
+       return outputs;
+}
+
+static tdm_output **
+_tdm_display_get_ordered_outputs(tdm_private_display *private_display,
+                           int *count, int init)
+{
+       tdm_func_display *func_display = &private_display->func_display;
+       tdm_output **outputs = NULL;
+       tdm_output **new_outputs = NULL;
+       tdm_output *output_dsi = NULL;
+       tdm_output *output_lvds = NULL;
+       tdm_output *output_hdmia = NULL;
+       tdm_output *output_hdmib = NULL;
+       int i, output_count = 0, output_connected_count = 0;
+       int index_dsi = 0, index_lvds = 0, index_hdmia = 0, index_hdmib = 0;
+       tdm_error ret;
+
+       outputs = func_display->display_get_outputs(private_display->bdata,
+                       &output_count, &ret);
+       if (ret != TDM_ERROR_NONE)
+               goto failed_get_outputs;
+
+       *count = output_count;
+
+       if (output_count == 0)
+               goto failed_get_outputs;
+       else if (output_count == 1)
+               return outputs;
+
+       /* don't change list order if not init time */
+       if (init != 0)
+               return outputs;
+
+       /* count connected outputs */
+       for (i = 0; i < output_count; i++) {
+               tdm_func_output *func_output = &private_display->func_output;
+               tdm_caps_output caps;
+               memset(&caps, 0, sizeof(tdm_caps_output));
+
+               if (!func_output->output_get_capability) {
+                       TDM_ERR("no output_get_capability()");
+                       return outputs;
+               }
+
+               ret = func_output->output_get_capability(outputs[i], &caps);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("output_get_capability() failed");
+                       return outputs;
+               }
+
+               if (caps.status == TDM_OUTPUT_CONN_STATUS_CONNECTED) {
+                       output_connected_count++;
+
+                       switch (caps.type) {
+                       case TDM_OUTPUT_TYPE_DSI:
+                               output_dsi = outputs[i];
+                               index_dsi = i;
+                               break;
+                       case TDM_OUTPUT_TYPE_LVDS:
+                               output_lvds = outputs[i];
+                               index_lvds = i;
+                               break;
+                       case TDM_OUTPUT_TYPE_HDMIA:
+                               output_hdmia = outputs[i];
+                               index_hdmia = i;
+                               break;
+                       case TDM_OUTPUT_TYPE_HDMIB:
+                               output_hdmib = outputs[i];
+                               index_hdmib = i;
+                               break;
+                       default :
+                               break;
+                       }
+               }
+       }
+
+       /* ordering : main output is first */
+       /* If there is no connected output, lvds or dsi cannot be main display. (cannot connect after booting)
+         * But hdmi is possible, so set hdmi to main display.
+         * If connected only one output, it is main output.
+         * If connected outputs over 2, has priority like below.
+         * (dsi > lvds > hdmi > else)
+         */
+       if (output_connected_count == 0) {
+               /* hdmi > dsi > lvds > else */
+               if (output_hdmia != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_hdmia);
+               else if (output_hdmib != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_hdmib);
+               else if (output_dsi != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_dsi);
+               else if (output_lvds != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_lvds);
+               else
+                       new_outputs = outputs;
+       } else { /* (output_connected_count > 1) */
+               /* dsi > lvds > hdmi > else */
+               if (output_dsi != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_dsi);
+               else if (output_lvds != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_lvds);
+               else if (output_hdmia != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_hdmia);
+               else if (output_hdmib != NULL)
+                       new_outputs = _tdm_display_set_main_first(outputs, index_hdmib);
+               else
+                       new_outputs = outputs;
+       }
+
+       return new_outputs;
+
+failed_get_outputs:
+       *count = 0;
+       return NULL;
+}
+
 static tdm_error
 _tdm_display_update_internal(tdm_private_display *private_display,
                              int only_display)
 {
-       tdm_func_display *func_display = &private_display->func_display;
        tdm_output **outputs = NULL;
        int output_count = 0, i;
        tdm_error ret;
@@ -502,9 +620,8 @@ _tdm_display_update_internal(tdm_private_display *private_display,
                        goto failed_update;
        }
 
-       outputs = func_display->display_get_outputs(private_display->bdata,
-                       &output_count, &ret);
-       if (ret != TDM_ERROR_NONE)
+       outputs = _tdm_display_get_ordered_outputs(private_display, &output_count, only_display);
+       if (!outputs)
                goto failed_update;
 
        for (i = 0; i < output_count; i++) {
@@ -558,12 +675,9 @@ _tdm_display_check_module(tdm_backend_module *module)
        const char *name;
        const char *vendor;
        int major, minor;
-       int abimaj, abimin;
 
-       abimaj = TDM_BACKEND_GET_ABI_MAJOR(TDM_BACKEND_ABI_VERSION);
-       abimin = TDM_BACKEND_GET_ABI_MINOR(TDM_BACKEND_ABI_VERSION);
-
-       TDM_INFO("TDM module ABI version : %d.%d", abimaj, abimin);
+       TDM_INFO("TDM ABI version : %d.%d",
+                TDM_MAJOR_VERSION, TDM_MINOR_VERSION);
 
        name = module->name ? module->name : "unknown";
        vendor = module->vendor ? module->vendor : "unknown";
@@ -574,13 +688,15 @@ _tdm_display_check_module(tdm_backend_module *module)
        TDM_INFO("'%s' vendor: %s", name, vendor);
        TDM_INFO("'%s' version: %d.%d", name, major, minor);
 
-       if (major != abimaj) {
-               TDM_ERR("'%s' major version mismatch, %d != %d", name, major, abimaj);
+       if (major != TDM_MAJOR_VERSION) {
+               TDM_ERR("'%s' major version mismatch, %d != %d",
+                       name, major, TDM_MAJOR_VERSION);
                return TDM_ERROR_BAD_MODULE;
        }
 
-       if (minor > abimin) {
-               TDM_ERR("'%s' minor version(%d) is newer than %d", name, minor, abimin);
+       if (minor > TDM_MINOR_VERSION) {
+               TDM_ERR("'%s' minor version(%d) is newer than %d",
+                       name, minor, TDM_MINOR_VERSION);
                return TDM_ERROR_BAD_MODULE;
        }
 
@@ -809,25 +925,37 @@ tdm_display_init(tdm_error *error)
                goto failed_mutex_init;
        }
 
-       ret = tdm_event_init(private_display);
-       if (ret != TDM_ERROR_NONE)
-               goto failed_event;
+       _pthread_mutex_lock(&private_display->lock);
 
-       ret = tdm_thread_init(private_display);
+       ret = tdm_event_loop_init(private_display);
        if (ret != TDM_ERROR_NONE)
-               goto failed_thread;
+               goto failed_event;
 
        ret = _tdm_display_load_module(private_display);
        if (ret != TDM_ERROR_NONE)
                goto failed_load;
 
+#ifdef INIT_BUFMGR
+       int tdm_drm_fd = tdm_helper_get_fd("TDM_DRM_MASTER_FD");
+       if (tdm_drm_fd >= 0) {
+               private_display->bufmgr = tbm_bufmgr_init(tdm_drm_fd);
+               close(tdm_drm_fd);
+               if (!private_display->bufmgr) {
+                       TDM_ERR("tbm_bufmgr_init failed");
+                       goto failed_update;
+               } else {
+                       TDM_INFO("tbm_bufmgr_init successed");
+               }
+       }
+#endif
+
        TDM_TRACE_BEGIN(Update_Display);
        ret = _tdm_display_update_internal(private_display, 0);
        TDM_TRACE_END();
        if (ret != TDM_ERROR_NONE)
                goto failed_update;
 
-       tdm_event_create_backend_source(private_display);
+       tdm_event_loop_create_backend_source(private_display);
 
        private_display->init_count = 1;
 
@@ -836,6 +964,7 @@ tdm_display_init(tdm_error *error)
        if (error)
                *error = TDM_ERROR_NONE;
 
+       _pthread_mutex_unlock(&private_display->lock);
        _pthread_mutex_unlock(&gLock);
 
        return (tdm_display *)private_display;
@@ -843,10 +972,9 @@ tdm_display_init(tdm_error *error)
 failed_update:
        _tdm_display_unload_module(private_display);
 failed_load:
-       tdm_thread_deinit(private_display);
-failed_thread:
-       tdm_event_deinit(private_display);
+       tdm_event_loop_deinit(private_display);
 failed_event:
+       _pthread_mutex_unlock(&private_display->lock);
        pthread_mutex_destroy(&private_display->lock);
 failed_mutex_init:
        free(private_display);
@@ -877,12 +1005,16 @@ tdm_display_deinit(tdm_display *dpy)
 
        _pthread_mutex_lock(&private_display->lock);
 
-       tdm_thread_deinit(private_display);
-       tdm_event_deinit(private_display);
+       tdm_event_loop_deinit(private_display);
 
        _tdm_display_destroy_private_display(private_display);
        _tdm_display_unload_module(private_display);
 
+#ifdef INIT_BUFMGR
+       if (private_display->bufmgr)
+               tbm_bufmgr_deinit(private_display->bufmgr);
+#endif
+
        tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
 
        _pthread_mutex_unlock(&private_display->lock);
@@ -894,5 +1026,21 @@ tdm_display_deinit(tdm_display *dpy)
        tdm_debug_buffer = 0;
 
        _pthread_mutex_unlock(&gLock);
+
+       TDM_INFO("done");
+}
+
+INTERN int
+tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin)
+{
+       tdm_backend_module *module = private_display->module_data;
+
+       if (TDM_BACKEND_GET_ABI_MAJOR(module->abi_version) < abimaj)
+               return 0;
+
+       if (TDM_BACKEND_GET_ABI_MINOR(module->abi_version) < abimin)
+               return 0;
+
+       return 1;
 }