set tdm output list's first element to main
[platform/core/uifw/libtdm.git] / src / tdm.c
index 58c781a..1d52152 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)
@@ -70,6 +73,20 @@ _tdm_display_find_private_output(tdm_private_display *private_display,
        return NULL;
 }
 
+INTERN tdm_private_output *
+tdm_display_find_output_stamp(tdm_private_display *private_display,
+                              unsigned long stamp)
+{
+       tdm_private_output *private_output = NULL;
+
+       LIST_FOR_EACH_ENTRY(private_output, &private_display->output_list, link) {
+               if (private_output->stamp == stamp)
+                       return private_output;
+       }
+
+       return NULL;
+}
+
 static void
 _tdm_display_destroy_caps_pp(tdm_caps_pp *caps_pp)
 {
@@ -122,6 +139,7 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
        tdm_private_capture *c = NULL, *cc = NULL;
        tdm_private_vblank_handler *v = NULL, *vv = NULL;
        tdm_private_commit_handler *m = NULL, *mm = NULL;
+       tdm_private_change_handler *h = NULL, *hh = NULL;
 
        LIST_DEL(&private_output->link);
 
@@ -137,6 +155,16 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
                free(m);
        }
 
+       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);
+       }
+
        LIST_FOR_EACH_ENTRY_SAFE(c, cc, &private_output->capture_list, link)
        tdm_capture_destroy_internal(c);
 
@@ -145,6 +173,7 @@ _tdm_display_destroy_private_output(tdm_private_output *private_output)
 
        _tdm_display_destroy_caps_output(&private_output->caps);
 
+       private_output->stamp = 0;
        free(private_output);
 }
 
@@ -278,10 +307,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;
 
@@ -296,6 +326,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);
@@ -372,8 +406,14 @@ _tdm_display_update_output(tdm_private_display *private_display,
                private_output = calloc(1, sizeof(tdm_private_output));
                TDM_RETURN_VAL_IF_FAIL(private_output != NULL, TDM_ERROR_OUT_OF_MEMORY);
 
-               LIST_ADD(&private_output->link, &private_display->output_list);
+               private_output->stamp = tdm_helper_get_time_in_millis();
+               while (tdm_display_find_output_stamp(private_display, private_output->stamp))
+                       private_output->stamp++;
+
+               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;
 
@@ -381,10 +421,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_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;
@@ -408,17 +456,146 @@ 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, index_lvds, index_hdmia, index_hdmib;
+       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;
 
        LIST_INITHEAD(&private_display->output_list);
        LIST_INITHEAD(&private_display->pp_list);
+       LIST_INITHEAD(&private_display->capture_list);
 
        if (!only_display) {
                ret = _tdm_display_update_caps_pp(private_display, &private_display->caps_pp);
@@ -431,9 +608,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++) {
@@ -475,6 +651,7 @@ tdm_display_update(tdm_display *dpy)
 
 int tdm_debug;
 int tdm_debug_buffer;
+int tdm_debug_thread;
 int tdm_debug_mutex;
 
 static tdm_private_display *g_private_display;
@@ -716,6 +893,10 @@ tdm_display_init(tdm_error *error)
        if (debug && (strstr(debug, "1")))
                tdm_debug_buffer = 1;
 
+       debug = getenv("TDM_DEBUG_THREAD");
+       if (debug && (strstr(debug, "1")))
+               tdm_debug_thread = 1;
+
        debug = getenv("TDM_DEBUG_MUTEX");
        if (debug && (strstr(debug, "1")))
                tdm_debug_mutex = 1;
@@ -733,16 +914,38 @@ tdm_display_init(tdm_error *error)
                goto failed_mutex_init;
        }
 
+       _pthread_mutex_lock(&private_display->lock);
+
+       ret = tdm_event_loop_init(private_display);
+       if (ret != TDM_ERROR_NONE)
+               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_loop_create_backend_source(private_display);
+
        private_display->init_count = 1;
 
        g_private_display = private_display;
@@ -750,6 +953,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;
@@ -757,6 +961,9 @@ tdm_display_init(tdm_error *error)
 failed_update:
        _tdm_display_unload_module(private_display);
 failed_load:
+       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);
@@ -787,9 +994,16 @@ tdm_display_deinit(tdm_display *dpy)
 
        _pthread_mutex_lock(&private_display->lock);
 
+       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);
@@ -801,5 +1015,7 @@ tdm_display_deinit(tdm_display *dpy)
        tdm_debug_buffer = 0;
 
        _pthread_mutex_unlock(&gLock);
+
+       TDM_INFO("done");
 }