summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaegeun Park <haegeun.park@samsung.com>2016-02-03 23:02:00 -0800
committerjutty.lee <jutty.lee@samsung.com>2017-01-11 17:22:12 +0900
commitfee2a55b27667680a376b0e5c0e88d4371ff458b (patch)
treef4435b5fb72c820e1eafd5384eccf1a09a196650
parent8ee0c30eb0950b0e142d77f4cb0da745085b2054 (diff)
downloadefl-fee2a55b27667680a376b0e5c0e88d4371ff458b.tar.gz
evas: (GL thread) Added GL thread renderer logics based of SW thread renderer
- Modified existing thread logic to manage multiple worker thread - Added functions for thread enqueue, thread-id query - Added a new threading mode 'FINISH' for waiting main-thread until command processed Change-Id: I6cf0228a4adb04ea776e1c41936ab327ec06730e
-rw-r--r--src/lib/evas/canvas/evas_main.c4
-rw-r--r--src/lib/evas/common/evas_thread_render.c313
-rw-r--r--src/lib/evas/include/evas_common_private.h14
3 files changed, 230 insertions, 101 deletions
diff --git a/src/lib/evas/canvas/evas_main.c b/src/lib/evas/canvas/evas_main.c
index 912760cc60..d89104ed41 100644
--- a/src/lib/evas/canvas/evas_main.c
+++ b/src/lib/evas/canvas/evas_main.c
@@ -83,7 +83,7 @@ evas_init(void)
_evas_preload_thread_init();
evas_filter_init();
- if (!evas_thread_init())
+ if (!evas_threads_init())
goto shutdown_filter;
eina_log_timing(_evas_log_dom_global,
@@ -160,7 +160,7 @@ evas_shutdown(void)
evas_object_filter_cow = NULL;
evas_object_mask_cow = NULL;
- evas_thread_shutdown();
+ evas_threads_shutdown();
_evas_preload_thread_shutdown();
evas_async_events_shutdown();
evas_module_shutdown();
diff --git a/src/lib/evas/common/evas_thread_render.c b/src/lib/evas/common/evas_thread_render.c
index 85955669ac..ae7362faa3 100644
--- a/src/lib/evas/common/evas_thread_render.c
+++ b/src/lib/evas/common/evas_thread_render.c
@@ -2,17 +2,29 @@
#include <assert.h>
-static Eina_Thread evas_thread_worker;
-static Eina_Condition evas_thread_queue_condition;
-static Eina_Lock evas_thread_queue_lock;
-static Eina_Bool evas_thread_queue_ready = EINA_FALSE;
-static Eina_Inarray evas_thread_queue;
-static Evas_Thread_Command *evas_thread_queue_cache = NULL;
-static unsigned int evas_thread_queue_cache_max = 0;
-
-static volatile int evas_thread_exited = 0;
-static Eina_Bool exit_thread = EINA_FALSE;
-static int init_count = 0;
+typedef struct
+{
+ char *thread_name;
+ Eina_Thread worker;
+ Eina_Condition queue_condition;
+ Eina_Lock queue_lock;
+ Eina_Bool queue_ready;
+ Eina_Inarray queue;
+ Evas_Thread_Command *queue_cache;
+ unsigned int queue_cache_max;
+
+ Eina_Condition finish_condition;
+ Eina_Lock finish_lock;
+
+ volatile int exited;
+ Eina_Bool exit_thread;
+} Evas_Thread;
+
+static int evas_threads_init_count = 0;
+
+static Evas_Thread evas_thread_software;
+static Evas_Thread evas_thread_gl;
+static Evas_Thread evas_thread_evgl;
#define SHUTDOWN_TIMEOUT_RESET (0)
#define SHUTDOWN_TIMEOUT_CHECK (1)
@@ -30,15 +42,14 @@ _shutdown_timeout(double *time, int mode, int timeout_ms)
return ((tv.tv_sec + tv.tv_usec / 1000000.0) * 1000.0 - (*time)) > timeout_ms ;
}
-
static void
-evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush)
+evas_thread_queue_append(Evas_Thread *ev_thread, Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush, Eina_Bool do_finish)
{
Evas_Thread_Command *cmd;
- eina_lock_take(&evas_thread_queue_lock);
+ eina_lock_take(&ev_thread->queue_lock);
- cmd = eina_inarray_grow(&evas_thread_queue, 1);
+ cmd = eina_inarray_grow(&ev_thread->queue, 1);
if (cmd)
{
cmd->cb = cb;
@@ -52,69 +63,129 @@ evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flu
if (do_flush)
{
- evas_thread_queue_ready = EINA_TRUE;
- eina_condition_signal(&evas_thread_queue_condition);
+ ev_thread->queue_ready = EINA_TRUE;
+ eina_condition_signal(&ev_thread->queue_condition);
+ }
+
+ if (do_finish)
+ {
+ eina_condition_wait(&ev_thread->finish_condition);
}
out:
- eina_lock_release(&evas_thread_queue_lock);
+ eina_lock_release(&ev_thread->queue_lock);
}
EAPI void
evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data)
{
- evas_thread_queue_append(cb, data, EINA_FALSE);
+ evas_thread_queue_append(&evas_thread_software, cb, data, EINA_FALSE, EINA_FALSE);
}
EAPI void
evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data)
{
- evas_thread_queue_append(cb, data, EINA_TRUE);
+ evas_thread_queue_append(&evas_thread_software, cb, data, EINA_TRUE, EINA_FALSE);
}
+EAPI void
+evas_gl_thread_cmd_enqueue(int thread_type, Evas_Thread_Command_Cb cb, void *data, int thread_mode)
+{
+ Evas_Thread *ev_thread = NULL;
+
+ if (thread_type == EVAS_GL_THREAD_TYPE_GL)
+ ev_thread = &evas_thread_gl;
+ else if (thread_type == EVAS_GL_THREAD_TYPE_EVGL)
+ ev_thread = &evas_thread_evgl;
+ else
+ {
+ ERR("GL thread type is invalid");
+ goto out;
+ }
+
+ if (thread_mode == EVAS_GL_THREAD_MODE_ENQUEUE)
+ evas_thread_queue_append(ev_thread, cb, data, EINA_FALSE, EINA_FALSE);
+ else if (thread_mode == EVAS_GL_THREAD_MODE_FLUSH)
+ evas_thread_queue_append(ev_thread, cb, data, EINA_TRUE, EINA_FALSE);
+ else if (thread_mode == EVAS_GL_THREAD_MODE_FINISH)
+ evas_thread_queue_append(ev_thread, cb, data, EINA_TRUE, EINA_TRUE);
+ else
+ {
+ ERR("GL thread mode is invalid");
+ goto out;
+ }
+
+out:
+ return;
+}
+
+EAPI Eina_Thread
+evas_gl_thread_get(int thread_type)
+{
+ Evas_Thread *ev_thread = NULL;
+
+ if (thread_type == EVAS_GL_THREAD_TYPE_GL)
+ ev_thread = &evas_thread_gl;
+ else if (thread_type == EVAS_GL_THREAD_TYPE_EVGL)
+ ev_thread = &evas_thread_evgl;
+ else
+ {
+ ERR("GL thread type is invalid");
+ goto out;
+ }
+
+ return ev_thread->worker;
+
+out:
+ return (Eina_Thread)NULL;
+}
+
+
static void*
-evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
+evas_thread_worker_func(void *data, Eina_Thread thread EINA_UNUSED)
{
- eina_thread_name_set(eina_thread_self(), "Eevas-thread-wk");
+ Evas_Thread *ev_thread = data;
+ eina_thread_name_set(eina_thread_self(), ev_thread->thread_name);
while (1)
{
Evas_Thread_Command *cmd;
unsigned int len, max;
- eina_lock_take(&evas_thread_queue_lock);
+ eina_lock_take(&ev_thread->queue_lock);
- while (!evas_thread_queue_ready)
+ while (!ev_thread->queue_ready)
{
- if (exit_thread)
+ if (ev_thread->exit_thread)
{
- eina_lock_release(&evas_thread_queue_lock);
+ eina_lock_release(&ev_thread->queue_lock);
goto out;
}
- eina_condition_wait(&evas_thread_queue_condition);
+ eina_condition_signal(&ev_thread->finish_condition);
+ eina_condition_wait(&ev_thread->queue_condition);
}
- if (!eina_inarray_count(&evas_thread_queue))
+ if (!eina_inarray_count(&ev_thread->queue))
{
ERR("Signaled to find an empty queue. BUG!");
- evas_thread_queue_ready = EINA_FALSE;
- eina_lock_release(&evas_thread_queue_lock);
+ ev_thread->queue_ready = EINA_FALSE;
+ eina_lock_release(&ev_thread->queue_lock);
continue;
}
- cmd = evas_thread_queue.members;
- evas_thread_queue.members = evas_thread_queue_cache;
- evas_thread_queue_cache = cmd;
+ cmd = ev_thread->queue.members;
+ ev_thread->queue.members = ev_thread->queue_cache;
+ ev_thread->queue_cache = cmd;
- max = evas_thread_queue.max;
- evas_thread_queue.max = evas_thread_queue_cache_max;
- evas_thread_queue_cache_max = max;
+ max = ev_thread->queue.max;
+ ev_thread->queue.max = ev_thread->queue_cache_max;
+ ev_thread->queue_cache_max = max;
- len = evas_thread_queue.len;
- evas_thread_queue.len = 0;
+ len = ev_thread->queue.len;
+ ev_thread->queue.len = 0;
- evas_thread_queue_ready = EINA_FALSE;
+ ev_thread->queue_ready = EINA_FALSE;
- eina_lock_release(&evas_thread_queue_lock);
+ eina_lock_release(&ev_thread->queue_lock);
DBG("Evas render thread command queue length: %u", len);
@@ -135,83 +206,82 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
out:
/* WRN: add a memory barrier or use a lock if we add more code here */
- evas_thread_exited = 1;
+ ev_thread->exited = 1;
return NULL;
}
-int
-evas_thread_init(void)
+static Eina_Bool
+evas_thread_init(Evas_Thread *ev_thread, char *thread_name)
{
- if (init_count++)
- return init_count;
+ ev_thread->thread_name = thread_name;
+ ev_thread->queue_ready = EINA_FALSE;
+ ev_thread->queue_cache = NULL;
+ ev_thread->queue_cache_max = 0;
- exit_thread = EINA_FALSE;
- evas_thread_exited = 0;
+ ev_thread->exit_thread = EINA_FALSE;
+ ev_thread->exited = 0;
- if(!eina_threads_init())
+ eina_inarray_step_set(&ev_thread->queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
+
+ if (!eina_lock_new(&ev_thread->queue_lock))
{
- CRI("Could not init eina threads");
- goto fail_on_eina_thread_init;
+ CRI("Could not create draw thread queue lock (%m)");
+ goto fail_on_queue_lock_creation;
}
-
- eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
-
- if (!eina_lock_new(&evas_thread_queue_lock))
+ if (!eina_condition_new(&ev_thread->queue_condition, &ev_thread->queue_lock))
{
- CRI("Could not create draw thread lock (%m)");
- goto fail_on_lock_creation;
+ CRI("Could not create draw thread queue condition (%m)");
+ goto fail_on_queue_cond_creation;
}
- if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock))
+ if (!eina_lock_new(&ev_thread->finish_lock))
{
- CRI("Could not create draw thread condition (%m)");
- goto fail_on_cond_creation;
+ CRI("Could not create draw thread finish lock (%m)");
+ goto fail_on_finish_lock_creation;
}
-
- if (!eina_thread_create(&evas_thread_worker, EINA_THREAD_NORMAL, -1,
- evas_thread_worker_func, NULL))
+ if (!eina_condition_new(&ev_thread->finish_condition, &ev_thread->queue_lock))
+ {
+ CRI("Could not create draw thread finish condition (%m)");
+ goto fail_on_finish_cond_creation;
+ }
+ if (!eina_thread_create(&ev_thread->worker, EINA_THREAD_NORMAL, -1,
+ evas_thread_worker_func, ev_thread))
{
CRI("Could not create draw thread (%m)");
goto fail_on_thread_creation;
}
-
- return init_count;
+ return EINA_TRUE;
fail_on_thread_creation:
- evas_thread_worker = 0;
- eina_condition_free(&evas_thread_queue_condition);
-fail_on_cond_creation:
- eina_lock_free(&evas_thread_queue_lock);
-fail_on_lock_creation:
- eina_threads_shutdown();
-fail_on_eina_thread_init:
- exit_thread = EINA_TRUE;
- evas_thread_exited = 1;
- return --init_count;
+ ev_thread->worker = 0;
+ eina_condition_free(&ev_thread->finish_condition);
+fail_on_finish_cond_creation:
+ eina_lock_free(&ev_thread->finish_lock);
+fail_on_finish_lock_creation:
+ eina_condition_free(&ev_thread->queue_condition);
+fail_on_queue_cond_creation:
+ eina_lock_free(&ev_thread->queue_lock);
+fail_on_queue_lock_creation:
+ ev_thread->exit_thread = EINA_TRUE;
+ ev_thread->exited = 1;
+ return EINA_FALSE;
}
-int
-evas_thread_shutdown(void)
+static void
+evas_thread_shutdown(Evas_Thread *ev_thread)
{
- double to = 0 ;
-
- if (init_count <= 0)
- {
- ERR("Too many calls to shutdown, ignored.");
- return 0;
- }
+ double to = 0;
- if (--init_count)
- return init_count;
+ if (!ev_thread) return;
- eina_lock_take(&evas_thread_queue_lock);
+ eina_lock_take(&ev_thread->queue_lock);
- exit_thread = EINA_TRUE;
- eina_condition_signal(&evas_thread_queue_condition);
+ ev_thread->exit_thread = EINA_TRUE;
+ eina_condition_signal(&ev_thread->queue_condition);
- eina_lock_release(&evas_thread_queue_lock);
+ eina_lock_release(&ev_thread->queue_lock);
_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_RESET, SHUTDOWN_TIMEOUT);
- while (!evas_thread_exited && (evas_async_events_process() != -1))
+ while (!ev_thread->exited && (evas_async_events_process() != -1))
{
if(_shutdown_timeout(&to, SHUTDOWN_TIMEOUT_CHECK, SHUTDOWN_TIMEOUT))
{
@@ -220,16 +290,65 @@ evas_thread_shutdown(void)
}
}
- eina_thread_join(evas_thread_worker);
+ eina_thread_join(ev_thread->worker);
timeout_shutdown:
- eina_lock_free(&evas_thread_queue_lock);
- eina_condition_free(&evas_thread_queue_condition);
+ eina_condition_free(&ev_thread->finish_condition);
+ eina_lock_free(&ev_thread->finish_lock);
+ eina_condition_free(&ev_thread->queue_condition);
+ eina_lock_free(&ev_thread->queue_lock);
+
+ ev_thread->worker = 0;
+
+ free(ev_thread->queue_cache);
+ ev_thread->queue_cache = NULL;
+ eina_inarray_flush(&ev_thread->queue);
+}
+
+int
+evas_threads_init(void)
+{
+ if (evas_threads_init_count++)
+ return evas_threads_init_count;
+
+ if (!eina_threads_init())
+ {
+ CRI("Could not init eina threads");
+ goto fail_on_eina_thread_init;
+ }
+
+ if (!evas_thread_init(&evas_thread_software, "Evas-thread-wk-sw"))
+ goto fail_on_software_thread_init;
+ if (!evas_thread_init(&evas_thread_gl, "Evas-thread-wk-gl"))
+ goto fail_on_gl_thread_init;
+ if (!evas_thread_init(&evas_thread_evgl, "Evas-thread-wk-evgl"))
+ goto fail_on_evgl_thread_init;
+ return evas_threads_init_count;
+
+fail_on_evgl_thread_init:
+ evas_thread_shutdown(&evas_thread_gl);
+fail_on_gl_thread_init:
+ evas_thread_shutdown(&evas_thread_software);
+fail_on_software_thread_init:
+ eina_threads_shutdown();
+fail_on_eina_thread_init:
+ return --evas_threads_init_count;
+ }
+
+int
+evas_threads_shutdown(void)
+{
+ if (evas_threads_init_count <= 0)
+ {
+ ERR("Too many calls to shutdown, ignored.");
+ return 0;
+ }
- evas_thread_worker = 0;
+ if (--evas_threads_init_count)
+ return evas_threads_init_count;
- free(evas_thread_queue_cache);
- evas_thread_queue_cache = NULL;
- eina_inarray_flush(&evas_thread_queue);
+ evas_thread_shutdown(&evas_thread_evgl);
+ evas_thread_shutdown(&evas_thread_gl);
+ evas_thread_shutdown(&evas_thread_software);
eina_threads_shutdown();
diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h
index d52dec5fb3..38a2981e31 100644
--- a/src/lib/evas/include/evas_common_private.h
+++ b/src/lib/evas/include/evas_common_private.h
@@ -1324,10 +1324,20 @@ EAPI int evas_async_events_process_blocking(void);
void evas_render_rendering_wait(Evas_Public_Data *evas);
void evas_all_sync(void);
-int evas_thread_init(void);
-int evas_thread_shutdown(void);
+
+#define EVAS_GL_THREAD_TYPE_GL 1
+#define EVAS_GL_THREAD_TYPE_EVGL 2
+
+#define EVAS_GL_THREAD_MODE_FINISH 0
+#define EVAS_GL_THREAD_MODE_FLUSH 1
+#define EVAS_GL_THREAD_MODE_ENQUEUE 2
+
+int evas_threads_init(void);
+int evas_threads_shutdown(void);
EAPI void evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data);
EAPI void evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data);
+EAPI void evas_gl_thread_cmd_enqueue(int thread_type, Evas_Thread_Command_Cb cb, void *data, int thread_mode);
+EAPI Eina_Thread evas_gl_thread_get(int thread_type);
typedef enum _Evas_Render_Mode
{