evas: first implementation of an ector drawer inside Evas software engine.

Note: this won't work with the OpenGL backend.
This commit is contained in:
Cedric BAIL 2015-04-03 16:22:18 +02:00
parent 3f3fb4cac7
commit b6ffe1cc87
3 changed files with 251 additions and 12 deletions

View File

@ -6,7 +6,7 @@
#endif
#include <Eina.h>
#include <eina_safety_checks.h>
#include <Ector.h>
#include "Evas.h"
@ -737,6 +737,7 @@ struct _Evas_Public_Data
struct {
Evas_Module *module;
Evas_Func *func;
Ector_Surface *surface;
struct {
void *output;
@ -1365,6 +1366,9 @@ struct _Evas_Func
void (*texture_filter_set) (void *data, void *texture, Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag);
void (*texture_filter_get) (void *data, void *texture, Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag);
void (*texture_image_set) (void *data, void *texture, void *image);
Ector_Surface *(*ector_get) (void *data);
void (*ector_draw) (void *data, void *context, void *surface, Ector_Renderer *r, Eina_Array *clips, int x, int y, Eina_Bool do_async);
};
struct _Evas_Image_Save_Func

View File

@ -15,7 +15,4 @@ class Ector.Cairo_Software.Surface (Ector.Cairo.Surface)
}
}
}
implements {
Eo.Base.finalize;
}
}

View File

