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).
This commit is contained in:
Jean-Philippe Andre 2016-01-04 20:33:37 +09:00
parent 0d5b42e6bb
commit 13f66f8887
2 changed files with 165 additions and 0 deletions

View File

@ -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)
{

View File

@ -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;
}
}