use wl_event_loop to support the event handling system 28/65528/1
authorBoram Park <boram1288.park@samsung.com>
Wed, 30 Mar 2016 08:16:48 +0000 (17:16 +0900)
committerBoram Park <boram1288.park@samsung.com>
Mon, 11 Apr 2016 10:32:54 +0000 (19:32 +0900)
Conflicts:
src/tdm_private.h

Change-Id: Ie7be4057582a58d6c9db54edd39521e7bc7c4ab3

configure.ac
include/tdm_backend.h
include/tdm_types.h
packaging/libtdm.spec
src/Makefile.am
src/tdm.c
src/tdm_display.c
src/tdm_event.c [new file with mode: 0644]
src/tdm_private.h

index c4b1a40..358c2e4 100644 (file)
@@ -23,17 +23,17 @@ LT_INIT([disable-static])
 # Enable quiet compiles on automake 1.11.
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
+PKG_CHECK_MODULES(TDM, libtbm pthread-stubs libpng wayland-server)
+
 PKG_CHECK_MODULES(TTRACE,
                [ttrace],
                [have_ttrace="yes"], [have_ttrace="no"])
 if test "x$have_ttrace" = "xyes"; then
-    PKG_CHECK_MODULES(TDM, libtbm pthread-stubs libpng ttrace)
+    TDM_CFLAGS="$TDM_CFLAGS $TTRACE_CFLAGS"
+    TDM_LIBS="$TDM_LIBS $TTRACE_LIBS"
        AC_DEFINE(HAVE_TTRACE, 1, [ttrace available])
-else
-    PKG_CHECK_MODULES(TDM, libtbm pthread-stubs libpng)
 fi
 
-PKG_CHECK_MODULES(TDM, libtbm pthread-stubs libpng)
 AC_SUBST(TDM_CFLAGS)
 AC_SUBST(TDM_LIBS)
 
index f240d41..0fe68c8 100644 (file)
@@ -917,6 +917,24 @@ tdm_buffer_remove_destroy_handler(tbm_surface_h buffer,
                                   tdm_buffer_destroy_handler func, void *user_data);
 
 
+tdm_event_source*
+tdm_event_add_fd_handler(tdm_display *dpy, int fd, tdm_event_mask mask,
+                         tdm_event_fd_handler func, void *user_data,
+                         tdm_error *error);
+
+tdm_error
+tdm_event_source_fd_update(tdm_event_source *source, tdm_event_mask mask);
+
+tdm_event_source*
+tdm_event_add_timer_handler(tdm_display *dpy, tdm_event_timer_handler func,
+                            void *user_data, tdm_error *error);
+
+tdm_error
+tdm_event_source_timer_update(tdm_event_source *source, int ms_delay);
+
+void
+tdm_event_source_remove(tdm_event_source *source);
+
 #ifdef __cplusplus
 }
 #endif
index e31a96b..5236982 100755 (executable)
@@ -224,6 +224,14 @@ typedef enum {
        TDM_OUTPUT_MODE_FLAG_CLKDIV2    = (1 << 13),
 } tdm_output_mode_flag;
 
+typedef enum
+{
+       TDM_EVENT_READABLE = (1 << 0),
+       TDM_EVENT_WRITABLE = (1 << 1),
+       TDM_EVENT_HANGUP   = (1 << 2),
+       TDM_EVENT_ERROR    = (1 << 3),
+} tdm_event_mask;
+
 /**
  * @brief The output mode structure
  */
@@ -355,6 +363,20 @@ typedef void (*tdm_output_commit_handler)(tdm_output *output, unsigned int seque
                                           unsigned int tv_sec, unsigned int tv_usec,
                                           void *user_data);
 
+/**
+ * @brief The tdm event source
+ */
+typedef void tdm_event_source;
+
+/**
+ * @brief The fd source handler
+ */
+typedef tdm_error (*tdm_event_fd_handler)(int fd, tdm_event_mask mask, void *user_data);
+
+/**
+ * @brief The timer source handler
+ */
+typedef tdm_error (*tdm_event_timer_handler)(void *user_data);
 
 #ifdef __cplusplus
 }
index b06652b..0673f9c 100644 (file)
@@ -10,6 +10,7 @@ BuildRequires:  pkgconfig(pthread-stubs)
 BuildRequires:  pkgconfig(libtbm)
 BuildRequires:  pkgconfig(libpng)
 BuildRequires:  pkgconfig(ttrace)
+BuildRequires:  pkgconfig(wayland-server)
 
 %description
 Common user library of Tizen Display Manager : libtdm front-end library
