evas: add theoric GL backend support.
authorCedric BAIL <cedric@osg.samsung.com>
Fri, 3 Apr 2015 14:30:44 +0000 (16:30 +0200)
committerCedric BAIL <cedric@osg.samsung.com>
Fri, 3 Apr 2015 14:30:44 +0000 (16:30 +0200)
src/Makefile_Evas.am
src/modules/evas/engines/gl_generic/ector_cairo_software_surface.eo [new file with mode: 0644]
src/modules/evas/engines/gl_generic/evas_engine.c

index b5f42a52ace89597acb449e37aab0607f8d0be49..34600fe7bfdc0c594efb91d03486005840530325 100644 (file)
@@ -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 (file)
index 0000000..d5070ab
--- /dev/null
@@ -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;
+        }
+      }
+   }
+}
index dac9232c5f9c28b1a1c0a5ed4981d15159af861a..225a32b006e0159b5fa5a72a822d09ae99a13e68 100644 (file)
 #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"