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
This commit is contained in:
Cedric BAIL 2012-12-30 23:39:11 +00:00
parent 493f9a9ff9
commit f8ea554926
4 changed files with 126 additions and 77 deletions

View File

@ -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);
do
count = async_queue.len;
ev = eina_inarray_add(&async_queue);
if (ev)
{
check = write(_fd_write, &ev, sizeof (Evas_Event_Async*));
ev->func = func;
ev->target = target;
ev->type = type;
ev->event_info = event_info;
}
eina_lock_release(&async_lock);
if (count == 0 && ev)
{
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
{

View File

@ -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)
{

View File

@ -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_Command *cmd;
evas_thread_queue = eina_inlist_append(evas_thread_queue, EINA_INLIST_GET(cmd));
eina_lock_take(&evas_thread_queue_lock);
if (do_flush)
{
evas_thread_queue_ready = EINA_TRUE;
eina_condition_signal(&evas_thread_queue_condition);
}
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;
}
eina_lock_release(&evas_thread_queue_lock);
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();
}

View File

@ -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
{