index f445f27..2f994ba 100644 (file)
@@ -11,6 +11,7 @@ libtdm_la_LIBADD = $(TDM_LIBS) -ldl -lpthread
 
 libtdm_la_SOURCES = \
        tdm_backend.c \
+       tdm_event.c \
        tdm_helper.c \
        tdm_buffer.c \
        tdm_display.c \
index 58c781a..0023e7e 100644 (file)
--- a/src/tdm.c
+++ b/src/tdm.c
@@ -733,6 +733,10 @@ tdm_display_init(tdm_error *error)
                goto failed_mutex_init;
        }
 
+       ret = tdm_event_init(private_display);
+       if (ret != TDM_ERROR_NONE)
+               goto failed_load;
+
        ret = _tdm_display_load_module(private_display);
        if (ret != TDM_ERROR_NONE)
                goto failed_load;
@@ -743,6 +747,8 @@ tdm_display_init(tdm_error *error)
        if (ret != TDM_ERROR_NONE)
                goto failed_update;
 
+       tdm_event_create_main_source(private_display);
+
        private_display->init_count = 1;
 
        g_private_display = private_display;
@@ -789,6 +795,7 @@ tdm_display_deinit(tdm_display *dpy)
 
        _tdm_display_destroy_private_display(private_display);
        _tdm_display_unload_module(private_display);
+       tdm_event_deinit(private_display);
 
        tdm_helper_set_fd("TDM_DRM_MASTER_FD", -1);
 
