#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"
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
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;
#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"