From 8fb2dca520920432e76f8c1db0db5da515e070ce Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 19 Jul 2016 21:08:02 +0900 Subject: [PATCH] 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. --- .../evas/engines/gl_common/evas_gl_common.h | 15 +++ .../evas/engines/gl_generic/evas_engine.c | 126 ++++++++++++++++-- .../engines/software_generic/evas_engine.c | 20 +-- 3 files changed, 141 insertions(+), 20 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 92e968b7ad..c390e3370b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -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); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 6eab3848ff..3c88a868bf 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -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); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 628ae5ef52..314415caf3 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -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++; }