index 8e3dbe3..f730f11 100644 (file)
@@ -300,21 +300,13 @@ tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error)
 EXTERN tdm_error
 tdm_display_get_fd(tdm_display *dpy, int *fd)
 {
-       tdm_func_display *func_display;
        DISPLAY_FUNC_ENTRY();
 
        TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        _pthread_mutex_lock(&private_display->lock);
 
-       func_display = &private_display->func_display;
-
-       if (!func_display->display_get_fd) {
-               pthread_mutex_unlock(&private_display->lock);
-               return TDM_ERROR_NONE;
-       }
-
-       ret = func_display->display_get_fd(private_display->bdata, fd);
+       *fd = tdm_event_get_fd(private_display);
 
        _pthread_mutex_unlock(&private_display->lock);
 
@@ -324,19 +316,11 @@ tdm_display_get_fd(tdm_display *dpy, int *fd)
 EXTERN tdm_error
 tdm_display_handle_events(tdm_display *dpy)
 {
-       tdm_func_display *func_display;
        DISPLAY_FUNC_ENTRY();
 
        _pthread_mutex_lock(&private_display->lock);
 
-       func_display = &private_display->func_display;
-
-       if (!func_display->display_handle_events) {
-               pthread_mutex_unlock(&private_display->lock);
-               return TDM_ERROR_NONE;
-       }
-
-       ret = func_display->display_handle_events(private_display->bdata);
+       ret = tdm_event_dispatch(private_display);
 
        _pthread_mutex_unlock(&private_display->lock);
 
diff --git a/src/tdm_event.c b/src/tdm_event.c
new file mode 100644 (file)
index 0000000..4c5f3a3
--- /dev/null
@@ -0,0 +1,336 @@
+/**************************************************************************
+
+libtdm
+
+Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: Eunchul Kim <chulspro.kim@samsung.com>,
+         JinYoung Jeon <jy0.jeon@samsung.com>,
+         Taeheon Kim <th908.kim@samsung.com>,
+         YoungJun Cho <yj44.cho@samsung.com>,
+         SooChan Lim <sc1.lim@samsung.com>,
+         Boram Park <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tdm.h"
+#include "tdm_private.h"
+#include "tdm_list.h"
+
+typedef struct _tdm_event_source_base
+{
+       struct wl_event_source *wl_source;
+} tdm_event_source_base;
+
+typedef struct _tdm_event_source_fd
+{
+       tdm_event_source_base base;
+       tdm_private_display *private_display;
+       tdm_event_fd_handler func;
+       void *user_data;
+} tdm_event_source_fd;
+
+typedef struct _tdm_event_source_timer
+{
+       tdm_event_source_base base;
+       tdm_private_display *private_display;
+       tdm_event_timer_handler func;
+       void *user_data;
+} tdm_event_source_timer;
+
+static tdm_error
+_tdm_event_main_fd_handler(int fd, tdm_event_mask mask, void *user_data)
+{
+       tdm_private_display *private_display = (tdm_private_display*)user_data;
+       tdm_func_display *func_display;
+
+       TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
+
+       func_display = &private_display->func_display;
+       if (!func_display->display_handle_events)
+               return TDM_ERROR_NONE;
+
+       return func_display->display_handle_events(private_display->bdata);
+}
+
+INTERN tdm_error
+tdm_event_init(tdm_private_display *private_display)
+{
+       if (private_display->event_loop)
+               return TDM_ERROR_NONE;
+
+       private_display->event_loop = wl_event_loop_create();
+       if (!private_display->event_loop) {
+               TDM_ERR("creating a event loop failed");
+               return TDM_ERROR_OUT_OF_MEMORY;
+       }
+
+       TDM_INFO("event_loop fd(%d)",
+                wl_event_loop_get_fd(private_display->event_loop));
+
+       return TDM_ERROR_NONE;
+}
+
+INTERN void
+tdm_event_deinit(tdm_private_display *private_display)
+{
+       if (private_display->main_source) {
+               tdm_event_source_remove(private_display->main_source);
+               private_display->main_source = NULL;
+       }
+
+       if (private_display->event_loop) {
+               wl_event_loop_destroy(private_display->event_loop);
+               private_display->event_loop = NULL;
+       }
+}
+
+INTERN void
+tdm_event_create_main_source(tdm_private_display *private_display)
+{
+       tdm_func_display *func_display;
+       tdm_error ret;
+       int fd = -1;
+
+       func_display = &private_display->func_display;
+       if (!func_display->display_get_fd) {
+               TDM_INFO("TDM backend module won't offer a display fd");
+               return;
+       }
+
+       ret = func_display->display_get_fd(private_display->bdata, &fd);
+       if (fd < 0) {
+               TDM_WRN("TDM backend module returns fd(%d)", fd);
+               return;
+       }
+
+       if (!func_display->display_handle_events) {
+               TDM_ERR("no display_handle_events function");
+               return;
+       }
+
+       private_display->main_source =
+               tdm_event_add_fd_handler(private_display, fd, TDM_EVENT_READABLE,
+                                        _tdm_event_main_fd_handler, private_display,
+                                        &ret);
+       if (!private_display->main_source) {
+               TDM_ERR("no main event source");
+               return;
+       }
+
+       TDM_INFO("main event source created");
+}
+
+INTERN int
+tdm_event_get_fd(tdm_private_display *private_display)
+{
+       if (!private_display->event_loop)
+               return -1;
+
+       return wl_event_loop_get_fd(private_display->event_loop);
+}
+
+INTERN tdm_error
+tdm_event_dispatch(tdm_private_display *private_display)
+{
+       if (!private_display->event_loop)
+               return TDM_ERROR_NONE;
+
+       if (wl_event_loop_dispatch(private_display->event_loop, 0) < 0) {
+               TDM_ERR("dispatch failed");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static int
+_tdm_event_loop_fd_func(int fd, uint32_t wl_mask, void *data)
+{
+       tdm_event_source_fd *fd_source = (tdm_event_source_fd*)data;
+       tdm_event_mask mask = 0;
+
+       TDM_RETURN_VAL_IF_FAIL(fd_source, 1);
+       TDM_RETURN_VAL_IF_FAIL(fd_source->func, 1);
+
+       if (wl_mask & WL_EVENT_READABLE)
+               mask |= TDM_EVENT_READABLE;
+       if (wl_mask & WL_EVENT_WRITABLE)
+               mask |= TDM_EVENT_WRITABLE;
+       if (wl_mask & WL_EVENT_HANGUP)
+               mask |= TDM_EVENT_HANGUP;
+       if (wl_mask & WL_EVENT_ERROR)
+               mask |= TDM_EVENT_ERROR;
+
+       fd_source->func(fd, mask, fd_source->user_data);
+
+       return 1;
+}
+
+EXTERN tdm_event_source*
+tdm_event_add_fd_handler(tdm_display *dpy, int fd, tdm_event_mask mask,
+                         tdm_event_fd_handler func, void *user_data,
+                         tdm_error *error)
+{
+       tdm_private_display *private_display;
+       tdm_event_source_fd *fd_source;
+       uint32_t wl_mask = 0;
+       tdm_error ret;
+
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd >= 0, TDM_ERROR_INVALID_PARAMETER, NULL);
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
+
+       private_display = (tdm_private_display*)dpy;
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_display->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
+
+       fd_source = calloc(1, sizeof(tdm_event_source_fd));
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(fd_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
+
+       if (mask & TDM_EVENT_READABLE)
+               wl_mask |= WL_EVENT_READABLE;
+       if (mask & TDM_EVENT_WRITABLE)
+               wl_mask |= WL_EVENT_WRITABLE;
+
+       fd_source->base.wl_source =
+               wl_event_loop_add_fd(private_display->event_loop,
+                                    fd, wl_mask, _tdm_event_loop_fd_func, fd_source);
+       if (!fd_source->base.wl_source) {
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               free(fd_source);
+               return NULL;
+       }
+
+       fd_source->private_display = private_display;
+       fd_source->func = func;
+       fd_source->user_data = user_data;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return (tdm_event_source*)fd_source;
+}
+
+EXTERN tdm_error
+tdm_event_source_fd_update(tdm_event_source *source, tdm_event_mask mask)
+{
+       tdm_event_source_fd *fd_source = source;
+       uint32_t wl_mask = 0;
+
+       TDM_RETURN_VAL_IF_FAIL(fd_source, TDM_ERROR_INVALID_PARAMETER);
+
+       if (mask & TDM_EVENT_READABLE)
+               wl_mask |= WL_EVENT_READABLE;
+       if (mask & TDM_EVENT_WRITABLE)
+               wl_mask |= WL_EVENT_WRITABLE;
+
+       if (wl_event_source_fd_update(fd_source->base.wl_source, wl_mask) < 0) {
+               TDM_ERR("source update failed: %m");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+static int
+_tdm_event_loop_timer_func(void *data)
+{
+       tdm_event_source_timer *timer_source = (tdm_event_source_timer*)data;
+
+       TDM_RETURN_VAL_IF_FAIL(timer_source, 1);
+       TDM_RETURN_VAL_IF_FAIL(timer_source->func, 1);
+
+       timer_source->func(timer_source->user_data);
+
+       return 1;
+}
+
+EXTERN tdm_event_source*
+tdm_event_add_timer_handler(tdm_display *dpy, tdm_event_timer_handler func,
+                            void *user_data, tdm_error *error)
+{
+       tdm_private_display *private_display;
+       tdm_event_source_timer *timer_source;
+       tdm_error ret;
+
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(dpy, TDM_ERROR_INVALID_PARAMETER, NULL);
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(func, TDM_ERROR_INVALID_PARAMETER, NULL);
+
+       private_display = (tdm_private_display*)dpy;
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(private_display->event_loop, TDM_ERROR_INVALID_PARAMETER, NULL);
+
+       timer_source = calloc(1, sizeof(tdm_event_source_timer));
+       TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(timer_source, TDM_ERROR_OUT_OF_MEMORY, NULL);
+
+       timer_source->base.wl_source =
+               wl_event_loop_add_timer(private_display->event_loop,
+                                       _tdm_event_loop_timer_func, timer_source);
+       if (!timer_source->base.wl_source) {
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               free(timer_source);
+               return NULL;
+       }
+
+       timer_source->private_display = private_display;
+       timer_source->func = func;
+       timer_source->user_data = user_data;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return (tdm_event_source*)timer_source;
+}
+
+EXTERN tdm_error
+tdm_event_source_timer_update(tdm_event_source *source, int ms_delay)
+{
+       tdm_event_source_timer *timer_source = source;
+
+       TDM_RETURN_VAL_IF_FAIL(timer_source, TDM_ERROR_INVALID_PARAMETER);
+
+       if (wl_event_source_timer_update(timer_source->base.wl_source, ms_delay) < 0) {
+               TDM_ERR("source update failed: %m");
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+EXTERN void
+tdm_event_source_remove(tdm_event_source *source)
+{
+       tdm_event_source_base *base = (tdm_event_source_base*)source;
+
+       if (!base)
+               return;
+
+       wl_event_source_remove(base->wl_source);
+
+       free(source);
+}
index 15a2448..50396fe 100644 (file)
@@ -51,6 +51,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include <tbm_bufmgr.h>
 #include <tbm_surface_queue.h>
+#include <wayland-server-core.h>
 
 #include "tdm_backend.h"
 #include "tdm_log.h"
@@ -190,6 +191,10 @@ struct _tdm_private_display {
        struct list_head pp_list;
 
        void **outputs_ptr;
+
+       /* for event handling */
+       struct wl_event_loop *event_loop;
+       tdm_event_source *main_source;
 };
 
 struct _tdm_private_output {
@@ -311,6 +316,18 @@ tdm_buffer_list_get_first_entry(struct list_head *list);
 void
 tdm_buffer_list_dump(struct list_head *list);
 
+/* event functions for private */
+tdm_error
+tdm_event_init(tdm_private_display *private_display);
+void
+tdm_event_deinit(tdm_private_display *private_display);
+void
+tdm_event_create_main_source(tdm_private_display *private_display);
+int
+tdm_event_get_fd(tdm_private_display *private_display);
+tdm_error
+tdm_event_dispatch(tdm_private_display *private_display);
+
 #define _pthread_mutex_lock(l) \
     do {if (tdm_debug_mutex) TDM_INFO("mutex lock"); pthread_mutex_lock(l);} while (0)
 #define _pthread_mutex_unlock(l) \