From 13f66f8887b3f7f63be26c6ec55cebd6ca7bd1bd Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 4 Jan 2016 20:33:37 +0900 Subject: [PATCH] Evas filters: Complete basic repairs for GL engine Now the filters should work with the GL engine, again, but with a potentially crazy performance. Indeed, the input buffer is now backed by an FBO, that needs to be glReadPixel'ed everytime it is accessed by the filters (mapped). --- .../gl_generic/evas_ector_gl_image_buffer.c | 160 +++++++++++++++++++++ .../gl_generic/evas_ector_gl_image_buffer.eo | 5 + 2 files changed, 165 insertions(+) diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c index c8de1d8..2b5b644 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c @@ -17,16 +17,54 @@ #define MY_CLASS EVAS_ECTOR_GL_IMAGE_BUFFER_CLASS +typedef struct _Ector_GL_Buffer_Map +{ + EINA_INLIST; + void *ptr; + unsigned int size; // in bytes + unsigned int x, y, w, h; + Efl_Gfx_Colorspace cspace; + Evas_GL_Image *im; + Eina_Bool allocated; + Ector_Buffer_Access_Flag mode; +} Ector_GL_Buffer_Map; + typedef struct { Ector_GL_Buffer_Base_Data *base; Evas *evas; Evas_GL_Image *image; + struct { + Eina_Inlist *maps; // Ector_GL_Buffer_Map + } internal; } Evas_Ector_GL_Image_Buffer_Data; #define ENFN e->engine.func #define ENDT e->engine.data.output +/* FIXME: Conversion routines don't belong here */ +static inline void +_pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len) +{ + int k; + for (k = 0; k < len; k++) + { + const uint32_t *s = src++; + *dst++ = A_VAL(s); + } +} + +static inline void +_pixels_gry8_to_argb_convert(uint32_t *dst, const uint8_t *src, int len) +{ + int k; + for (k = 0; k < len; k++) + { + uint8_t s = *src++; + *dst++ = ARGB_JOIN(s, s, s, s); + } +} + EOLIAN static void _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, Evas *evas, void *image) @@ -86,6 +124,128 @@ _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_get(Eo *obj EINA_UNUS if (image) *image = pd->image; } +EOLIAN static Ector_Buffer_Flag +_evas_ector_gl_image_buffer_ector_generic_buffer_flags_get(Eo *obj EINA_UNUSED, + Evas_Ector_GL_Image_Buffer_Data *pd) +{ + Ector_Buffer_Flag flags; + + if (!pd->image) return 0; + + flags = ECTOR_BUFFER_FLAG_CPU_READABLE; + if (pd->image->tex) + { + flags |= ECTOR_BUFFER_FLAG_DRAWABLE; + if (pd->image->tex->pt->fb) + flags |= ECTOR_BUFFER_FLAG_RENDERABLE; + } + if (pd->image->im) + flags |= ECTOR_BUFFER_FLAG_CPU_WRITABLE; + + return flags; +} + +EOLIAN static void * +_evas_ector_gl_image_buffer_ector_generic_buffer_map(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd, unsigned int *length, + Ector_Buffer_Access_Flag mode, + unsigned int x, unsigned int y, unsigned int w, unsigned int h, + Efl_Gfx_Colorspace cspace, unsigned int *stride) +{ + Evas_Public_Data *e = eo_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); + Ector_GL_Buffer_Map *map = NULL; + Eina_Bool tofree = EINA_FALSE; + Evas_GL_Image *im; + uint32_t *data; + int len, err; + + im = ENFN->image_data_get(ENDT, pd->image, + mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE, + &data, &err, &tofree); + if (!im) return NULL; + + map = calloc(1, sizeof(*map)); + map->mode = mode; + map->cspace = cspace; + map->x = x; + map->y = y; + map->w = w; + map->h = h; + map->ptr = data; + + if (tofree) + map->im = im; + else + map->im = ENFN->image_ref(ENDT, im); + + len = w * h; + if (cspace == EFL_GFX_COLORSPACE_GRY8) + { + uint8_t *data8 = malloc(len); + _pixels_argb_to_gry8_convert(data8, data, len); + map->allocated = EINA_TRUE; + map->ptr = data8; + map->size = len; + if (stride) *stride = w; + } + else + { + map->allocated = EINA_FALSE; + map->ptr = data; + map->size = len * 4; + if (stride) *stride = w * 4; + } + + if (length) *length = map->size; + + pd->internal.maps = eina_inlist_prepend(pd->internal.maps, EINA_INLIST_GET(map)); + return map->ptr; +} + +EOLIAN static void +_evas_ector_gl_image_buffer_ector_generic_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd, + void *data, unsigned int length) +{ + Evas_Public_Data *e = eo_data_scope_get(pd->evas, EVAS_CANVAS_CLASS); + Ector_GL_Buffer_Map *map; + if (!data) return; + + EINA_INLIST_FOREACH(pd->internal.maps, map) + { + if ((map->ptr == data) && ((map->size == length) || (length == (unsigned int) -1))) + { + pd->internal.maps = eina_inlist_remove(pd->internal.maps, EINA_INLIST_GET(map)); + if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) + { + CRI("Not implemented yet. Dropping pixel changes."); + } + ENFN->image_free(ENDT, map->im); + if (map->allocated) + free(map->ptr); + return; + } + } + + CRI("Tried to unmap a non-mapped region!"); +} + +EOLIAN static uint8_t * +_evas_ector_gl_image_buffer_ector_generic_buffer_span_get(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, int x, int y, unsigned int w, + Efl_Gfx_Colorspace cspace, unsigned int *length) +{ + // ector_buffer_map + return _evas_ector_gl_image_buffer_ector_generic_buffer_map + (obj, pd, length, ECTOR_BUFFER_ACCESS_FLAG_READ, x, y, w, 1, cspace, NULL); +} + +EOLIAN static void +_evas_ector_gl_image_buffer_ector_generic_buffer_span_free(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, uint8_t *data) +{ + // ector_buffer_unmap + return _evas_ector_gl_image_buffer_ector_generic_buffer_unmap + (obj, pd, data, (unsigned int) -1); +} + + EOLIAN static Eo_Base * _evas_ector_gl_image_buffer_eo_base_constructor(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd) { diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo index 82cebb4..2eede45 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.eo @@ -8,5 +8,10 @@ class Evas.Ector.GL.Image.Buffer (Evas.Ector.GL.Buffer, Evas.Ector.Buffer) Eo.Base.destructor; Evas.Ector.Buffer.engine_image.set; Evas.Ector.Buffer.engine_image.get; + Ector.Generic.Buffer.flags.get; + Ector.Generic.Buffer.span_get; + Ector.Generic.Buffer.span_free; + Ector.Generic.Buffer.map; + Ector.Generic.Buffer.unmap; } } -- 2.7.4