summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2012-12-30 23:39:11 +0000
committerCedric BAIL <cedric.bail@free.fr>2012-12-30 23:39:11 +0000
commitf8ea554926295213004c4a7917ffb10cac7dfd8f (patch)
tree0b3eb193efe9dc550dc09109f09c24ef96d4ed06
parent493f9a9ff9ba1a37664fa68be35ae31c15ecaba7 (diff)
efl: limit regression with async rendering.
NOTE: There is still an issue with text rendering, that is still 4 times slower and impact all text object (text, textblock and textgrid). SVN revision: 81912
-rw-r--r--src/lib/evas/canvas/evas_async_events.c84
-rw-r--r--src/lib/evas/canvas/evas_render.c2
-rw-r--r--src/lib/evas/common/evas_thread_render.c118
-rw-r--r--src/lib/evas/include/evas_common.h5
4 files changed, 129 insertions, 80 deletions
diff --git a/src/lib/evas/canvas/evas_async_events.c b/src/lib/evas/canvas/evas_async_events.c
index 209ba8e85..fe81be065 100644
--- a/src/lib/evas/canvas/evas_async_events.c
+++ b/src/lib/evas/canvas/evas_async_events.c
@@ -15,6 +15,9 @@ static int _fd_write = -1;
static int _fd_read = -1;
static pid_t _fd_pid = 0;
+static Eina_Lock async_lock;
+static Eina_Inarray async_queue;
+
static int _init_evas_event = 0;
typedef struct _Evas_Event_Async Evas_Event_Async;
@@ -71,6 +74,9 @@ evas_async_events_init(void)
fcntl(_fd_read, F_SETFL, O_NONBLOCK);
+ eina_lock_new(&async_lock);
+ eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16);
+
return _init_evas_event;
}
@@ -85,6 +91,9 @@ evas_async_events_shutdown(void)
_fd_read = -1;
_fd_write = -1;
+ eina_lock_free(&async_lock);
+ eina_inarray_flush(&async_queue);
+
return _init_evas_event;
}
@@ -108,15 +117,40 @@ evas_async_events_fd_get(void)
static int
_evas_async_events_process_single(void)
{
- Evas_Event_Async *ev;
+ int wakeup;
int ret;
- ret = read(_fd_read, &ev, sizeof(Evas_Event_Async *));
- if (ret == sizeof(Evas_Event_Async *))
+ ret = read(_fd_read, &wakeup, sizeof(int));
+ if (ret == sizeof(int))
{
- if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
- free(ev);
- return 1;
+ static Evas_Event_Async *memory = NULL;
+ static unsigned int memory_max = 0;
+ Evas_Event_Async *ev;
+ unsigned int len;
+ unsigned int max;
+
+ eina_lock_take(&async_lock);
+
+ ev = async_queue.members;
+ async_queue.members = memory;
+ memory = ev;
+
+ max = async_queue.max;
+ async_queue.max = memory_max;
+ memory_max = max;
+
+ len = async_queue.len;
+ async_queue.len = 0;
+
+ eina_lock_release(&async_lock);
+
+ while (len > 0)
+ {
+ if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
+ ev++;
+ len--;
+ }
+ ret = 1;
}
else if (ret < 0)
{
@@ -179,32 +213,44 @@ EAPI Eina_Bool
evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_info, Evas_Async_Events_Put_Cb func)
{
Evas_Event_Async *ev;
- ssize_t check;
+ ssize_t check = sizeof (int);
Eina_Bool result = EINA_FALSE;
+ int count;
if (!func) return 0;
if (_fd_write == -1) return 0;
_evas_async_events_fork_handle();
-
- ev = calloc(1, sizeof (Evas_Event_Async));
- if (!ev) return 0;
- ev->func = func;
- ev->target = target;
- ev->type = type;
- ev->event_info = event_info;
+ eina_lock_take(&async_lock);
+
+ count = async_queue.len;
+ ev = eina_inarray_add(&async_queue);
+ if (ev)
+ {
+ ev->func = func;
+ ev->target = target;
+ ev->type = type;
+ ev->event_info = event_info;
+ }
+
+ eina_lock_release(&async_lock);
- do
+ if (count == 0 && ev)
{
- check = write(_fd_write, &ev, sizeof (Evas_Event_Async*));
+ int wakeup = 1;
+
+ do
+ {
+ check = write(_fd_write, &wakeup, sizeof (int));
+ }
+ while ((check != sizeof (int)) &&
+ ((errno == EINTR) || (errno == EAGAIN)));
}
- while ((check != sizeof (Evas_Event_Async*)) &&
- ((errno == EINTR) || (errno == EAGAIN)));
evas_cache_image_wakeup();
- if (check == sizeof (Evas_Event_Async*))
+ if (check == sizeof (int))
result = EINA_TRUE;
else
{
diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c
index 1e924d7a2..bed97c5b2 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -1705,7 +1705,7 @@ evas_render_updates_internal(Evas *eo_e,
e->render.data = updates_data;
e->render.updates_cb = updates_func;
- evas_thread_queue_flush((Evas_Thread_Command_Cb)done_func, done_data, 0);
+ evas_thread_queue_flush((Evas_Thread_Command_Cb)done_func, done_data);
}
else if (haveup)
{
diff --git a/src/lib/evas/common/evas_thread_render.c b/src/lib/evas/common/evas_thread_render.c
index 750bbc4c8..34b9dcd0b 100644
--- a/src/lib/evas/common/evas_thread_render.c
+++ b/src/lib/evas/common/evas_thread_render.c
@@ -6,67 +6,61 @@ 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_Inlist *evas_thread_queue = NULL;
+static Eina_Inarray evas_thread_queue;
+
+static Evas_Thread_Command *evas_thread_queue_cache = NULL;
+static 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;
-static Evas_Thread_Command *
-evas_thread_cmd_new(Evas_Thread_Command_Cb cb, void *data, size_t size)
-{
- Evas_Thread_Command *cmd = malloc(sizeof(*cmd) + size);
- if (!cmd)
- {
- ERR("Out of memory allocating thread command.");
- return NULL;
- }
-
- cmd->cb = cb;
- if (size)
- {
- cmd->data = cmd + 1;
- memcpy(cmd->data, data, size);
- }
- else
- cmd->data = data;
-
- return cmd;
-}
-
static void
-evas_thread_queue_append(Evas_Thread_Command *cmd, Eina_Bool do_flush)
+evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush)
{
- eina_lock_take(&evas_thread_queue_lock);
-
- evas_thread_queue = eina_inlist_append(evas_thread_queue, EINA_INLIST_GET(cmd));
-
- if (do_flush)
- {
- evas_thread_queue_ready = EINA_TRUE;
- eina_condition_signal(&evas_thread_queue_condition);
- }
-
- eina_lock_release(&evas_thread_queue_lock);
+ Evas_Thread_Command *cmd;
+
+ eina_lock_take(&evas_thread_queue_lock);
+
+ if (evas_thread_queue.members == NULL)
+ {
+ evas_thread_queue.members = evas_thread_queue_cache;
+ evas_thread_queue.len = 0;
+ evas_thread_queue.max = evas_thread_queue_cache_max;
+ evas_thread_queue_cache = NULL;
+ evas_thread_queue_cache_max = 0;
+ }
+
+ cmd = eina_inarray_add(&evas_thread_queue);
+ if (cmd)
+ {
+ cmd->cb = cb;
+ cmd->data = data;
+ }
+ else
+ {
+ ERR("Out of memory allocating thread command.");
+ }
+
+ if (do_flush)
+ {
+ evas_thread_queue_ready = EINA_TRUE;
+ eina_condition_signal(&evas_thread_queue_condition);
+ }
+
+ eina_lock_release(&evas_thread_queue_lock);
}
EAPI void
-evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data, size_t size)
+evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data)
{
- Evas_Thread_Command *cmd = evas_thread_cmd_new(cb, data, size);
- if (!cmd)
- return;
-
- evas_thread_queue_append(cmd, EINA_FALSE);
+ evas_thread_queue_append(cb, data, EINA_FALSE);
}
EAPI void
-evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data, size_t size)
+evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data)
{
- Evas_Thread_Command *cmd = evas_thread_cmd_new(cb, data, size);
- if (!cmd)
- return;
-
- evas_thread_queue_append(cmd, EINA_TRUE);
+ evas_thread_queue_append(cb, data, EINA_TRUE);
}
static void*
@@ -74,8 +68,10 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
{
while (1)
{
+ Evas_Thread_Command *head;
Evas_Thread_Command *cmd;
- Eina_Inlist *queue;
+ int len;
+ int max;
eina_lock_take(&evas_thread_queue_lock);
@@ -89,31 +85,35 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
eina_condition_wait(&evas_thread_queue_condition);
}
- if (!evas_thread_queue)
+ if (!eina_inarray_count(&evas_thread_queue))
{
ERR("Signaled to find an empty queue. BUG!");
eina_lock_release(&evas_thread_queue_lock);
continue;
}
- queue = evas_thread_queue;
- evas_thread_queue = NULL;
+ head = evas_thread_queue.members;
+ evas_thread_queue.members = NULL;
+ max = evas_thread_queue.max; evas_thread_queue.max = 0;
+ len = evas_thread_queue.len; evas_thread_queue.len = 0;
+
evas_thread_queue_ready = EINA_FALSE;
eina_lock_release(&evas_thread_queue_lock);
- while (queue)
+ cmd = head;
+ while (len)
{
- cmd = EINA_INLIST_CONTAINER_GET(queue, Evas_Thread_Command);
-
- assert(cmd);
assert(cmd->cb);
cmd->cb(cmd->data);
- queue = eina_inlist_remove(queue, queue);
- free(cmd);
+ cmd++;
+ len--;
}
+
+ evas_thread_queue_cache = head;
+ evas_thread_queue_cache_max = max;
}
out:
@@ -129,6 +129,8 @@ evas_thread_init(void)
eina_threads_init();
+ eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
+
if (!eina_lock_new(&evas_thread_queue_lock))
CRIT("Could not create draw thread lock");
if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock))
@@ -160,5 +162,7 @@ evas_thread_shutdown(void)
eina_lock_free(&evas_thread_queue_lock);
eina_condition_free(&evas_thread_queue_condition);
+ eina_inarray_flush(&evas_thread_queue);
+
eina_threads_shutdown();
}
diff --git a/src/lib/evas/include/evas_common.h b/src/lib/evas/include/evas_common.h
index b83b3e8ff..01029034c 100644
--- a/src/lib/evas/include/evas_common.h
+++ b/src/lib/evas/include/evas_common.h
@@ -443,7 +443,6 @@ typedef struct _Evas_Thread_Command Evas_Thread_Command;
struct _Evas_Thread_Command
{
- EINA_INLIST;
Evas_Thread_Command_Cb cb;
void *data;
};
@@ -1272,8 +1271,8 @@ void evas_render_rendering_wait(Evas_Public_Data *evas);
void evas_thread_init(void);
void evas_thread_shutdown(void);
-EAPI void evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data, size_t size);
-EAPI void evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data, size_t size);
+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);
typedef enum _Evas_Render_Mode
{