*~
html/
latex/
+protocol/*.h
+protocol/*.c
-SUBDIRS = . include src
+SUBDIRS = . include protocol client src
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtdm.pc
--- /dev/null
+libtdm_clientincludedir = ${includedir}
+libtdm_clientinclude_HEADERS = \
+ tdm_client.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libtdm-client.pc
+
+libtdm_client_la_LTLIBRARIES = libtdm-client.la
+libtdm_client_ladir = $(libdir)
+libtdm_client_la_LDFLAGS = $(LDFLAGS)
+libtdm_client_la_LIBADD = $(TDM_CLIENT_LIBS)
+libtdm_client_la_CFLAGS = \
+ $(CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(TDM_CLIENT_CFLAGS) \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/protocol \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/client
+
+libtdm_client_la_SOURCES = \
+ $(top_srcdir)/protocol/tdm-protocol.c \
+ tdm_client.c
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libtdm-client
+Description: Tizen Display Manager Client Library
+Version: @PACKAGE_VERSION@
+Requires:
+Libs: -L${libdir} -ltdm-client
+Cflags: -I${includedir}
--- /dev/null
+/**************************************************************************
+
+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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tdm_client.h"
+#include "tdm_log.h"
+#include "tdm_macro.h"
+#include "tdm_list.h"
+#include "tdm-client-protocol.h"
+
+extern int tdm_debug;
+
+typedef struct _tdm_private_client {
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct wl_tdm *tdm;
+
+ struct list_head vblank_list;
+} tdm_private_client;
+
+typedef struct _tdm_client_vblank_info {
+ struct list_head link;
+ struct wl_tdm_vblank *vblank;
+ tdm_client_vblank_handler func;
+ void *user_data;
+} tdm_client_vblank_info;
+
+static void
+_tdm_client_cb_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface,
+ uint32_t version)
+{
+ tdm_private_client *private_client = data;
+
+ if (strcmp(interface, "wl_tdm") == 0) {
+ private_client->tdm =
+ wl_registry_bind(registry, name, &wl_tdm_interface, version);
+ TDM_RETURN_IF_FAIL(private_client->tdm != NULL);
+
+ wl_display_flush(private_client->display);
+ }
+}
+
+static void
+_tdm_client_cb_global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+}
+
+static const struct wl_registry_listener tdm_client_registry_listener =
+{
+ _tdm_client_cb_global,
+ _tdm_client_cb_global_remove
+};
+
+tdm_client*
+tdm_client_create(tdm_client_error *error)
+{
+ tdm_private_client *private_client;
+
+ private_client = calloc(1, sizeof *private_client);
+ if (!private_client) {
+ TDM_ERR("alloc failed");
+ if (error)
+ *error = TDM_CLIENT_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ private_client->display = wl_display_connect("tdm-socket");
+ TDM_GOTO_IF_FAIL(private_client->display != NULL, create_failed);
+
+ private_client->registry = wl_display_get_registry(private_client->display);
+ TDM_GOTO_IF_FAIL(private_client->registry != NULL, create_failed);
+
+ wl_registry_add_listener(private_client->registry,
+ &tdm_client_registry_listener, private_client);
+ wl_display_roundtrip(private_client->display);
+
+ /* check global objects */
+ TDM_GOTO_IF_FAIL(private_client->tdm != NULL, create_failed);
+
+ LIST_INITHEAD(&private_client->vblank_list);
+
+ if (error)
+ *error = TDM_CLIENT_ERROR_NONE;
+
+ return (tdm_client*)private_client;
+create_failed:
+ tdm_client_destroy((tdm_client*)private_client);
+ if (error)
+ *error = TDM_CLIENT_ERROR_OPERATION_FAILED;
+ return NULL;
+}
+
+void
+tdm_client_destroy(tdm_client *client)
+{
+ tdm_private_client *private_client = (tdm_private_client*)client;
+ tdm_client_vblank_info *v = NULL, *vv = NULL;
+
+ if (!private_client)
+ return;
+
+ LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_client->vblank_list, link) {
+ LIST_DEL(&v->link);
+ wl_tdm_vblank_destroy(v->vblank);
+ free(v);
+ }
+
+ if (private_client->tdm)
+ wl_tdm_destroy(private_client->tdm);
+ if (private_client->registry)
+ wl_registry_destroy(private_client->registry);
+ if (private_client->display)
+ wl_display_disconnect(private_client->display);
+
+ free(private_client);
+}
+
+tdm_client_error
+tdm_client_get_fd(tdm_client *client, int *fd)
+{
+ tdm_private_client *private_client;
+
+ TDM_RETURN_VAL_IF_FAIL(client != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(fd != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+
+ private_client = (tdm_private_client*)client;
+
+ *fd = wl_display_get_fd(private_client->display);
+ if (*fd < 0)
+ return TDM_CLIENT_ERROR_OPERATION_FAILED;
+
+ return TDM_CLIENT_ERROR_NONE;
+}
+
+tdm_client_error
+tdm_client_handle_events(tdm_client *client)
+{
+ tdm_private_client *private_client;
+
+ TDM_RETURN_VAL_IF_FAIL(client != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+
+ private_client = (tdm_private_client*)client;
+
+ wl_display_dispatch(private_client->display);
+
+ return TDM_CLIENT_ERROR_NONE;
+}
+
+static void
+_tdm_client_cb_vblank_done(void *data, struct wl_tdm_vblank *vblank,
+ uint32_t sequence, uint32_t tv_sec, uint32_t tv_usec)
+{
+ tdm_client_vblank_info *vblank_info = (tdm_client_vblank_info*)data;
+
+ TDM_RETURN_IF_FAIL(vblank_info != NULL);
+
+ if (vblank_info->func) {
+ vblank_info->func(sequence, tv_sec, tv_usec, vblank_info->user_data);
+ }
+
+ LIST_DEL(&vblank_info->link);
+ free(vblank_info);
+}
+
+static const struct wl_tdm_vblank_listener tdm_client_vblank_listener = {
+ _tdm_client_cb_vblank_done,
+};
+
+tdm_client_error
+tdm_client_wait_vblank(tdm_client *client, char *name, int interval, int sync,
+ tdm_client_vblank_handler func, void *user_data)
+{
+ tdm_private_client *private_client = (tdm_private_client*)client;
+ tdm_client_vblank_info *vblank_info;
+
+ TDM_RETURN_VAL_IF_FAIL(name != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(interval > 0, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_client != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_client->tdm != NULL, TDM_CLIENT_ERROR_INVALID_PARAMETER);
+
+ vblank_info = calloc(1, sizeof *vblank_info);
+ if (!vblank_info) {
+ TDM_ERR("alloc failed");
+ return TDM_CLIENT_ERROR_OUT_OF_MEMORY;
+ }
+
+ vblank_info->vblank = wl_tdm_wait_vblank(private_client->tdm, name, interval);
+ if (!vblank_info->vblank) {
+ TDM_ERR("couldn't create vblank resource");
+ free(vblank_info);
+ return TDM_CLIENT_ERROR_OUT_OF_MEMORY;
+ }
+
+ wl_tdm_vblank_add_listener(vblank_info->vblank,
+ &tdm_client_vblank_listener, vblank_info);
+
+ vblank_info->func = func;
+ vblank_info->user_data = user_data;
+ LIST_ADDTAIL(&vblank_info->link, &private_client->vblank_list);
+
+ if (sync)
+ wl_display_roundtrip(private_client->display);
+ else
+ wl_display_flush(private_client->display);
+
+ return TDM_CLIENT_ERROR_NONE;
+}
--- /dev/null
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifndef _TDM_CLIENT_H_
+#define _TDM_CLIENT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file tdm_client.h
+ * @brief The header file for a client user of TDM.
+ * @par Example
+ * @code
+ #include <tdm_client.h> //for a client user of TDM
+ * @endcode
+ */
+
+typedef enum
+{
+ TDM_CLIENT_ERROR_NONE = 0, /**< none */
+ TDM_CLIENT_ERROR_OPERATION_FAILED = -1, /**< operaion failed */
+ TDM_CLIENT_ERROR_INVALID_PARAMETER = -2, /**< wrong input parameter */
+ TDM_CLIENT_ERROR_PERMISSION_DENIED = -3, /**< access denied */
+ TDM_CLIENT_ERROR_OUT_OF_MEMORY = -4, /**< no free memory */
+} tdm_client_error;
+
+typedef void *tdm_client;
+
+typedef void
+(*tdm_client_vblank_handler)(unsigned int sequence, unsigned int tv_sec,
+ unsigned int tv_usec, void *user_data);
+
+tdm_client*
+tdm_client_create(tdm_client_error *error);
+
+void
+tdm_client_destroy(tdm_client *client);
+
+tdm_client_error
+tdm_client_get_fd(tdm_client *client, int *fd);
+
+tdm_client_error
+tdm_client_handle_events(tdm_client *client);
+
+tdm_client_error
+tdm_client_wait_vblank(tdm_client *client, char *name, int interval, int sync,
+ tdm_client_vblank_handler func, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TDM_CLIENT_H_ */
# 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)
+AC_PATH_PROG([wayland_scanner], [wayland-scanner])
+if test x$wayland_scanner = x; then
+ AC_MSG_ERROR([wayland-scanner is needed to compile])
+fi
+
+PKG_CHECK_MODULES(WAYLAND_SCANNER, wayland-scanner >= 1.7.0)
+
+PKG_CHECK_MODULES(TDM, dlog libtbm pthread-stubs libpng wayland-server)
PKG_CHECK_MODULES(TTRACE,
[ttrace],
AC_SUBST(TDM_CFLAGS)
AC_SUBST(TDM_LIBS)
+PKG_CHECK_MODULES(TDM_CLIENT, dlog wayland-client)
+AC_SUBST(TDM_CLIENT_CFLAGS)
+AC_SUBST(TDM_CLIENT_LIBS)
+
# set the dir for the tbm module
DEFAULT_TDM_MODULE_PATH="${libdir}/tdm"
AC_ARG_WITH(tdm-module-path, AS_HELP_STRING([--with-tdm-module-path=PATH], [tdm module dir]),
Makefile
libtdm.pc
include/Makefile
+ protocol/Makefile
+ client/libtdm-client.pc
+ client/Makefile
src/Makefile])
echo ""
echo ""
echo "TDM_CFLAGS : $TDM_CFLAGS"
echo "TDM_LIBS : $TDM_LIBS"
+echo "TDM_CLIENT_CFLAGS : $TDM_CLIENT_CFLAGS"
+echo "TDM_CLIENT_LIBS : $TDM_CLIENT_LIBS"
echo "TDM_MODULE_PATH : $TDM_MODULE_PATH"
echo ""
&pos->member != (head); \
pos = container_of(pos->member.prev, pos, member))
+#define LIST_FIND_ITEM(item, head, type, member, found) \
+ do { \
+ type *pos; \
+ found = NULL; \
+ LIST_FOR_EACH_ENTRY(pos, head, member) \
+ if (pos == item) { found = item; break; } \
+ } while (0)
+
#endif /*_U_DOUBLE_LIST_H_*/
extern "C" {
#endif
+#include <unistd.h>
#include <time.h>
#include <sys/syscall.h>
%description devel
This supports frontend & backend library header and so
+%package client
+Summary: Client library for Tizen Display Manager
+Group: Development/Libraries
+
+%description client
+Tizen Display Manager Client Library
+
+%package client-devel
+Summary: Client library for Tizen Display Manager
+Group: Development/Libraries
+Requires: libtdm-client = %{version}
+
+%description client-devel
+Tizen Display Manager Client Library headers
+
%global TZ_SYS_RO_SHARE %{?TZ_SYS_RO_SHARE:%TZ_SYS_RO_SHARE}%{!?TZ_SYS_RO_SHARE:/usr/share}
%prep
cp -af COPYING %{buildroot}/%{TZ_SYS_RO_SHARE}/license/%{name}
%make_install
+%__mkdir_p %{buildroot}%{_unitdir}
+install -m 644 service/tdm-socket.service %{buildroot}%{_unitdir}
+install -m 644 service/tdm-socket.path %{buildroot}%{_unitdir}
+%__mkdir_p %{buildroot}%{_unitdir_user}
+install -m 644 service/tdm-socket-user.service %{buildroot}%{_unitdir_user}
+install -m 644 service/tdm-socket-user.path %{buildroot}%{_unitdir_user}
+
%remove_docs
+
+%pre
+%__mkdir_p %{_unitdir}/graphical.target.wants
+ln -sf ../tdm-socket.path %{_unitdir}/graphical.target.wants/
+%__mkdir_p %{_unitdir_user}/default.target.wants
+ln -sf ../tdm-socket-user.path %{_unitdir_user}/default.target.wants/
+
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
-
+rm -f %{_unitdir}/graphical.target.wants/tdm-socket.path
+rm -f %{_unitdir_user}/default.target.wants/tdm-socket-user.path
%files
%manifest %{name}.manifest
%defattr(-,root,root,-)
%{TZ_SYS_RO_SHARE}/license/%{name}
%{_libdir}/libtdm.so.*
+%{_unitdir}/tdm-socket.path
+%{_unitdir}/tdm-socket.service
+%{_unitdir_user}/tdm-socket-user.path
+%{_unitdir_user}/tdm-socket-user.service
%files devel
%manifest %{name}.manifest
%defattr(-,root,root,-)
-%{_includedir}/*
-%{_libdir}/pkgconfig/*
+%{_includedir}/tdm.h
+%{_includedir}/tdm_backend.h
+%{_includedir}/tdm_helper.h
+%{_includedir}/tdm_list.h
+%{_includedir}/tdm_log.h
+%{_includedir}/tdm_types.h
+%{_libdir}/pkgconfig/libtdm.pc
%{_libdir}/libtdm.so
+%files client
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{TZ_SYS_RO_SHARE}/license/%{name}
+%{_libdir}/libtdm-client.so.*
+
+%files client-devel
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_includedir}/tdm_client.h
+%{_libdir}/pkgconfig/libtdm-client.pc
+%{_libdir}/libtdm-client.so
+
%changelog
--- /dev/null
+### protocol.[ch]
+%-protocol.c : %.xml
+ $(wayland_scanner) code < $< > $@
+%-server-protocol.h : %.xml
+ $(wayland_scanner) server-header < $< > $@
+%-client-protocol.h : %.xml
+ $(wayland_scanner) client-header < $< > $@
+
+BUILT_SOURCES = \
+ tdm-server-protocol.h \
+ tdm-client-protocol.h \
+ tdm-protocol.c
+
+CLEANFILES = $(BUILT_SOURCES)
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<protocol name="wl_tdm">
+
+ <interface name="wl_tdm_vblank" version="1">
+
+ <event name="done">
+ <arg name="sequence" type="uint"/>
+ <arg name="tv_sec" type="uint"/>
+ <arg name="tv_usec" type="uint"/>
+ </event>
+
+ </interface>
+
+ <interface name="wl_tdm" version="1">
+
+ <enum name="error">
+ <entry name="invalid_name" value="0"/>
+ <entry name="operation_failed" value="1"/>
+ </enum>
+
+ <request name="wait_vblank">
+ <arg name="id" type="new_id" interface="wl_tdm_vblank"/>
+ <arg name="name" type="string"/>
+ <arg name="interval" type="int"/>
+ </request>
+
+ </interface>
+
+</protocol>
--- /dev/null
+[Unit]
+Description=Wait for tdm-socket
+
+[Path]
+PathExists=/run/tdm-socket
--- /dev/null
+[Unit]
+Description=Creating a link file for user to access tdm-socket
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/ln -sf /run/tdm-socket /run/user/%U/
--- /dev/null
+[Unit]
+Description=Wait for tdm-socket
+
+[Path]
+PathExists=/run/tdm-socket
--- /dev/null
+[Unit]
+Description= tdm-socket setup service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/chmod g+w /run/tdm-socket
+ExecStart=/usr/bin/chgrp display /run/tdm-socket
+ExecStart=/usr/bin/chsmack -a User /run/tdm-socket
+
+[Install]
+WantedBy=graphical.target
-AM_CFLAGS = \
- $(WARN_CFLAGS) \
- $(TDM_CFLAGS) \
- -I$(top_srcdir)/include \
- -I$(top_srcdir)/src
-
libtdm_la_LTLIBRARIES = libtdm.la
libtdm_ladir = $(libdir)
libtdm_la_LDFLAGS = -version-number 1:0:0 -no-undefined
libtdm_la_LIBADD = $(TDM_LIBS) -ldl -lpthread
+libtdm_la_CFLAGS = \
+ $(CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(TDM_CFLAGS) \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/protocol \
+ -I$(top_srcdir)/src
libtdm_la_SOURCES = \
+ $(top_srcdir)/protocol/tdm-protocol.c \
tdm_backend.c \
+ tdm_server.c \
tdm_event_loop.c \
tdm_thread.c \
tdm_helper.c \
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);
}
}
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;
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);
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)
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;
if (ret != TDM_ERROR_NONE)
goto failed_event;
- ret = tdm_thread_init(private_display);
- if (ret != TDM_ERROR_NONE)
- goto failed_thread;
-
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);
+ 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();
failed_update:
_tdm_display_unload_module(private_display);
failed_load:
- tdm_thread_deinit(private_display);
-failed_thread:
tdm_event_loop_deinit(private_display);
failed_event:
pthread_mutex_destroy(&private_display->lock);
_pthread_mutex_lock(&private_display->lock);
- tdm_thread_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);
int lock_after_cb_done = 0;
int ret;
- if (!tdm_thread_in_display_thread(private_display)) {
+ if (private_capture->owner_tid != syscall(SYS_gettid)) {
tdm_thread_cb_capture_done capture_done;
tdm_error ret;
capture_done.buffer = buffer;
capture_done.user_data = user_data;
- ret = tdm_thread_send_cb(private_display, &capture_done.base);
+ ret = tdm_thread_send_cb(private_display->private_loop, &capture_done.base);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return;
}
+ if (private_capture->owner_tid != syscall(SYS_gettid))
+ TDM_NEVER_GET_HERE();
+
if (tdm_debug_buffer)
TDM_INFO("capture(%p) done: %p", private_capture, buffer);
private_capture->private_output = private_output;
private_capture->private_layer = NULL;
private_capture->capture_backend = capture_backend;
+ private_capture->owner_tid = syscall(SYS_gettid);
LIST_INITHEAD(&private_capture->pending_buffer_list);
LIST_INITHEAD(&private_capture->buffer_list);
private_capture->private_output = private_output;
private_capture->private_layer = private_layer;
private_capture->capture_backend = capture_backend;
+ private_capture->owner_tid = syscall(SYS_gettid);
LIST_INITHEAD(&private_capture->pending_buffer_list);
LIST_INITHEAD(&private_capture->buffer_list);
_pthread_mutex_lock(&private_display->lock);
- if (private_display->private_thread)
- *fd = tdm_thread_get_fd(private_display);
+ if (private_display->private_loop->private_thread) {
+ _pthread_mutex_unlock(&private_display->lock);
+ *fd = tdm_thread_get_fd(private_display->private_loop);
+ _pthread_mutex_lock(&private_display->lock);
+ }
else
*fd = tdm_event_loop_get_fd(private_display);
_pthread_mutex_lock(&private_display->lock);
- if (private_display->private_thread)
- ret = tdm_thread_handle_cb(private_display);
+ if (private_display->private_loop->private_thread) {
+ _pthread_mutex_unlock(&private_display->lock);
+ ret = tdm_thread_handle_cb(private_display->private_loop);
+ _pthread_mutex_lock(&private_display->lock);
+ }
else
ret = tdm_event_loop_dispatch(private_display);
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;
+ int lock_after_cb_done = 0;
+ int ret;
+
+ TDM_RETURN_IF_FAIL(private_output);
+
+ private_display = private_output->private_display;
+
+ if (!tdm_thread_in_display_thread(private_display->private_loop,
+ syscall(SYS_gettid))) {
+ 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;
+
+ value.u32 = status;
+ tdm_output_call_change_handler_internal(private_output,
+ &private_output->change_handler_list_sub,
+ TDM_OUTPUT_CHANGE_CONNECTION,
+ value);
+
+ ret = tdm_thread_send_cb(private_display->private_loop, &output_status.base);
+ TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+ return;
+ }
+
+ ret = pthread_mutex_trylock(&private_display->lock);
+ if (ret == 0)
+ _pthread_mutex_unlock(&private_display->lock);
+ else if (ret == EBUSY) {
+ _pthread_mutex_unlock(&private_display->lock);
+ lock_after_cb_done = 1;
+ }
+
+ value.u32 = status;
+ tdm_output_call_change_handler_internal(private_output,
+ &private_output->change_handler_list_main,
+ TDM_OUTPUT_CHANGE_CONNECTION,
+ value);
+
+ if (lock_after_cb_done)
+ _pthread_mutex_lock(&private_display->lock);
+}
+
EXTERN tdm_error
tdm_output_add_change_handler(tdm_output *output,
tdm_output_change_handler func,
return TDM_ERROR_OUT_OF_MEMORY;
}
- LIST_ADD(&change_handler->link, &private_output->change_handler_list);
change_handler->private_output = private_output;
change_handler->func = func;
change_handler->user_data = user_data;
+ change_handler->owner_tid = syscall(SYS_gettid);
+
+ if (!tdm_thread_in_display_thread(private_display->private_loop,
+ change_handler->owner_tid))
+ LIST_ADD(&change_handler->link, &private_output->change_handler_list_sub);
+ else
+ LIST_ADD(&change_handler->link, &private_output->change_handler_list_main);
_pthread_mutex_unlock(&private_display->lock);
_pthread_mutex_lock(&private_display->lock);
- 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) {
+ if (h->func != func || h->user_data != user_data)
+ continue;
+
+ LIST_DEL(&h->link);
+ free(h);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return;
+ }
+
+ LIST_FOR_EACH_ENTRY_SAFE(h, hh, &private_output->change_handler_list_sub, link) {
if (h->func != func || h->user_data != user_data)
continue;
private_display = vblank_handler->private_output->private_display;
- if (!tdm_thread_in_display_thread(private_display)) {
+ if (vblank_handler->owner_tid != syscall(SYS_gettid)) {
tdm_thread_cb_output_vblank output_vblank;
tdm_error ret;
output_vblank.tv_usec = tv_usec;
output_vblank.user_data = user_data;
- ret = tdm_thread_send_cb(private_display, &output_vblank.base);
+ ret = tdm_thread_send_cb(private_display->private_loop, &output_vblank.base);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return;
}
+ if (vblank_handler->owner_tid != syscall(SYS_gettid))
+ TDM_NEVER_GET_HERE();
+
if (vblank_handler->func) {
- _pthread_mutex_unlock(&private_display->lock);
+ int lock_after_cb_done = 0;
+ int ret;
+
+ ret = pthread_mutex_trylock(&private_display->lock);
+ if (ret == 0)
+ _pthread_mutex_unlock(&private_display->lock);
+ else if (ret == EBUSY) {
+ _pthread_mutex_unlock(&private_display->lock);
+ lock_after_cb_done = 1;
+ }
+
vblank_handler->func(vblank_handler->private_output, sequence,
tv_sec, tv_usec, vblank_handler->user_data);
- _pthread_mutex_lock(&private_display->lock);
+
+ if (lock_after_cb_done)
+ _pthread_mutex_lock(&private_display->lock);
}
LIST_DEL(&vblank_handler->link);
tdm_private_display *private_display;
tdm_private_output *private_output;
tdm_private_layer *private_layer = NULL;
+ int lock_after_cb_done = 0;
+ int ret;
TDM_RETURN_IF_FAIL(commit_handler);
private_output = commit_handler->private_output;
private_display = private_output->private_display;
- if (!tdm_thread_in_display_thread(private_display)) {
+ if (commit_handler->owner_tid != syscall(SYS_gettid)) {
tdm_thread_cb_output_commit output_commit;
tdm_error ret;
output_commit.tv_usec = tv_usec;
output_commit.user_data = user_data;
- ret = tdm_thread_send_cb(private_display, &output_commit.base);
+ ret = tdm_thread_send_cb(private_display->private_loop, &output_commit.base);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return;
}
+ ret = pthread_mutex_trylock(&private_display->lock);
+ if (ret == 0)
+ _pthread_mutex_unlock(&private_display->lock);
+ else if (ret == EBUSY) {
+ _pthread_mutex_unlock(&private_display->lock);
+ lock_after_cb_done = 1;
+ }
+
LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
if (!private_layer->waiting_buffer)
continue;
if (private_layer->showing_buffer) {
- _pthread_mutex_unlock(&private_display->lock);
tdm_buffer_unref_backend(private_layer->showing_buffer);
- _pthread_mutex_lock(&private_display->lock);
if (private_layer->buffer_queue) {
- _pthread_mutex_unlock(&private_display->lock);
tbm_surface_queue_release(private_layer->buffer_queue,
private_layer->showing_buffer);
- _pthread_mutex_lock(&private_display->lock);
}
}
}
if (commit_handler->func) {
- _pthread_mutex_unlock(&private_display->lock);
commit_handler->func(private_output, sequence,
tv_sec, tv_usec, commit_handler->user_data);
- _pthread_mutex_lock(&private_display->lock);
}
+ if (lock_after_cb_done)
+ _pthread_mutex_lock(&private_display->lock);
+
LIST_DEL(&commit_handler->link);
free(commit_handler);
}
vblank_handler->private_output = private_output;
vblank_handler->func = func;
vblank_handler->user_data = user_data;
+ vblank_handler->owner_tid = syscall(SYS_gettid);
ret = func_output->output_wait_vblank(private_output->output_backend, interval,
sync, vblank_handler);
commit_handler->private_output = private_output;
commit_handler->func = func;
commit_handler->user_data = user_data;
+ commit_handler->owner_tid = syscall(SYS_gettid);
ret = func_output->output_commit(private_output->output_backend, sync,
commit_handler);
INTERN void
tdm_output_call_change_handler_internal(tdm_private_output *private_output,
+ struct list_head *change_handler_list,
tdm_output_change_type type,
tdm_value value)
{
- tdm_private_change_handler *change_handler;
tdm_private_display *private_display;
+ tdm_private_change_handler *change_handler;
TDM_RETURN_IF_FAIL(private_output);
private_display = private_output->private_display;
+ if (!tdm_thread_in_display_thread(private_display->private_loop,
+ syscall(SYS_gettid))) {
+ if (type & TDM_OUTPUT_CHANGE_CONNECTION)
+ TDM_INFO("output(%d) changed: %s (%d)",
+ private_output->pipe, status_str(value.u32), value.u32);
+ if (type & TDM_OUTPUT_CHANGE_DPMS)
+ TDM_INFO("output(%d) changed: dpms %s (%d)",
+ private_output->pipe, dpms_str(value.u32), value.u32);
+ }
- if (type & TDM_OUTPUT_CHANGE_CONNECTION)
- TDM_INFO("output(%d) changed: %s",
- private_output->pipe, status_str(value.u32));
- if (type & TDM_OUTPUT_CHANGE_DPMS)
- TDM_INFO("output(%d) changed: dpms %s",
- private_output->pipe, dpms_str(value.u32));
+ if (LIST_IS_EMPTY(change_handler_list))
+ return;
- _pthread_mutex_unlock(&private_display->lock);
+ LIST_FOR_EACH_ENTRY(change_handler, change_handler_list, link) {
+ if (change_handler->owner_tid != syscall(SYS_gettid))
+ TDM_NEVER_GET_HERE();
- LIST_FOR_EACH_ENTRY(change_handler, &private_output->change_handler_list, link) {
change_handler->func(private_output, type,
value, change_handler->user_data);
}
-
- _pthread_mutex_lock(&private_display->lock);
}
EXTERN tdm_error
#include <wayland-server-core.h>
-struct _tdm_private_loop {
- struct wl_display *wl_display;
- struct wl_event_loop *wl_loop;
-
- int backend_fd;
- tdm_event_loop_source *backend_source;
-};
-
typedef struct _tdm_event_loop_source_base
{
struct wl_event_source *wl_source;
tdm_private_display *private_display = (tdm_private_display*)user_data;
tdm_private_loop *private_loop;
tdm_func_display *func_display;
+ tdm_error ret;
TDM_RETURN_VAL_IF_FAIL(private_display != NULL, TDM_ERROR_OPERATION_FAILED);
TDM_RETURN_VAL_IF_FAIL(private_display->private_loop != NULL, TDM_ERROR_OPERATION_FAILED);
if (!func_display->display_handle_events)
return TDM_ERROR_NONE;
- return func_display->display_handle_events(private_display->bdata);
+ ret = func_display->display_handle_events(private_display->bdata);
+
+ return ret;
}
INTERN tdm_error
tdm_event_loop_init(tdm_private_display *private_display)
{
tdm_private_loop *private_loop;
+ tdm_error ret;
if (private_display->private_loop)
return TDM_ERROR_NONE;
TDM_ERR("no event loop");
wl_display_destroy(private_loop->wl_display);
free(private_loop);
- return TDM_ERROR_OUT_OF_MEMORY;
+ return TDM_ERROR_OPERATION_FAILED;
}
- TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
+ ret = tdm_server_init(private_loop);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("server init failed");
+ wl_display_destroy(private_loop->wl_display);
+ free(private_loop);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+ private_loop->dpy = private_display;
private_display->private_loop = private_loop;
+ ret = tdm_thread_init(private_loop);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("thread init failed");
+ tdm_server_deinit(private_loop);
+ wl_display_destroy(private_loop->wl_display);
+ free(private_loop);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ TDM_INFO("event loop fd(%d)", wl_event_loop_get_fd(private_loop->wl_loop));
+
return TDM_ERROR_NONE;
}
if (!private_display->private_loop)
return;
+ tdm_thread_deinit(private_display->private_loop);
+ tdm_server_deinit(private_display->private_loop);
+
if (private_display->private_loop->backend_source)
tdm_event_loop_source_remove(private_display->private_loop->backend_source);
return TDM_ERROR_NONE;
}
-INTERN tdm_error
-tdm_event_loop_add_socket(tdm_private_display *private_display, const char *name)
+
+INTERN void
+tdm_event_loop_flush(tdm_private_display *private_display)
{
tdm_private_loop *private_loop = private_display->private_loop;
- TDM_RETURN_VAL_IF_FAIL(private_loop->wl_display != NULL, TDM_ERROR_OPERATION_FAILED);
-
- if (wl_display_add_socket(private_loop->wl_display, name) < 0) {
- TDM_ERR("add socket(\"%s\") failed", name);
- return TDM_ERROR_OPERATION_FAILED;
- }
+ TDM_RETURN_IF_FAIL(private_loop->wl_display != NULL);
- return TDM_ERROR_NONE;
+ wl_display_flush_clients(private_loop->wl_display);
}
static int
static const char *dump_prefix[2] = {"png", "yuv"};
+INTERN int
+tdm_helper_unlock_in_cb(tdm_private_display *private_display)
+{
+ int ret = pthread_mutex_trylock(&private_display->lock);
+ int need_lock = 0;
+
+ if (ret == 0)
+ _pthread_mutex_unlock(&private_display->lock);
+ else if (ret == EBUSY) {
+ _pthread_mutex_unlock(&private_display->lock);
+ need_lock = 1;
+ }
+
+ return need_lock;
+}
+
+INTERN void
+tdm_helper_lock_in_cb(tdm_private_display *private_display, int need_lock)
+{
+ if (!need_lock)
+ return;
+
+ _pthread_mutex_lock(&private_display->lock);
+}
+
INTERN unsigned long
tdm_helper_get_time_in_millis(void)
{
--- /dev/null
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+#ifndef _TDM_MACRO_H_
+#define _TDM_MACRO_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef EXTERN
+#undef DEPRECATED
+#undef INTERN
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define EXTERN __attribute__ ((visibility("default")))
+#else
+#define EXTERN
+#endif
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define INTERN __attribute__ ((visibility("hidden")))
+#else
+#define INTERN
+#endif
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define DEPRECATED __attribute__ ((deprecated))
+#else
+#define DEPRECATED
+#endif
+
+/* check condition */
+#define TDM_RETURN_IF_FAIL(cond) {\
+ if (!(cond)) {\
+ TDM_ERR ("'%s' failed", #cond);\
+ return;\
+ }\
+}
+#define TDM_RETURN_VAL_IF_FAIL(cond, val) {\
+ if (!(cond)) {\
+ TDM_ERR ("'%s' failed", #cond);\
+ return val;\
+ }\
+}
+#define TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(cond, error_v, val) {\
+ if (!(cond)) {\
+ TDM_ERR ("'%s' failed", #cond);\
+ ret = error_v;\
+ if (error) *error = ret;\
+ return val;\
+ }\
+}
+
+#define TDM_WARNING_IF_FAIL(cond) {\
+ if (!(cond))\
+ TDM_ERR ("'%s' failed", #cond);\
+}
+#define TDM_GOTO_IF_FAIL(cond, dst) {\
+ if (!(cond)) {\
+ TDM_ERR ("'%s' failed", #cond);\
+ goto dst;\
+ }\
+}
+
+#define TDM_NEVER_GET_HERE() TDM_ERR("** NEVER GET HERE **")
+
+#define TDM_SNPRINTF(p, len, fmt, ARG...) \
+ do { \
+ if (p && len && *len > 0) \
+ { \
+ int s = snprintf(p, *len, fmt, ##ARG); \
+ p += s; \
+ *len -= s; \
+ } \
+ } while (0)
+
+#define C(b,m) (((b) >> (m)) & 0xFF)
+#define B(c,s) ((((unsigned int)(c)) & 0xff) << (s))
+#define FOURCC(a,b,c,d) (B(d,24) | B(c,16) | B(b,8) | B(a,0))
+#define FOURCC_STR(id) C(id,0), C(id,8), C(id,16), C(id,24)
+#define FOURCC_ID(str) FOURCC(((char*)str)[0],((char*)str)[1],((char*)str)[2],((char*)str)[3])
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TDM_MACRO_H_ */
int lock_after_cb_done = 0;
int ret;
- if (!tdm_thread_in_display_thread(private_display)) {
+ if (private_pp->owner_tid != syscall(SYS_gettid)) {
tdm_thread_cb_pp_done pp_done;
tdm_error ret;
pp_done.dst = dst;
pp_done.user_data = user_data;
- ret = tdm_thread_send_cb(private_display, &pp_done.base);
+ ret = tdm_thread_send_cb(private_display->private_loop, &pp_done.base);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return;
}
+ if (private_pp->owner_tid != syscall(SYS_gettid))
+ TDM_NEVER_GET_HERE();
+
if (tdm_debug_buffer)
TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
LIST_ADD(&private_pp->link, &private_display->pp_list);
private_pp->private_display = private_display;
private_pp->pp_backend = pp_backend;
+ private_pp->owner_tid = syscall(SYS_gettid);
LIST_INITHEAD(&private_pp->src_pending_buffer_list);
LIST_INITHEAD(&private_pp->dst_pending_buffer_list);
#include "tdm_backend.h"
#include "tdm_log.h"
#include "tdm_list.h"
+#include "tdm_macro.h"
#ifdef __cplusplus
extern "C" {
#endif
+//#define INIT_BUFMGR
+
/**
* @file tdm_private.h
* @brief The private header file for a frontend library
extern int tdm_debug_mutex;
extern int tdm_debug_thread;
-#undef EXTERN
-#undef DEPRECATED
-#undef INTERN
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-#define EXTERN __attribute__ ((visibility("default")))
-#else
-#define EXTERN
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-#define INTERN __attribute__ ((visibility("hidden")))
-#else
-#define INTERN
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-#define DEPRECATED __attribute__ ((deprecated))
-#else
-#define DEPRECATED
-#endif
-
-/* check condition */
-#define TDM_RETURN_IF_FAIL(cond) {\
- if (!(cond)) {\
- TDM_ERR ("'%s' failed", #cond);\
- return;\
- }\
-}
-#define TDM_RETURN_VAL_IF_FAIL(cond, val) {\
- if (!(cond)) {\
- TDM_ERR ("'%s' failed", #cond);\
- return val;\
- }\
-}
-#define TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(cond, error_v, val) {\
- if (!(cond)) {\
- TDM_ERR ("'%s' failed", #cond);\
- ret = error_v;\
- if (error) *error = ret;\
- return val;\
- }\
-}
-
-#define TDM_WARNING_IF_FAIL(cond) {\
- if (!(cond))\
- TDM_ERR ("'%s' failed", #cond);\
-}
-#define TDM_GOTO_IF_FAIL(cond, dst) {\
- if (!(cond)) {\
- TDM_ERR ("'%s' failed", #cond);\
- goto dst;\
- }\
-}
-
#ifdef HAVE_TTRACE
#include <ttrace.h>
#define TDM_TRACE_BEGIN(NAME) traceBegin(TTRACE_TAG_GRAPHICS, "TDM:"#NAME)
#define TDM_TRACE_END()
#endif
-#define TDM_NEVER_GET_HERE() TDM_ERR("** NEVER GET HERE **")
-
-#define TDM_SNPRINTF(p, len, fmt, ARG...) \
- do { \
- if (p && len && *len > 0) \
- { \
- int s = snprintf(p, *len, fmt, ##ARG); \
- p += s; \
- *len -= s; \
- } \
- } while (0)
-
-#define C(b,m) (((b) >> (m)) & 0xFF)
-#define B(c,s) ((((unsigned int)(c)) & 0xff) << (s))
-#define FOURCC(a,b,c,d) (B(d,24) | B(c,16) | B(b,8) | B(a,0))
-#define FOURCC_STR(id) C(id,0), C(id,8), C(id,16), C(id,24)
-#define FOURCC_ID(str) FOURCC(((char*)str)[0],((char*)str)[1],((char*)str)[2],((char*)str)[3])
-
typedef enum {
TDM_CAPTURE_TARGET_OUTPUT,
TDM_CAPTURE_TARGET_LAYER,
typedef struct _tdm_private_pp tdm_private_pp;
typedef struct _tdm_private_capture tdm_private_capture;
typedef struct _tdm_private_loop tdm_private_loop;
+typedef struct _tdm_private_server tdm_private_server;
typedef struct _tdm_private_thread tdm_private_thread;
typedef struct _tdm_private_vblank_handler tdm_private_vblank_handler;
typedef struct _tdm_private_commit_handler tdm_private_commit_handler;
tdm_backend_module *module_data;
tdm_backend_data *bdata;
+#ifdef INIT_BUFMGR
+ tbm_bufmgr bufmgr;
+#endif
+
/* backend function */
tdm_display_capability capabilities;
tdm_func_display func_display;
/* for event handling */
tdm_private_loop *private_loop;
-
- /* for own event thread */
- tdm_private_thread *private_thread;
};
struct _tdm_private_output {
struct list_head capture_list;
struct list_head vblank_handler_list;
struct list_head commit_handler_list;
- struct list_head change_handler_list;
+
+ /* seperate list for multi-thread*/
+ struct list_head change_handler_list_main;
+ struct list_head change_handler_list_sub;
void **layers_ptr;
};
struct list_head dst_pending_buffer_list;
struct list_head src_buffer_list;
struct list_head dst_buffer_list;
+
+ pid_t owner_tid;
};
struct _tdm_private_capture {
struct list_head pending_buffer_list;
struct list_head buffer_list;
+
+ pid_t owner_tid;
+};
+
+/* CAUTION:
+ * Note that this structure is not thread-safe. If there is no TDM thread, all
+ * TDM resources are protected by private_display's lock. If there is a TDM
+ * thread, this struct will be used only in a TDM thread. So, we don't need to
+ * protect this structure.
+ */
+struct _tdm_private_loop {
+ /* TDM uses wl_event_loop to handle various event sources including the TDM
+ * backend's fd.
+ */
+ struct wl_display *wl_display;
+ struct wl_event_loop *wl_loop;
+
+ int backend_fd;
+ tdm_event_loop_source *backend_source;
+
+ /* In event loop, all resources are accessed by this dpy.
+ * CAUTION:
+ * - DO NOT include other private structure in this structure because this
+ * struct is not thread-safe.
+ */
+ tdm_display *dpy;
+
+ /* for handling TDM client requests */
+ tdm_private_server *private_server;
+
+ /* To have a TDM event thread. If TDM_THREAD enviroment variable is not set
+ * private_thread is NULL.
+ */
+ tdm_private_thread *private_thread;
};
struct _tdm_private_vblank_handler {
tdm_private_output *private_output;
tdm_output_vblank_handler func;
void *user_data;
+
+ pid_t owner_tid;
};
struct _tdm_private_commit_handler {
tdm_private_output *private_output;
tdm_output_commit_handler func;
void *user_data;
+
+ pid_t owner_tid;
};
struct _tdm_private_change_handler {
tdm_private_output *private_output;
tdm_output_change_handler func;
void *user_data;
+
+ pid_t owner_tid;
};
typedef struct _tdm_buffer_info {
void
tdm_output_call_change_handler_internal(tdm_private_output *private_output,
+ struct list_head *change_handler_list,
tdm_output_change_type type,
tdm_value value);
tdm_event_loop_get_fd(tdm_private_display *private_display);
tdm_error
tdm_event_loop_dispatch(tdm_private_display *private_display);
-tdm_error
-tdm_event_loop_add_socket(tdm_private_display *private_display, const char *name);
-
+void
+tdm_event_loop_flush(tdm_private_display *private_display);
typedef enum {
TDM_THREAD_CB_NONE,
};
tdm_error
-tdm_thread_init(tdm_private_display *private_display);
+tdm_thread_init(tdm_private_loop *private_loop);
void
-tdm_thread_deinit(tdm_private_display *private_display);
+tdm_thread_deinit(tdm_private_loop *private_loop);
int
-tdm_thread_get_fd(tdm_private_display *private_display);
+tdm_thread_get_fd(tdm_private_loop *private_loop);
tdm_error
-tdm_thread_send_cb(tdm_private_display *private_display, tdm_thread_cb_base *base);
+tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base);
tdm_error
-tdm_thread_handle_cb(tdm_private_display *private_display);
+tdm_thread_handle_cb(tdm_private_loop *private_loop);
int
-tdm_thread_in_display_thread(tdm_private_display *private_display);
+tdm_thread_in_display_thread(tdm_private_loop *private_loop, pid_t tid);
+
+tdm_error
+tdm_server_init(tdm_private_loop *private_loop);
+void
+tdm_server_deinit(tdm_private_loop *private_loop);
unsigned long
tdm_helper_get_time_in_millis(void);
+int
+tdm_helper_unlock_in_cb(tdm_private_display *private_display);
+void
+tdm_helper_lock_in_cb(tdm_private_display *private_display, int need_lock);
#define _pthread_mutex_lock(l) \
do {if (tdm_debug_mutex) TDM_INFO("mutex lock"); pthread_mutex_lock(l);} while (0)
--- /dev/null
+/**************************************************************************
+
+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"
+#include "tdm-server-protocol.h"
+
+/* CAUTION:
+ * - tdm server doesn't care about multi-thread.
+ * - DO NOT use the TDM internal functions here.
+ */
+
+struct _tdm_private_server {
+ struct list_head vblank_list;
+};
+
+typedef struct _tdm_server_vblank_info {
+ struct list_head link;
+ struct wl_resource *resource;
+ tdm_private_server *private_server;
+} tdm_server_vblank_info;
+
+static void
+_tdm_server_cb_output_vblank(tdm_output *output, unsigned int sequence,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data)
+{
+ tdm_server_vblank_info *vblank_info = (tdm_server_vblank_info*)user_data;
+ tdm_server_vblank_info *found;
+
+ LIST_FIND_ITEM(vblank_info, &vblank_info->private_server->vblank_list,
+ tdm_server_vblank_info, link, found);
+ if (!found) {
+ TDM_DBG("vblank_info(%p) is destroyed", vblank_info);
+ return;
+ }
+
+ TDM_DBG("wl_tdm_vblank@%d done", wl_resource_get_id(vblank_info->resource));
+
+ wl_tdm_vblank_send_done(vblank_info->resource, sequence, tv_sec, tv_usec);
+ wl_resource_destroy(vblank_info->resource);
+}
+
+static void
+destroy_vblank_callback(struct wl_resource *resource)
+{
+ tdm_server_vblank_info *vblank_info = wl_resource_get_user_data(resource);
+ LIST_DEL(&vblank_info->link);
+ free(vblank_info);
+}
+
+static void
+_tdm_server_cb_wait_vblank(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id, const char *name, int32_t interval)
+{
+ tdm_private_loop *private_loop = wl_resource_get_user_data(resource);
+ tdm_private_server *private_server = private_loop->private_server;
+ tdm_server_vblank_info *vblank_info;
+ struct wl_resource *vblank_resource;
+ tdm_output *found = NULL;
+ int count = 0, i;
+ tdm_error ret;
+
+ TDM_DBG("The tdm client requests vblank");
+
+ tdm_display_get_output_count(private_loop->dpy, &count);
+
+ for (i = 0; i < count; i++) {
+ tdm_output *output= tdm_display_get_output(private_loop->dpy, i, NULL);
+ tdm_output_conn_status status;
+ const char *model = NULL;
+
+ ret = tdm_output_get_conn_status(output, &status);
+ if (ret || status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+ continue;
+
+ ret = tdm_output_get_model_info(output, NULL, &model, NULL);
+ if (ret || !model)
+ continue;
+
+ if (strncmp(model, name, TDM_NAME_LEN))
+ continue;
+
+ found = output;
+ break;
+ }
+
+ if (!found) {
+ wl_resource_post_error(resource, WL_TDM_ERROR_INVALID_NAME,
+ "There is no '%s' output", name);
+ TDM_ERR("There is no '%s' output", name);
+ return;
+ }
+
+ vblank_resource =
+ wl_resource_create(client, &wl_tdm_vblank_interface,
+ wl_resource_get_version(resource), id);
+ if (!vblank_resource) {
+ wl_resource_post_no_memory(resource);
+ TDM_ERR("wl_resource_create failed");
+ return;
+ }
+
+ vblank_info = calloc(1, sizeof *vblank_info);
+ if (!vblank_info) {
+ wl_resource_destroy(vblank_resource);
+ wl_resource_post_no_memory(resource);
+ TDM_ERR("alloc failed");
+ return;
+ }
+
+ TDM_DBG("wl_tdm_vblank@%d output(%s) interval(%d)", id, name, interval);
+
+ ret = tdm_output_wait_vblank(found, interval, 0,
+ _tdm_server_cb_output_vblank, vblank_info);
+ if (ret != TDM_ERROR_NONE) {
+ wl_resource_destroy(vblank_resource);
+ free(vblank_info);
+ wl_resource_post_error(resource, WL_TDM_ERROR_OPERATION_FAILED,
+ "couldn't wait vblank for %s", name);
+ TDM_ERR("couldn't wait vblank for %s", name);
+ return;
+ }
+
+ vblank_info->resource = vblank_resource;
+ vblank_info->private_server = private_server;
+
+ wl_resource_set_implementation(vblank_resource, NULL, vblank_info,
+ destroy_vblank_callback);
+
+ LIST_ADDTAIL(&vblank_info->link, &private_server->vblank_list);
+}
+
+static const struct wl_tdm_interface tdm_implementation = {
+ _tdm_server_cb_wait_vblank,
+};
+
+static void
+_tdm_server_bind(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id)
+{
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client, &wl_tdm_interface, version, id);
+ if (!resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ TDM_DBG("tdm server binding");
+
+ wl_resource_set_implementation(resource, &tdm_implementation, data, NULL);
+}
+
+INTERN tdm_error
+tdm_server_init(tdm_private_loop *private_loop)
+{
+ tdm_private_server *private_server;
+
+ if (private_loop->private_server)
+ return TDM_ERROR_NONE;
+
+ TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_OPERATION_FAILED);
+ TDM_RETURN_VAL_IF_FAIL(private_loop->wl_display, TDM_ERROR_OPERATION_FAILED);
+
+ if(wl_display_add_socket(private_loop->wl_display, "tdm-socket")) {
+ TDM_ERR("createing a tdm-socket failed");
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ private_server = calloc(1, sizeof *private_server);
+ if (!private_server) {
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ LIST_INITHEAD(&private_server->vblank_list);
+
+ if (!wl_global_create(private_loop->wl_display, &wl_tdm_interface, 1,
+ private_loop, _tdm_server_bind)) {
+ TDM_ERR("creating a global resource failed");
+ free(private_server);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ private_loop->private_server = private_server;
+
+ return TDM_ERROR_NONE;
+}
+
+INTERN void
+tdm_server_deinit(tdm_private_loop *private_loop)
+{
+ tdm_server_vblank_info *v = NULL, *vv = NULL;
+ tdm_private_server *private_server;
+
+ if (!private_loop->private_server)
+ return;
+
+ private_server = private_loop->private_server;
+
+ LIST_FOR_EACH_ENTRY_SAFE(v, vv, &private_server->vblank_list, link) {
+ wl_resource_destroy(v->resource);
+ }
+
+ free(private_server);
+ private_loop->private_server = NULL;
+}
#include "tdm_list.h"
struct _tdm_private_thread {
+ tdm_private_loop *private_loop;
+
pthread_t event_thread;
- pthread_mutex_t event_mutex;
pid_t display_tid;
pid_t thread_tid;
static void*
_tdm_thread_main(void *data)
{
- tdm_private_display *private_display = (tdm_private_display*)data;
- tdm_private_thread *private_thread;
+ tdm_private_thread *private_thread = (tdm_private_thread*)data;
+ tdm_private_loop *private_loop = private_thread->private_loop;
int fd;
struct pollfd fds;
int ret;
- _pthread_mutex_lock(&private_display->lock);
-
- private_thread = private_display->private_thread;
+ /* Not lock/unlock for the private_thread and private_loop structure
+ * because they won't be destroyed as long as tdm thread is running.
+ * When they're destroyed, we have already exit the tdm thread.
+ */
private_thread->thread_tid = syscall(SYS_gettid);
TDM_INFO("display_tid:%d, thread_tid: %d",
private_thread->display_tid, private_thread->thread_tid);
- fd = tdm_event_loop_get_fd(private_display);
+ fd = tdm_event_loop_get_fd(private_loop->dpy);
if (fd < 0) {
TDM_ERR("couldn't get fd");
goto exit_thread;
fds.fd = fd;
fds.revents = 0;
- _pthread_mutex_unlock(&private_display->lock);
-
while (1) {
+ if (tdm_debug_thread)
+ TDM_INFO("server flush");
+ tdm_event_loop_flush(private_loop->dpy);
if (tdm_debug_thread)
TDM_INFO("fd(%d) polling in", fd);
if (tdm_debug_thread)
TDM_INFO("thread got events");
- _pthread_mutex_lock(&private_display->lock);
-
- if (tdm_event_loop_dispatch(private_display) < 0)
+ if (tdm_event_loop_dispatch(private_loop->dpy) < 0)
TDM_ERR("dispatch error");
-
- _pthread_mutex_unlock(&private_display->lock);
}
exit_thread:
pthread_exit(NULL);
}
+/* NOTE: tdm thread doesn't care about multi-thread. */
INTERN tdm_error
-tdm_thread_init(tdm_private_display *private_display)
+tdm_thread_init(tdm_private_loop *private_loop)
{
+ tdm_private_display *private_display;
tdm_private_thread *private_thread;
const char *thread;
- if (private_display->private_thread)
+ TDM_RETURN_VAL_IF_FAIL(private_loop->dpy, TDM_ERROR_OPERATION_FAILED);
+
+ private_display = private_loop->dpy;
+ TDM_RETURN_VAL_IF_FAIL(private_display->private_loop, TDM_ERROR_OPERATION_FAILED);
+
+ if (private_loop->private_thread)
return TDM_ERROR_NONE;
/* enable as default */
return TDM_ERROR_OPERATION_FAILED;
}
+ private_thread->private_loop = private_loop;
+ private_loop->private_thread = private_thread;
+
private_thread->display_tid = syscall(SYS_gettid);
- pthread_mutex_init(&private_thread->event_mutex, NULL);
pthread_create(&private_thread->event_thread, NULL, _tdm_thread_main,
- private_display);
-
- private_display->private_thread = private_thread;
+ private_thread);
TDM_INFO("using a TDM event thread. pipe(%d,%d)",
private_thread->pipe[0], private_thread->pipe[1]);
}
INTERN void
-tdm_thread_deinit(tdm_private_display *private_display)
+tdm_thread_deinit(tdm_private_loop *private_loop)
{
- if (!private_display->private_thread)
+ if (!private_loop->private_thread)
return;
- pthread_cancel(private_display->private_thread->event_thread);
- pthread_join(private_display->private_thread->event_thread, NULL);
- pthread_mutex_destroy(&private_display->private_thread->event_mutex);
+ pthread_cancel(private_loop->private_thread->event_thread);
+ pthread_join(private_loop->private_thread->event_thread, NULL);
- if (private_display->private_thread->pipe[0] >= 0)
- close(private_display->private_thread->pipe[0]);
- if (private_display->private_thread->pipe[1] >= 0)
- close(private_display->private_thread->pipe[1]);
+ if (private_loop->private_thread->pipe[0] >= 0)
+ close(private_loop->private_thread->pipe[0]);
+ if (private_loop->private_thread->pipe[1] >= 0)
+ close(private_loop->private_thread->pipe[1]);
- free(private_display->private_thread);
- private_display->private_thread = NULL;
+ free(private_loop->private_thread);
+ private_loop->private_thread = NULL;
TDM_INFO("Finish a TDM event thread");
}
INTERN int
-tdm_thread_get_fd(tdm_private_display *private_display)
+tdm_thread_get_fd(tdm_private_loop *private_loop)
{
tdm_private_thread *private_thread;
- TDM_RETURN_VAL_IF_FAIL(private_display, -1);
- TDM_RETURN_VAL_IF_FAIL(private_display->private_thread, -1);
+ TDM_RETURN_VAL_IF_FAIL(private_loop, -1);
+ TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, -1);
- private_thread = private_display->private_thread;
+ private_thread = private_loop->private_thread;
return private_thread->pipe[0];
}
INTERN tdm_error
-tdm_thread_send_cb(tdm_private_display *private_display, tdm_thread_cb_base *base)
+tdm_thread_send_cb(tdm_private_loop *private_loop, tdm_thread_cb_base *base)
{
tdm_private_thread *private_thread;
ssize_t len;
TDM_RETURN_VAL_IF_FAIL(base, TDM_ERROR_INVALID_PARAMETER);
- TDM_RETURN_VAL_IF_FAIL(private_display, TDM_ERROR_INVALID_PARAMETER);
- TDM_RETURN_VAL_IF_FAIL(private_display->private_thread, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, TDM_ERROR_INVALID_PARAMETER);
- private_thread = private_display->private_thread;
+ private_thread = private_loop->private_thread;
if (tdm_debug_thread)
TDM_INFO("fd(%d) type(%d), length(%d)",
}
INTERN tdm_error
-tdm_thread_handle_cb(tdm_private_display *private_display)
+tdm_thread_handle_cb(tdm_private_loop *private_loop)
{
tdm_private_thread *private_thread;
tdm_thread_cb_base *base;
char buffer[1024];
int len, i;
- TDM_RETURN_VAL_IF_FAIL(private_display, TDM_ERROR_INVALID_PARAMETER);
- TDM_RETURN_VAL_IF_FAIL(private_display->private_thread, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_loop, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(private_loop->private_thread, TDM_ERROR_INVALID_PARAMETER);
- private_thread = private_display->private_thread;
+ private_thread = private_loop->private_thread;
len = read(private_thread->pipe[0], buffer, sizeof buffer);
{
tdm_thread_cb_output_commit *output_commit = (tdm_thread_cb_output_commit*)base;
tdm_output *output_backend =
- tdm_display_find_output_stamp(private_display, output_commit->output_stamp);
+ tdm_display_find_output_stamp(private_loop->dpy, output_commit->output_stamp);
if (!output_backend) {
TDM_WRN("no output(%ld)", output_commit->output_stamp);
break;
{
tdm_thread_cb_output_vblank *output_vblank = (tdm_thread_cb_output_vblank*)base;
tdm_output *output_backend =
- tdm_display_find_output_stamp(private_display, output_vblank->output_stamp);
+ tdm_display_find_output_stamp(private_loop->dpy, output_vblank->output_stamp);
if (!output_backend) {
TDM_WRN("no output(%ld)", output_vblank->output_stamp);
break;
{
tdm_thread_cb_output_status *output_status = (tdm_thread_cb_output_status*)base;
tdm_output *output_backend =
- tdm_display_find_output_stamp(private_display, output_status->output_stamp);
+ tdm_display_find_output_stamp(private_loop->dpy, output_status->output_stamp);
if (!output_backend) {
TDM_WRN("no output(%ld)", output_status->output_stamp);
break;
{
tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done*)base;
tdm_pp *pp_backend =
- tdm_pp_find_stamp(private_display, pp_done->pp_stamp);
+ tdm_pp_find_stamp(private_loop->dpy, pp_done->pp_stamp);
if (!pp_backend) {
TDM_WRN("no pp(%ld)", pp_done->pp_stamp);
break;
{
tdm_thread_cb_capture_done *capture_done = (tdm_thread_cb_capture_done*)base;
tdm_capture *capture_backend =
- tdm_capture_find_stamp(private_display, capture_done->capture_stamp);
+ tdm_capture_find_stamp(private_loop->dpy, capture_done->capture_stamp);
if (!capture_backend) {
TDM_WRN("no capture(%ld)", capture_done->capture_stamp);
break;
i += base->length;
}
+ tdm_event_loop_flush(private_loop->dpy);
+
return TDM_ERROR_NONE;
}
INTERN int
-tdm_thread_in_display_thread(tdm_private_display *private_display)
+tdm_thread_in_display_thread(tdm_private_loop *private_loop, pid_t tid)
{
tdm_private_thread *private_thread;
- TDM_RETURN_VAL_IF_FAIL(private_display, 1);
+ TDM_RETURN_VAL_IF_FAIL(private_loop, 1);
- if (!private_display->private_thread)
+ if (!private_loop->private_thread)
return 1;
- private_thread = private_display->private_thread;
+ private_thread = private_loop->private_thread;
- return (private_thread->display_tid == syscall(SYS_gettid)) ? 1 : 0;
+ return (private_thread->display_tid == tid) ? 1 : 0;
}