#define CLIENT_QUEUE_SIZE 3
-typedef struct _twe_wl_disp_source twe_wl_disp_source;
-typedef struct _twe_wl_surf_source twe_wl_surf_source;
-typedef struct _twe_wl_buffer_info twe_wl_buffer_info;
-typedef struct _twe_tdm_source twe_tdm_source;
+typedef struct _twe_wl_disp_source twe_wl_disp_source;
+typedef struct _twe_wl_surf_source twe_wl_surf_source;
+typedef struct _twe_wl_buffer_info twe_wl_buffer_info;
+typedef struct _twe_tdm_source twe_tdm_source;
+typedef struct _twe_wl_disp_del_source twe_wl_disp_del_source;
struct _twe_thread_context {
int ref_cnt;
struct wayland_tbm_client *wl_tbm_client;
struct tizen_surface_shm *tss; /* used for surface buffer_flush */
tpl_bool_t prepared;
+ twe_wl_disp_del_source *disp_del_source;
twe_thread *thread;
tpl_object_t obj;
/* TODO : surface list */
};
+struct _twe_wl_disp_del_source {
+ GSource gsource;
+ gpointer tag;
+ int event_fd;
+ twe_wl_disp_source* disp_source;
+};
+
struct _twe_wl_surf_source {
GSource gsource;
gpointer tag;
twe_wl_disp_source *disp_source = (twe_wl_disp_source *)source;
TPL_OBJECT_LOCK(&disp_source->obj);
+
/* If disp_source is in prepared state, cancel it */
- if (disp_source->prepared)
+ if (disp_source->prepared) {
wl_display_cancel_read(disp_source->disp);
+ disp_source->prepared = TPL_FALSE;
+ }
if (wl_display_dispatch_queue_pending(disp_source->disp,
disp_source->ev_queue) == -1) {
}
}
+static void
+_twe_thread_wl_disp_del(twe_wl_disp_source *disp_source)
+{
+ if (g_source_is_destroyed(&disp_source->gsource)) {
+ TPL_ERR("disp_source(%p) already destroyed.", disp_source);
+ return;
+ }
+
+ g_source_remove_poll(&disp_source->gsource, &disp_source->gfd);
+ g_source_destroy(&disp_source->gsource);
+ g_source_unref(&disp_source->gsource);
+
+ TPL_LOG_T("WL_EGL", "[DEL] twe_display(%p) wl_display(%p)",
+ disp_source, disp_source->disp);
+}
+
+static gboolean
+_twe_thread_wl_disp_del_dispatch(GSource *source, GSourceFunc cb, gpointer data)
+{
+ twe_wl_disp_del_source *disp_del_source = (twe_wl_disp_del_source *)source;
+ GIOCondition cond;
+
+ if (g_source_is_destroyed(source)) {
+ TPL_ERR("disp_del source(%p) already destroyed.", source);
+ return G_SOURCE_REMOVE;
+ }
+
+ cond = g_source_query_unix_fd(source, disp_del_source->tag);
+
+ if (cond & G_IO_IN) {
+ ssize_t s;
+ uint64_t u;
+
+ s = read(disp_del_source->event_fd, &u, sizeof(uint64_t));
+ if (s != sizeof(uint64_t))
+ TPL_ERR("Failed to read from event_fd(%d)",
+ disp_del_source->event_fd);
+
+ _twe_thread_wl_disp_del(disp_del_source->disp_source);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+_twe_thread_wl_disp_del_finalize(GSource *source)
+{
+ twe_wl_disp_del_source *disp_del_source =
+ (twe_wl_disp_del_source *)source;
+
+ TPL_LOG_T("WL_EGL", "gsource(%p) event_fd(%d)",
+ source, disp_del_source->event_fd);
+
+ g_source_remove_unix_fd(source, disp_del_source->tag);
+
+ close(disp_del_source->event_fd);
+
+ disp_del_source->tag = NULL;
+ disp_del_source->event_fd = -1;
+
+ return;
+}
+
+static GSourceFuncs _twe_wl_disp_del_funcs = {
+ .prepare = NULL,
+ .check = NULL,
+ .dispatch = _twe_thread_wl_disp_del_dispatch,
+ .finalize = _twe_thread_wl_disp_del_finalize,
+};
+
+static void
+_twe_thread_wl_disp_del_trigger(twe_wl_disp_source *disp_source)
+{
+ twe_wl_disp_del_source *disp_del_source = disp_source->disp_del_source;
+ uint64_t value = 1;
+ int ret;
+
+ ret = write(disp_del_source->event_fd, &value, sizeof(uint64_t));
+ if (ret == -1) {
+ TPL_ERR("failed to send acquirable event. twe_wl_disp_del_source(%p)",
+ disp_del_source);
+ return;
+ }
+}
+
+twe_wl_disp_del_source *
+_twe_display_del_source_init(twe_thread *thread,
+ twe_wl_disp_source *disp_source)
+{
+ twe_thread_context *ctx = thread->ctx;
+ twe_wl_disp_del_source *source = NULL;
+
+ if (!disp_source) {
+ TPL_ERR("Invalid parameter. disp_source is NULL");
+ return NULL;
+ }
+
+ source = (twe_wl_disp_del_source *)g_source_new(&_twe_wl_disp_del_funcs,
+ sizeof(twe_wl_disp_del_source));
+ if (!source) {
+ TPL_ERR("[THREAD] Failed to create GSource");
+ return NULL;
+ }
+
+ source->event_fd = eventfd(0, EFD_CLOEXEC);
+ if (source->event_fd < 0) {
+ TPL_ERR("[THREAD] Failed to create eventfd. errno(%d)", errno);
+ g_source_unref(&source->gsource);
+ return NULL;
+ }
+
+ source->tag = g_source_add_unix_fd(&source->gsource,
+ source->event_fd,
+ G_IO_IN);
+ source->disp_source = disp_source;
+
+ g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop));
+ g_source_unref(&source->gsource);
+
+ return source;
+}
+
+void
+_twe_display_del_source_fini(twe_wl_disp_del_source *source)
+{
+ g_source_destroy(&source->gsource);
+ g_source_unref(&source->gsource);
+}
+
twe_display_h
twe_display_add(twe_thread* thread, struct wl_display *display)
{
_twe_display_shm_init(source);
+ source->disp_del_source = _twe_display_del_source_init(thread, source);
+
g_source_set_callback(&source->gsource, NULL, display, NULL);
g_source_add_poll(&source->gsource, &source->gfd);
g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop));
{
gboolean is_destroyed = FALSE;
twe_wl_disp_source *source = (twe_wl_disp_source *)twe_display;
+ twe_wl_disp_del_source *disp_del_source = NULL;
+
if (!source ||
(is_destroyed = g_source_is_destroyed(&source->gsource))) {
TPL_ERR("twe_display(%p) is invalid. | is_destroyed(%s)",
return TPL_ERROR_INVALID_PARAMETER;
}
+ disp_del_source = source->disp_del_source;
+
_twe_display_shm_fini(source);
_twe_display_fini_wl_tbm_client(source->wl_tbm_client);
source->wl_tbm_client = NULL;
- g_source_remove_poll(&source->gsource, &source->gfd);
- g_source_destroy(&source->gsource);
- g_source_unref(&source->gsource);
+ _twe_thread_wl_disp_del_trigger(source);
+
+ while (!g_source_is_destroyed(&source->gsource)) {
+ /* Waiting for destroying disp_source */
+ }
- TPL_LOG_T("WL_EGL", "del| twe_display(%p) wl_display(%p)",
- source, source->disp);
+ _twe_display_del_source_fini(disp_del_source);
return TPL_ERROR_NONE;
}