From 23c34b96d3fe25b75ab15e6ff6b2d0f7332c42e9 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Fri, 3 Apr 2015 16:30:44 +0200 Subject: [PATCH] evas: add theoric GL backend support. --- src/Makefile_Evas.am | 8 +- .../ector_cairo_software_surface.eo | 18 ++ .../evas/engines/gl_generic/evas_engine.c | 216 ++++++++++++++++++ 3 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index b5f42a52ac..34600fe7bf 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -519,7 +519,9 @@ lib/evas/filters/blur/blur_box_rgba_neon.c ### Engines if EVAS_STATIC_BUILD_SOFTWARE_GENERIC -evas_eolian_files += modules/evas/engines/software_generic/ector_cairo_software_surface.eo +BUILT_SOURCES += \ +modules/evas/engines/software_generic/ector_cairo_software_surface.eo.c \ +modules/evas/engines/software_generic/ector_cairo_software_surface.eo.h lib_evas_libevas_la_SOURCES += modules/evas/engines/software_generic/evas_engine.c modules/evas/engines/software_generic/Evas_Engine_Software_Generic.h lib_evas_libevas_la_LIBADD += else @@ -608,6 +610,10 @@ endif endif if BUILD_ENGINE_GL_COMMON +BUILT_SOURCES += \ +modules/evas/engines/gl_generic/ector_cairo_software_surface.eo.c \ +modules/evas/engines/gl_generic/ector_cairo_software_surface.eo.h + GL_COMMON_SOURCES = \ modules/evas/engines/gl_common/evas_gl_private.h \ modules/evas/engines/gl_common/evas_gl_common.h \ diff --git a/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo b/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo new file mode 100644 index 0000000000..d5070abccf --- /dev/null +++ b/src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo @@ -0,0 +1,18 @@ +class Ector.Cairo_Software.Surface (Ector.Cairo.Surface) +{ + eo_prefix: ector_cairo_software_surface; + legacy_prefix: null; + properties { + surface { + set { + } + get { + } + values { + void *pixels; + uint width; + uint height; + } + } + } +} diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index dac9232c5f..225a32b006 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -21,6 +21,10 @@ #include "evas_cs2_private.h" #endif +#include "cairo/Ector_Cairo.h" + +#include "ector_cairo_software_surface.eo.h" + #define EVAS_GL_NO_GL_H_CHECK 1 #include "Evas_GL.h" @@ -2087,6 +2091,127 @@ eng_texture_image_set(void *data EINA_UNUSED, void *texture, void *image) e3d_texture_import((E3D_Texture *)texture, im->tex->pt->texture); } +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 +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 EINA_UNUSED) +{ + Evas_GL_Image *dst = surface; + Evas_Engine_GL_Context *gc = context; + Eina_Rectangle *r; + Eina_Array *c; + Eina_Rectangle clip; + Eina_Array_Iterator it; + unsigned int i; + + if (gc->dc->clip.use) + { + clip.x = gc->dc->clip.x; + clip.y = gc->dc->clip.y; + clip.w = gc->dc->clip.w; + clip.h = gc->dc->clip.h; + } + else + { + clip.x = 0; + clip.y = 0; + clip.w = dst->w; + clip.h = dst->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)); + + eo_do(renderer, + ector_renderer_draw(_evas_render_op_to_ector_rop(gc->dc->render_op), + c, + x, + y, + // mul_col will be applied by GL during ector_end + 0xffffffff)); + + while ((r = eina_array_pop(c))) + eina_rectangle_free(r); + eina_array_free(c); +} + +static void *software_buffer = NULL; + +static void +eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, void *surface, Eina_Bool do_async EINA_UNUSED) +{ + Evas_GL_Image *dst = surface; + + software_buffer = realloc(software_buffer, sizeof (unsigned int) * dst->w * dst->h); + eo_do(_software_ector, + ector_cairo_software_surface_set(software_buffer, dst->w, dst->h)); +} + +static void +eng_ector_end(void *data, void *context, void *surface, Eina_Bool do_async) +{ + Evas_GL_Image *dst = surface; + Evas_GL_Image *im; + + eo_do(_software_ector, + ector_cairo_software_surface_set(NULL, 0, 0)); + + im = evas_gl_common_image_new_from_data(context, dst->w, dst->h, software_buffer, 1, EVAS_COLORSPACE_ARGB8888); + eng_image_draw(data, context, surface, im, + // We actually just bluntly push the pixel all over the + // destination surface. We don't have the actual information + // of the widget size. This is not a problem. + // Later on, we don't want that information and today when + // using GL backend, you just need to turn on Evas_Map on + // the Evas_Object_VG. + 0, 0, dst->w, dst->h, + 0, 0, dst->w, dst->h, 0, do_async); + + evas_common_rgba_image_free(software_buffer); + software_buffer = NULL; +} + static Evas_Func func, pfunc; static int @@ -2229,6 +2354,11 @@ module_open(Evas_Module *em) ORD(texture_filter_get); ORD(texture_image_set); + ORD(ector_get); + ORD(ector_begin); + ORD(ector_renderer_draw); + ORD(ector_end); + /* now advertise out own api */ em->functions = (void *)(&func); return 1; @@ -2257,3 +2387,89 @@ EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, gl_generic); #ifndef EVAS_STATIC_BUILD_GL_COMMON EVAS_EINA_MODULE_DEFINE(engine, gl_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; +}; + +static 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)); +} + +static void +_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"