@ -296,6 +296,7 @@ typedef struct _Evas_Thread_Command_Image Evas_Thread_Command_Image;
typedef struct _Evas_Thread_Command_Font Evas_Thread_Command_Font;
typedef struct _Evas_Thread_Command_Map Evas_Thread_Command_Map;
typedef struct _Evas_Thread_Command_Multi_Font Evas_Thread_Command_Multi_Font;
typedef struct _Evas_Thread_Command_Ector Evas_Thread_Command_Ector;
struct _Evas_Thread_Command_Rect
{
@ -387,6 +388,19 @@ struct _Evas_Thread_Command_Multi_Font
Evas_Font_Array *texts;
};
struct _Evas_Thread_Command_Ector
{
void *surface;
Ector_Renderer *r;
Eina_Array *clips;
DATA32 mul_col;
Ector_Rop render_op;
int x, y;
Eina_Bool free_it;
};
Eina_Mempool *_mp_command_rect = NULL;
Eina_Mempool *_mp_command_line = NULL;
Eina_Mempool *_mp_command_polygon = NULL;
@ -394,7 +408,7 @@ Eina_Mempool *_mp_command_image = NULL;
Eina_Mempool *_mp_command_font = NULL;
Eina_Mempool *_mp_command_map = NULL;
Eina_Mempool *_mp_command_multi_font = NULL;
Eina_Mempool *_mp_command_ector = NULL;
/*
*****
**
@ -3431,6 +3445,148 @@ eng_output_idle_flush(void *data)
if (re->outbuf_idle_flush) re->outbuf_idle_flush(re->ob);
}
static Ector_Surface *_software_ector = NULL;
static Ector_Surface *
eng_ector_get(void *data EINA_UNUSED)
{
if (!_software_ector)
{
_software_ector = eo_add(ECTOR_CAIRO_SOFTWARE_SURFACE_CLASS, NULL);
}
return _software_ector;
}
static Ector_Rop
_evas_render_op_to_ector_rop(Evas_Render_Op op)
{
switch (op)
{
case EVAS_RENDER_BLEND:
return ECTOR_ROP_BLEND;
case EVAS_RENDER_COPY:
return ECTOR_ROP_COPY;
default:
return ECTOR_ROP_BLEND;
}
}
static void
_draw_thread_ector_cleanup(Evas_Thread_Command_Ector *ector)
{
Eina_Rectangle *r;
while ((r = eina_array_pop(ector->clips)))
eina_rectangle_free(r);
eina_array_free(ector->clips);
eo_unref(ector->r);
if (ector->free_it)
eina_mempool_free(_mp_command_ector, ector);
}
static void
_draw_thread_ector_draw(void *data)
{
Evas_Thread_Command_Ector *ector = data;
RGBA_Image *surface = ector->surface;
void *pixels = evas_cache_image_pixels(&surface->cache_entry);
unsigned int w, h;
w = surface->cache_entry.w;
h = surface->cache_entry.h;
// FIXME: do not reset cairo context if not necessary
eo_do(_software_ector,
ector_cairo_software_surface_set(pixels, w, h));
eo_do(ector->r,
ector_renderer_draw(ector->render_op,
ector->clips,
ector->x,
ector->y,
ector->mul_col));
_draw_thread_ector_cleanup(ector);
}
static void
eng_ector_renderer_draw(void *data EINA_UNUSED, void *context, void *surface, Ector_Renderer *renderer, Eina_Array *clips, int x, int y, Eina_Bool do_async)
{
RGBA_Image *dst = surface;
RGBA_Draw_Context *dc = context;
Evas_Thread_Command_Ector ector;
Eina_Array *c;
Eina_Rectangle *r;
Eina_Rectangle clip;
Eina_Array_Iterator it;
unsigned int i;
if (dc->clip.use)
{
clip.x = dc->clip.x;
clip.y = dc->clip.y;
clip.w = dc->clip.w;
clip.h = dc->clip.h;
}
else
{
clip.x = 0;
clip.y = 0;
clip.w = dst->cache_entry.w;
clip.h = dst->cache_entry.h;
}
c = eina_array_new(8);
EINA_ARRAY_ITER_NEXT(clips, i, r, it)
{
Eina_Rectangle *rc;
rc = eina_rectangle_new(r->x, r->y, r->w, r->h);
if (!rc) continue;
if (eina_rectangle_intersection(rc, &clip))
eina_array_push(c, rc);
else
eina_rectangle_free(rc);
}
if (eina_array_count(c) == 0 &&
eina_array_count(clips) > 0)
return ;
if (eina_array_count(c) == 0)
eina_array_push(c, eina_rectangle_new(clip.x, clip.y, clip.w, clip.h));
ector.surface = surface;
ector.r = eo_ref(renderer);
ector.clips = c;
ector.render_op = _evas_render_op_to_ector_rop(dc->render_op);
ector.mul_col = dc->mul.use ? dc->mul.col : 0xffffffff;
ector.x = x;
ector.y = y;
ector.free_it = EINA_FALSE;
if (do_async)
{
Evas_Thread_Command_Ector *ne;
ne = eina_mempool_malloc(_mp_command_ector, sizeof (Evas_Thread_Command_Ector));
if (!ne)
{
_draw_thread_ector_cleanup(&ector);
return ;
}
memcpy(ne, &ector, sizeof (Evas_Thread_Command_Ector));
ne->free_it = EINA_TRUE;
evas_thread_cmd_enqueue(_draw_thread_ector_draw, ne);
}
else
{
_draw_thread_ector_draw(&ector);
}
}
//------------------------------------------------//
@ -3613,6 +3769,8 @@ static Evas_Func func =
NULL, // eng_texture_filter_set
NULL, // eng_texture_filter_get
NULL, // eng_texture_image_set
eng_ector_get,
eng_ector_renderer_draw
/* FUTURE software generic calls go here */
};
@ -4661,6 +4819,9 @@ module_open(Evas_Module *em)
_mp_command_multi_font =
eina_mempool_add("chained_mempool", "Evas_Thread_Command_Multi_Font",
NULL, sizeof(Evas_Thread_Command_Multi_Font), 128);
_mp_command_ector =
eina_mempool_add("chained_mempool", "Evas_Thread_Command_Ector",
NULL, sizeof(Evas_Thread_Command_Ector), 128);
init_gl();
evas_common_pipe_init();
@ -4679,6 +4840,7 @@ module_close(Evas_Module *em EINA_UNUSED)
eina_mempool_del(_mp_command_image);
eina_mempool_del(_mp_command_font);
eina_mempool_del(_mp_command_map);
eina_mempool_del(_mp_command_ector);
eina_log_domain_unregister(_evas_soft_gen_log_dom);
}
@ -4693,30 +4855,106 @@ static Evas_Module_Api evas_modapi =
}
};
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_generic);
Eina_Bool evas_engine_software_generic_init(void)
{
return evas_module_register(&evas_modapi, EVAS_MODULE_TYPE_ENGINE);
}
// Time to destroy the ector context
void evas_engine_software_generic_shutdown(void)
{
if (_software_ector) eo_del(_software_ector);
_software_ector = NULL;
evas_module_unregister(&evas_modapi, EVAS_MODULE_TYPE_ENGINE);
}
#ifndef EVAS_STATIC_BUILD_SOFTWARE_GENERIC
EVAS_EINA_MODULE_DEFINE(engine, software_generic);
#endif
#define USE(Obj, Sym, Error) \
if (!Sym) _ector_cairo_symbol_get(Obj, #Sym); \
if (!Sym) return Error;
static inline void *
_ector_cairo_symbol_get(Eo *ector_surface, const char *name)
{
void *sym;
eo_do(ector_surface,
sym = ector_cairo_surface_symbol_get(name));
return sym;
}
typedef struct _cairo_surface_t cairo_surface_t;
typedef enum {
CAIRO_FORMAT_INVALID = -1,
CAIRO_FORMAT_ARGB32 = 0,
CAIRO_FORMAT_RGB24 = 1,
CAIRO_FORMAT_A8 = 2,
CAIRO_FORMAT_A1 = 3,
CAIRO_FORMAT_RGB16_565 = 4,
CAIRO_FORMAT_RGB30 = 5
} cairo_format_t;
static cairo_surface_t *(*cairo_image_surface_create_for_data)(unsigned char *data,
cairo_format_t format,
int width,
int height,
int stride) = NULL;
static void (*cairo_surface_destroy)(cairo_surface_t *surface) = NULL;
static cairo_t *(*cairo_create)(cairo_surface_t *target) = NULL;
static void (*cairo_destroy)(cairo_t *cr) = NULL;
typedef struct _Ector_Cairo_Software_Surface_Data Ector_Cairo_Software_Surface_Data;
struct _Ector_Cairo_Software_Surface_Data
{
cairo_surface_t *surface;
cairo_t *ctx;
void *pixels;
unsigned int width;
unsigned int height;
};
void
_ector_cairo_software_surface_surface_set(Eo *obj, Ector_Cairo_Software_Surface_Data *pd, void *pixels, unsigned int width, unsigned int height)
{
USE(obj, cairo_image_surface_create_for_data, );
USE(obj, cairo_surface_destroy, );
USE(obj, cairo_create, );
USE(obj, cairo_destroy, );
cairo_surface_destroy(pd->surface); pd->surface = NULL;
cairo_destroy(pd->ctx); pd->ctx = NULL;
pd->pixels = NULL;
pd->width = 0;
pd->height = 0;
pd->surface = cairo_image_surface_create_for_data(pixels, CAIRO_FORMAT_ARGB32, width, height, width);
if (pd->surface) goto end;
pd->ctx = cairo_create(pd->surface);
if (pd->ctx)
{
pd->pixels = pixels;
pd->width = width;
pd->height = height;
}
end:
eo_do(obj, ector_cairo_surface_context_set(pd->ctx));
}
void
_ector_cairo_software_surface_surface_get(Eo *obj, Ector_Cairo_Software_Surface_Data *pd, void **pixels, unsigned int *width, unsigned int *height)
{
}
Eo *
_ector_cairo_software_surface_eo_base_finalize(Eo *obj, Ector_Cairo_Software_Surface_Data *pd)
_ector_cairo_software_surface_surface_get(Eo *obj EINA_UNUSED, Ector_Cairo_Software_Surface_Data *pd, void **pixels, unsigned int *width, unsigned int *height)
{
if (pixels) *pixels = pd->pixels;
if (width) *width = pd->width;
if (height) *height = pd->height;
}
#include "ector_cairo_software_surface.eo.c"