evas: Implement GL map/unmap for the simple case

Most of the code relies on the software generic engine
implementation, using inheritance between engines.

This fixes expedite image map RGBA test.
This commit is contained in:
Jean-Philippe Andre 2016-07-19 21:08:02 +09:00
parent 471a328ea0
commit 8fb2dca520
3 changed files with 141 additions and 20 deletions

View File

@ -68,6 +68,7 @@ typedef struct _Evas_GL_Font_Texture Evas_GL_Font_Texture;
typedef struct _Evas_GL_Polygon Evas_GL_Polygon;
typedef struct _Evas_GL_Polygon_Point Evas_GL_Polygon_Point;
typedef struct _Evas_GL_Texture_Async_Preload Evas_GL_Texture_Async_Preload;
typedef struct _Evas_GL_Image_Data_Map Evas_GL_Image_Data_Map;
typedef Eina_Bool (*evas_gl_make_current_cb)(void *engine_data, void *doit);
@ -449,6 +450,8 @@ struct _Evas_GL_Image
Eina_List *targets;
Evas_Image_Orient orient;
Eina_Inlist *maps; /* Evas_GL_Image_Data_Map */
unsigned char dirty : 1;
unsigned char cached : 1;
unsigned char alpha : 1;
@ -483,6 +486,18 @@ struct _Evas_GL_Texture_Async_Preload
Eina_Bool unpack_row_length;
};
struct _Evas_GL_Image_Data_Map
{
EINA_INLIST;
Evas_GL_Texture *tex; // one or the other
RGBA_Image *im; // one or the other
unsigned char *ptr;
int size, stride; // in bytes
int rx, ry, rw, rh; // actual map region
Evas_Colorspace cspace;
Efl_Gfx_Buffer_Access_Mode mode;
};
/* GL_Common function that are used by gl_generic inherited module */
EAPI void evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc);
EAPI void evas_gl_common_image_ref(Evas_GL_Image *im);

View File

@ -59,6 +59,8 @@ static Eina_Bool eng_gl_surface_read_pixels(void *data, void *surface, int x, in
Eina_Bool _need_context_restore = EINA_FALSE;
static Evas_Func func, pfunc;
void
_context_restore(void)
{
@ -1648,17 +1650,17 @@ eng_gl_proc_address_get(void *data, const char *name)
{
Render_Engine_GL_Generic *re = data;
EVGLINIT(re, NULL);
void *func = NULL;
void *fun = NULL;
if (!evgl_safe_extension_get(name, &func))
if (!evgl_safe_extension_get(name, &fun))
{
DBG("The extension '%s' is not safe to use with Evas GL or is not "
"supported on this platform.", name);
return NULL;
}
if (func)
return func;
if (fun)
return fun;
if (re->evgl_funcs && re->evgl_funcs->proc_address_get)
return re->evgl_funcs->proc_address_get(name);
@ -2792,7 +2794,112 @@ eng_ector_end(void *data, void *context EINA_UNUSED, Ector_Surface *ector,
}
}
static Evas_Func func, pfunc;
static void *
eng_image_data_map(void *engdata EINA_UNUSED, void **image,
int *length, int *stride,
int x, int y, int w, int h,
Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode)
{
Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE;
Evas_GL_Image_Data_Map *map = NULL;
Evas_GL_Image *im;
void *ret;
EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image, NULL);
im = *image;
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_COW)
cow = EINA_TRUE;
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
to_write = EINA_TRUE;
if (im->im)
{
int len = 0, strid = 0;
// Call sw generic implementation. Should work for simple cases.
ret = pfunc.image_data_map(NULL, (void **) &im->im, &len, &strid,
x, y, w, h, cspace, mode);
if (ret)
{
map = calloc(1, sizeof(*map));
map->cspace = cspace;
map->rx = x;
map->ry = y;
map->rw = w;
map->rh = h;
map->mode = mode;
map->size = len;
map->stride = strid;
map->im = im->im; // ref?
map->ptr = ret;
im->maps = eina_inlist_prepend(im->maps, EINA_INLIST_GET(map));
}
if (length) *length = len;
if (stride) *stride = strid;
return ret;
}
// TODO: glReadPixels from FBO if possible
return NULL;
}
static Eina_Bool
eng_image_data_unmap(void *engdata EINA_UNUSED, void *image, void *memory, int length)
{
Evas_GL_Image_Data_Map *map;
Evas_GL_Image *im = image;
Eina_Bool found = EINA_FALSE;
if (!im || !memory)
return EINA_FALSE;
EINA_INLIST_FOREACH(im->maps, map)
{
if ((map->ptr == memory) && (map->size == length))
{
found = EINA_TRUE;
if (map->im)
found = pfunc.image_data_unmap(NULL, map->im, memory, length);
if (found)
{
if (im->im && im->tex &&
(map->mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE))
evas_gl_common_texture_update(im->tex, im->im);
im->maps = eina_inlist_remove(im->maps, EINA_INLIST_GET(map));
free(map);
}
return found;
}
}
ERR("failed to unmap region %p (%u bytes)", memory, length);
return EINA_FALSE;
}
static int
eng_image_data_maps_get(void *engdata EINA_UNUSED, const void *image, void **maps, int *lengths)
{
Evas_GL_Image_Data_Map *map;
const Evas_GL_Image *im = image;
int k = 0;
if (!im) return -1;
if (!maps || !lengths)
return eina_inlist_count(im->maps);
EINA_INLIST_FOREACH(im->maps, map)
{
maps[k] = map->ptr;
lengths[k] = map->size;
k++;
}
return k;
}
static int
module_open(Evas_Module *em)
@ -2809,11 +2916,6 @@ module_open(Evas_Module *em)
return 0;
}
/* disable map/unmap for now as it's not implemented */
pfunc.image_data_map = NULL;
pfunc.image_data_unmap = NULL;
pfunc.image_data_maps_get = NULL;
ector_init();
ector_glsym_set(dlsym, RTLD_DEFAULT);
@ -2879,6 +2981,10 @@ module_open(Evas_Module *em)
ORD(image_cache_set);
ORD(image_cache_get);
ORD(image_data_map);
ORD(image_data_unmap);
ORD(image_data_maps_get);
ORD(font_cache_flush);
ORD(font_cache_set);
ORD(font_cache_get);

