2015-04-03 07:31:45 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Ector.h>
|
|
|
|
#include <software/Ector_Software.h>
|
|
|
|
|
|
|
|
#include "ector_private.h"
|
|
|
|
#include "ector_software_private.h"
|
|
|
|
|
2015-11-30 22:22:20 -08:00
|
|
|
#define MY_CLASS ECTOR_SOFTWARE_SURFACE_CLASS
|
2015-04-03 07:31:45 -07:00
|
|
|
|
2017-09-16 17:43:18 -07:00
|
|
|
typedef struct _Ector_Software_Task Ector_Software_Task;
|
|
|
|
|
|
|
|
struct _Ector_Software_Task
|
|
|
|
{
|
|
|
|
Eina_Thread_Queue_Msg member;
|
|
|
|
|
|
|
|
Ector_Thread_Worker_Cb cb;
|
|
|
|
Eina_Free_Cb done;
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
2018-11-14 19:15:58 -08:00
|
|
|
static int _count_init = 0;
|
2017-09-16 17:43:18 -07:00
|
|
|
static unsigned int current = 0;
|
|
|
|
static unsigned int cpu_core = 0;
|
|
|
|
static Ector_Software_Thread *ths = NULL;
|
|
|
|
static Eina_Thread_Queue *render_queue = NULL;
|
|
|
|
static Ector_Software_Thread render_thread;
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_prepare_process(void *data, Eina_Thread t)
|
|
|
|
{
|
|
|
|
Ector_Software_Thread *th = data;
|
|
|
|
|
|
|
|
eina_thread_name_set(t, "Ector Preparing Thread");
|
|
|
|
do
|
|
|
|
{
|
|
|
|
Ector_Software_Task *task, todo;
|
|
|
|
void *ref;
|
|
|
|
|
|
|
|
task = eina_thread_queue_wait(th->queue, &ref);
|
|
|
|
|
|
|
|
if (!task) break ;
|
|
|
|
todo.cb = task->cb;
|
|
|
|
todo.data = task->data;
|
|
|
|
todo.done = task->done;
|
|
|
|
|
|
|
|
eina_thread_queue_wait_done(th->queue, ref);
|
|
|
|
|
|
|
|
if (!todo.cb) break ;
|
|
|
|
|
|
|
|
todo.cb(todo.data, th);
|
|
|
|
|
|
|
|
task = eina_thread_queue_send(render_queue, sizeof (Ector_Software_Task), &ref);
|
|
|
|
task->cb = todo.cb;
|
|
|
|
task->data = todo.data;
|
|
|
|
task->done = todo.done;
|
|
|
|
eina_thread_queue_send_done(render_queue, ref);
|
|
|
|
}
|
|
|
|
while (1);
|
|
|
|
|
|
|
|
return th;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ector_software_init(void)
|
|
|
|
{
|
|
|
|
int cpu, i;
|
|
|
|
|
2018-11-14 19:15:58 -08:00
|
|
|
++_count_init;
|
|
|
|
if (_count_init != 1) return;
|
2017-09-16 17:43:18 -07:00
|
|
|
|
|
|
|
cpu = eina_cpu_count() - 1;
|
|
|
|
if (cpu < 1)
|
|
|
|
{
|
|
|
|
render_thread.queue = NULL;
|
|
|
|
ector_software_thread_init(&render_thread);
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
cpu = cpu > 8 ? 8 : cpu;
|
|
|
|
cpu_core = cpu;
|
|
|
|
|
|
|
|
render_queue = eina_thread_queue_new();
|
|
|
|
|
|
|
|
ths = malloc(sizeof(Ector_Software_Thread) * cpu);
|
|
|
|
for (i = 0; i < cpu; i++)
|
|
|
|
{
|
|
|
|
Ector_Software_Thread *t;
|
|
|
|
|
|
|
|
t = &ths[i];
|
|
|
|
t->queue = eina_thread_queue_new();
|
2017-09-16 23:23:36 -07:00
|
|
|
ector_software_thread_init(t);
|
2017-09-16 17:43:18 -07:00
|
|
|
if (!eina_thread_create(&t->thread, EINA_THREAD_NORMAL, -1,
|
|
|
|
_prepare_process, t))
|
|
|
|
{
|
|
|
|
eina_thread_queue_free(t->queue);
|
|
|
|
t->queue = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ector_software_shutdown(void)
|
|
|
|
{
|
|
|
|
Ector_Software_Thread *t;
|
|
|
|
unsigned int i;
|
|
|
|
|
2018-11-14 19:15:58 -08:00
|
|
|
--_count_init;
|
|
|
|
if (_count_init != 0) return;
|
2017-09-16 17:43:18 -07:00
|
|
|
|
2017-09-16 23:23:36 -07:00
|
|
|
if (!ths)
|
|
|
|
{
|
|
|
|
ector_software_thread_shutdown(&render_thread);
|
|
|
|
return ;
|
|
|
|
}
|
2017-09-16 17:43:18 -07:00
|
|
|
|
|
|
|
for (i = 0; i < cpu_core; i++)
|
|
|
|
{
|
|
|
|
Ector_Software_Task *task;
|
|
|
|
void *ref;
|
|
|
|
|
|
|
|
t = &ths[i];
|
|
|
|
|
|
|
|
task = eina_thread_queue_send(t->queue, sizeof (Ector_Software_Task), &ref);
|
|
|
|
task->cb = NULL;
|
|
|
|
task->data = NULL;
|
|
|
|
eina_thread_queue_send_done(t->queue, ref);
|
|
|
|
|
|
|
|
eina_thread_join(t->thread);
|
|
|
|
eina_thread_queue_free(t->queue);
|
2017-09-16 23:23:36 -07:00
|
|
|
ector_software_thread_shutdown(t);
|
2017-09-16 17:43:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
eina_thread_queue_free(render_queue);
|
|
|
|
render_queue = NULL;
|
|
|
|
|
|
|
|
free(ths);
|
|
|
|
ths = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ector_software_schedule(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data)
|
|
|
|
{
|
|
|
|
Ector_Software_Thread *t;
|
|
|
|
Ector_Software_Task *task;
|
|
|
|
void *ref;
|
|
|
|
|
|
|
|
// Not enough CPU, doing it inline in the rendering thread
|
|
|
|
if (!ths) return ;
|
|
|
|
|
|
|
|
t = &ths[current];
|
|
|
|
current = (current + 1) % cpu_core;
|
|
|
|
|
|
|
|
task = eina_thread_queue_send(t->queue, sizeof (Ector_Software_Task), &ref);
|
|
|
|
task->cb = cb;
|
|
|
|
task->done = done;
|
|
|
|
task->data = data;
|
|
|
|
eina_thread_queue_send_done(t->queue, ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do not call this function if the done function has already called
|
|
|
|
void
|
|
|
|
ector_software_wait(Ector_Thread_Worker_Cb cb, Eina_Free_Cb done, void *data)
|
|
|
|
{
|
|
|
|
Ector_Software_Task *task, covering;
|
|
|
|
|
|
|
|
// First handle case with just inlined prepare code call inside the rendering thread
|
|
|
|
if (!ths)
|
|
|
|
{
|
|
|
|
render_thread.thread = eina_thread_self();
|
|
|
|
cb(data, &render_thread);
|
|
|
|
done(data);
|
|
|
|
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't know which task is going to be done first, so
|
|
|
|
// we iterate until we find ourself back and trigger all
|
|
|
|
// the done call along the way.
|
|
|
|
do
|
|
|
|
{
|
|
|
|
void *ref;
|
|
|
|
|
|
|
|
task = eina_thread_queue_wait(render_queue, &ref);
|
|
|
|
if (!task) break;
|
|
|
|
covering.cb = task->cb;
|
|
|
|
covering.done = task->done;
|
|
|
|
covering.data = task->data;
|
|
|
|
eina_thread_queue_wait_done(render_queue, ref);
|
|
|
|
|
|
|
|
covering.done(covering.data);
|
|
|
|
}
|
|
|
|
while (covering.cb != cb ||
|
|
|
|
covering.done != done ||
|
|
|
|
covering.data != data);
|
|
|
|
}
|
|
|
|
|
2015-04-03 07:31:45 -07:00
|
|
|
static Ector_Renderer *
|
2016-05-11 04:57:06 -07:00
|
|
|
_ector_software_surface_ector_surface_renderer_factory_new(Eo *obj,
|
evas filters: Refactor ector and gfx filters A LOT
Alright, so this is a massive patch that is the result of
trying to get rid of unused or poorly implemented classes in
ector. Originally ector was meant to support VG but extend to
things like filters as well. At the moment, ector's design
makes it quite hard to plug in the filters.
For now I think it's easier to implement the GL support for
the filters directly in the engine, where I hope to interfere
as little as possible.
This massive patch keeps only the required minimum to support
a versatile gl buffer that can be mapped, drawn or rendered to (FBO).
It's extremely inefficient as it relies on glReadPixels and lots
of texture uploads, as well as conversions between ARGB and Alpha.
Another type of GL buffer is a wrap around an existing GL image,
but that one is read-only (map or draw: no write map, no FBO).
No, all the filters run fine, and the high-level implementation
(evas_filters.c) does not need to know whether the underlying engine
is SW or GL. One problem though appears with the blending or blurring
of some Alpha buffers, the colors are wrong.
This patch removes more lines than it adds so it must be good ;)
2017-01-17 18:47:25 -08:00
|
|
|
Ector_Software_Surface_Data *pd EINA_UNUSED,
|
|
|
|
const Efl_Class *type)
|
2015-04-03 07:31:45 -07:00
|
|
|
{
|
2016-05-11 04:57:06 -07:00
|
|
|
if (type == ECTOR_RENDERER_SHAPE_MIXIN)
|
2018-03-15 09:50:20 -07:00
|
|
|
return efl_add_ref(ECTOR_RENDERER_SOFTWARE_SHAPE_CLASS, NULL, ector_renderer_surface_set(efl_added, obj));
|
2016-05-11 04:57:06 -07:00
|
|
|
else if (type == ECTOR_RENDERER_GRADIENT_LINEAR_MIXIN)
|
2018-03-15 09:50:20 -07:00
|
|
|
return efl_add_ref(ECTOR_RENDERER_SOFTWARE_GRADIENT_LINEAR_CLASS, NULL, ector_renderer_surface_set(efl_added, obj));
|
2016-05-11 04:57:06 -07:00
|
|
|
else if (type == ECTOR_RENDERER_GRADIENT_RADIAL_MIXIN)
|
2018-03-15 09:50:20 -07:00
|
|
|
return efl_add_ref(ECTOR_RENDERER_SOFTWARE_GRADIENT_RADIAL_CLASS, NULL, ector_renderer_surface_set(efl_added, obj));
|
evas filters: Refactor ector and gfx filters A LOT
Alright, so this is a massive patch that is the result of
trying to get rid of unused or poorly implemented classes in
ector. Originally ector was meant to support VG but extend to
things like filters as well. At the moment, ector's design
makes it quite hard to plug in the filters.
For now I think it's easier to implement the GL support for
the filters directly in the engine, where I hope to interfere
as little as possible.
This massive patch keeps only the required minimum to support
a versatile gl buffer that can be mapped, drawn or rendered to (FBO).
It's extremely inefficient as it relies on glReadPixels and lots
of texture uploads, as well as conversions between ARGB and Alpha.
Another type of GL buffer is a wrap around an existing GL image,
but that one is read-only (map or draw: no write map, no FBO).
No, all the filters run fine, and the high-level implementation
(evas_filters.c) does not need to know whether the underlying engine
is SW or GL. One problem though appears with the blending or blurring
of some Alpha buffers, the colors are wrong.
This patch removes more lines than it adds so it must be good ;)
2017-01-17 18:47:25 -08:00
|
|
|
|
|
|
|
ERR("Couldn't find class for type: %s", efl_class_name_get(type));
|
2015-04-03 07:31:45 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-19 03:41:27 -07:00
|
|
|
static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_ector_software_surface_efl_object_constructor(Eo *obj, Ector_Software_Surface_Data *pd)
|
2015-04-03 07:31:45 -07:00
|
|
|
{
|
2017-09-16 17:43:18 -07:00
|
|
|
_ector_software_init();
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
2015-12-02 01:46:29 -08:00
|
|
|
pd->rasterizer = (Software_Rasterizer *) calloc(1, sizeof(Software_Rasterizer));
|
|
|
|
ector_software_rasterizer_init(pd->rasterizer);
|
2016-08-15 06:44:41 -07:00
|
|
|
pd->rasterizer->fill_data.raster_buffer = efl_data_ref(obj, ECTOR_SOFTWARE_BUFFER_BASE_MIXIN);
|
2015-11-30 22:22:20 -08:00
|
|
|
return obj;
|
2015-04-03 07:31:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-08-10 07:23:04 -07:00
|
|
|
_ector_software_surface_efl_object_destructor(Eo *obj, Ector_Software_Surface_Data *pd)
|
2015-04-03 07:31:45 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_data_unref(obj, pd->rasterizer->fill_data.raster_buffer);
|
2015-12-02 01:46:29 -08:00
|
|
|
free(pd->rasterizer);
|
|
|
|
pd->rasterizer = NULL;
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_destructor(efl_super(obj, ECTOR_SOFTWARE_SURFACE_CLASS));
|
2017-09-16 17:43:18 -07:00
|
|
|
|
|
|
|
_ector_software_shutdown();
|
2015-04-03 07:31:45 -07:00
|
|
|
}
|
|
|
|
|
2015-04-03 07:33:19 -07:00
|
|
|
static void
|
2016-05-11 04:57:06 -07:00
|
|
|
_ector_software_surface_ector_surface_reference_point_set(Eo *obj EINA_UNUSED,
|
evas filters: Refactor ector and gfx filters A LOT
Alright, so this is a massive patch that is the result of
trying to get rid of unused or poorly implemented classes in
ector. Originally ector was meant to support VG but extend to
things like filters as well. At the moment, ector's design
makes it quite hard to plug in the filters.
For now I think it's easier to implement the GL support for
the filters directly in the engine, where I hope to interfere
as little as possible.
This massive patch keeps only the required minimum to support
a versatile gl buffer that can be mapped, drawn or rendered to (FBO).
It's extremely inefficient as it relies on glReadPixels and lots
of texture uploads, as well as conversions between ARGB and Alpha.
Another type of GL buffer is a wrap around an existing GL image,
but that one is read-only (map or draw: no write map, no FBO).
No, all the filters run fine, and the high-level implementation
(evas_filters.c) does not need to know whether the underlying engine
is SW or GL. One problem though appears with the blending or blurring
of some Alpha buffers, the colors are wrong.
This patch removes more lines than it adds so it must be good ;)
2017-01-17 18:47:25 -08:00
|
|
|
Ector_Software_Surface_Data *pd,
|
|
|
|
int x, int y)
|
2015-04-03 07:33:19 -07:00
|
|
|
{
|
|
|
|
pd->x = x;
|
|
|
|
pd->y = y;
|
|
|
|
}
|
|
|
|
|
2015-04-03 07:31:45 -07:00
|
|
|
#include "ector_software_surface.eo.c"
|
2016-05-11 04:23:57 -07:00
|
|
|
#include "ector_renderer_software.eo.c"
|