View File

@ -1461,12 +1461,14 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image,
{
Eina_Bool cow = EINA_FALSE, to_write = EINA_FALSE;
RGBA_Image_Data_Map *map;
RGBA_Image *im = *image;
Image_Entry *ie = &im->cache_entry;
RGBA_Image *im;
Image_Entry *ie;
int src_stride, src_offset;
void *data;
EINA_SAFETY_ON_FALSE_RETURN_VAL(image && *image, NULL);
im = *image;
ie = &im->cache_entry;
// FIXME: implement planes support (YUV, RGB565, ETC1+Alpha)
// FIXME: implement YUV support (im->cs.data)
@ -1711,18 +1713,16 @@ eng_image_data_unmap(void *engdata EINA_UNUSED, void *image, void *memory, int l
im->maps = (RGBA_Image_Data_Map *)
eina_inlist_remove(EINA_INLIST_GET(im->maps), EINA_INLIST_GET(map));
free(map);
break;
return EINA_TRUE;
}
}
if (!found)
ERR("failed to unmap region %p (%u bytes)", memory, length);
return found;
ERR("failed to unmap region %p (%u bytes)", memory, length);
return EINA_FALSE;
}
static int
eng_image_data_maps_get(void *engdata EINA_UNUSED, const void *image, void **maps, int *lenghts)
eng_image_data_maps_get(void *engdata EINA_UNUSED, const void *image, void **maps, int *lengths)
{
RGBA_Image_Data_Map *map;
const RGBA_Image *im = image;
@ -1730,13 +1730,13 @@ eng_image_data_maps_get(void *engdata EINA_UNUSED, const void *image, void **map
if (!im) return -1;
if (!maps || !lenghts)
if (!maps || !lengths)
return eina_inlist_count(EINA_INLIST_GET(im->maps));
EINA_INLIST_FOREACH(EINA_INLIST_GET(im->maps), map)
{
maps[k] = map->ptr;
lenghts[k] = map->size;
lengths[k] = map->size;
k++;
}