From 48d97f7a9022d53ae82b9fff34108508cd7be7e5 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 27 Jun 2013 16:18:40 +0900 Subject: [PATCH] evas/cserve2: use Evas loaders from slave Use common loaders with evas, and ignore specific modules. Signed-off-by: Cedric Bail --- src/bin/evas/evas_cserve2_slave.c | 410 +++++++++++++++++++++++++++++- src/bin/evas/evas_cserve2_slave.h | 2 + src/bin/evas/evas_cserve2_utils.c | 9 + 3 files changed, 414 insertions(+), 7 deletions(-) diff --git a/src/bin/evas/evas_cserve2_slave.c b/src/bin/evas/evas_cserve2_slave.c index e930876633..fcc9db9d5d 100644 --- a/src/bin/evas/evas_cserve2_slave.c +++ b/src/bin/evas/evas_cserve2_slave.c @@ -13,6 +13,10 @@ #include "evas_cserve2.h" #include "evas_cserve2_slave.h" +#define LK(x) Eina_Lock x +#include "file/evas_module.h" +#include "Evas_Loader.h" + static Eina_Hash *loaders = NULL; static Eina_List *modules = NULL; static Eina_Prefix *pfx = NULL; @@ -27,6 +31,8 @@ struct ext_loader_s #define MATCHING(Ext, Module) \ { sizeof (Ext), Ext, Module } +#if !USE_EVAS_MODULE_API + static const struct ext_loader_s map_loaders[] = { /* map extensions to loaders to use for good first-guess tries */ MATCHING(".png", "png"), @@ -61,6 +67,118 @@ static const char *loaders_name[] = "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd" }; +#else + +static const struct ext_loader_s map_loaders[] = +{ /* map extensions to loaders to use for good first-guess tries */ + MATCHING(".png", "png"), + MATCHING(".jpg", "jpeg"), + MATCHING(".jpeg", "jpeg"), + MATCHING(".jfif", "jpeg"), + MATCHING(".eet", "eet"), + MATCHING(".edj", "eet"), + MATCHING(".eap", "eet"), + MATCHING(".xpm", "xpm"), + MATCHING(".tiff", "tiff"), + MATCHING(".tif", "tiff"), + MATCHING(".svg", "svg"), + MATCHING(".svgz", "svg"), + MATCHING(".svg.gz", "svg"), + MATCHING(".gif", "gif"), + MATCHING(".pbm", "pmaps"), + MATCHING(".pgm", "pmaps"), + MATCHING(".ppm", "pmaps"), + MATCHING(".pnm", "pmaps"), + MATCHING(".bmp", "bmp"), + MATCHING(".tga", "tga"), + MATCHING(".wbmp", "wbmp"), + MATCHING(".webp", "webp"), + MATCHING(".ico", "ico"), + MATCHING(".cur", "ico"), + MATCHING(".psd", "psd"), + MATCHING(".pdf", "generic"), + MATCHING(".ps", "generic"), + MATCHING(".xcf", "generic"), + MATCHING(".xcf.gz", "generic"), + /* RAW */ + MATCHING(".arw", "generic"), + MATCHING(".cr2", "generic"), + MATCHING(".crw", "generic"), + MATCHING(".dcr", "generic"), + MATCHING(".dng", "generic"), + MATCHING(".k25", "generic"), + MATCHING(".kdc", "generic"), + MATCHING(".erf", "generic"), + MATCHING(".mrw", "generic"), + MATCHING(".nef", "generic"), + MATCHING(".nrf", "generic"), + MATCHING(".nrw", "generic"), + MATCHING(".orf", "generic"), + MATCHING(".raw", "generic"), + MATCHING(".rw2", "generic"), + MATCHING(".pef", "generic"), + MATCHING(".raf", "generic"), + MATCHING(".sr2", "generic"), + MATCHING(".srf", "generic"), + MATCHING(".x3f", "generic"), + /* video */ + MATCHING(".264", "generic"), + MATCHING(".3g2", "generic"), + MATCHING(".3gp", "generic"), + MATCHING(".3gp2", "generic"), + MATCHING(".3gpp", "generic"), + MATCHING(".3gpp2", "generic"), + MATCHING(".3p2", "generic"), + MATCHING(".asf", "generic"), + MATCHING(".avi", "generic"), + MATCHING(".bdm", "generic"), + MATCHING(".bdmv", "generic"), + MATCHING(".clpi", "generic"), + MATCHING(".clp", "generic"), + MATCHING(".fla", "generic"), + MATCHING(".flv", "generic"), + MATCHING(".m1v", "generic"), + MATCHING(".m2v", "generic"), + MATCHING(".m2t", "generic"), + MATCHING(".m4v", "generic"), + MATCHING(".mkv", "generic"), + MATCHING(".mov", "generic"), + MATCHING(".mp2", "generic"), + MATCHING(".mp2ts", "generic"), + MATCHING(".mp4", "generic"), + MATCHING(".mpe", "generic"), + MATCHING(".mpeg", "generic"), + MATCHING(".mpg", "generic"), + MATCHING(".mpl", "generic"), + MATCHING(".mpls", "generic"), + MATCHING(".mts", "generic"), + MATCHING(".mxf", "generic"), + MATCHING(".nut", "generic"), + MATCHING(".nuv", "generic"), + MATCHING(".ogg", "generic"), + MATCHING(".ogm", "generic"), + MATCHING(".ogv", "generic"), + MATCHING(".rm", "generic"), + MATCHING(".rmj", "generic"), + MATCHING(".rmm", "generic"), + MATCHING(".rms", "generic"), + MATCHING(".rmx", "generic"), + MATCHING(".rmvb", "generic"), + MATCHING(".swf", "generic"), + MATCHING(".ts", "generic"), + MATCHING(".weba", "generic"), + MATCHING(".webm", "generic"), + MATCHING(".wmv", "generic") +}; + +static const char *loaders_name[] = +{ /* in order of most likely needed */ + "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "generic" +}; + +#endif + + Eina_Bool evas_cserve2_loader_register(Evas_Loader_Module_Api *api) { @@ -76,6 +194,9 @@ evas_cserve2_loader_register(Evas_Loader_Module_Api *api) # define EVAS_MODULE_NAME_IMAGE_LOADER "module.so" #endif + +#if !USE_EVAS_MODULE_API + static Evas_Loader_Module_Api * loader_module_find(const char *type) { @@ -112,6 +233,8 @@ loader_module_find(const char *type) return NULL; } +#endif // Old API + static Eina_Bool command_read(int fd, Slave_Command *cmd, void **params) { @@ -212,6 +335,263 @@ _cserve2_shm_unmap(void *map, size_t length) munmap(map, length); } +#if USE_EVAS_MODULE_API + +static void * +_image_file_open(Eina_File *fd, const char *key, Image_Load_Opts *opts, + Evas_Module *module, Evas_Image_Property *property, + Evas_Image_Animated *animated, Evas_Image_Load_Func **pfuncs) +{ + int error = EVAS_LOAD_ERROR_NONE; + Evas_Image_Load_Opts load_opts; + void *loader_data = NULL; + Evas_Image_Load_Func *funcs = NULL; + + *pfuncs = NULL; + if (!evas_module_load(module)) + goto unload; + + funcs = module->functions; + if (!funcs) + goto unload; + + evas_module_use(module); + memset(animated, 0, sizeof (*animated)); + memset(&load_opts, 0, sizeof (load_opts)); + + if (opts) + { + load_opts.w = opts->w; + load_opts.h = opts->h; + load_opts.dpi = opts->dpi; + load_opts.region.x = opts->rx; + load_opts.region.y = opts->ry; + load_opts.region.w = opts->rw; + load_opts.region.h = opts->rh; + load_opts.orientation = opts->orientation; + load_opts.scale_down_by = opts->scale_down_by; + } + // Not set here: struct load_opts.scale_load + + loader_data = funcs->file_open(fd, key, &load_opts, animated, &error); + if (!loader_data || (error != EVAS_LOAD_ERROR_NONE)) + goto unload; + + if (!funcs->file_head(loader_data, property, &error)) + goto unload; + + if (error != EVAS_LOAD_ERROR_NONE) + goto unload; + + *pfuncs = funcs; + return loader_data; + +unload: + if (funcs && loader_data) + funcs->file_close(loader_data); + evas_module_unload(module); + + return NULL; +} + +static Eina_Bool +_image_file_header(Eina_File *fd, const char *key, Image_Load_Opts *opts, + Slave_Msg_Image_Opened *result, Evas_Module *module) +{ + Evas_Image_Property property; + Evas_Image_Animated animated; + Evas_Image_Load_Func *funcs; + void *loader_data; + + memset(&property, 0, sizeof (property)); + loader_data = _image_file_open(fd, key, opts, module, &property, &animated, &funcs); + if (!loader_data) + return EINA_FALSE; + + memset(result, 0, sizeof (*result)); + result->w = property.w; + result->h = property.h; + //result->degree = opts-> + result->scale = property.scale; + result->alpha = property.alpha; + result->rotated = property.rotated; + + result->animated = animated.animated; + if (result->animated) + { + result->frame_count = animated.frame_count; + result->loop_count = animated.loop_count; + result->loop_hint = animated.loop_hint; + } + result->has_loader_data = EINA_TRUE; + + // Not set here: (Why?) + //property.premul; + //property.alpha_sparse; + + // FIXME: We need to close as we this slave might not be used for data loading + funcs->file_close(loader_data); + return EINA_TRUE; +} + +static Error_Type +image_open(const char *file, const char *key, Image_Load_Opts *opts, + Slave_Msg_Image_Opened *result, const char **use_loader) +{ + Evas_Module *module; + Eina_File *fd; + const char *loader = NULL; + const int filelen = strlen(file); + unsigned int i; + Error_Type ret = CSERVE2_NONE; + + fd = eina_file_open(file, EINA_FALSE); + if (!fd) + { + return CSERVE2_DOES_NOT_EXIST; // FIXME: maybe check errno + } + + if (!*use_loader) + goto try_extension; + + loader = *use_loader; + module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); + if (module) + { + if (_image_file_header(fd, key, opts, result, module)) + goto success; + } + +try_extension: + loader = NULL; + for (i = 0; i < sizeof(map_loaders) / sizeof(map_loaders[0]); i++) + { + int extlen = strlen(map_loaders[i].extension); + if (extlen > filelen) continue; + if (!strcasecmp(map_loaders[i].extension, file + filelen - extlen)) + { + loader = map_loaders[i].loader; + break; + } + } + + if (loader) + { + module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); + if (_image_file_header(fd, key, opts, result, module)) + goto success; + loader = NULL; + module = NULL; + } + + // Try all known modules + for (i = 0; i < sizeof(loaders_name) / sizeof(loaders_name[0]); i++) + { + loader = loaders_name[i]; + module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); + if (!module) continue; + if (_image_file_header(fd, key, opts, result, module)) + goto success; + } + + ret = CSERVE2_UNKNOWN_FORMAT; + goto end; + +success: + ret = CSERVE2_NONE; + *use_loader = loader; + +#warning FIXME: Do we need to unload the module now? + evas_module_unload(module); + +end: + eina_file_close(fd); + return ret; +} + +static Error_Type +image_load(const char *file, const char *key, const char *shmfile, + Slave_Msg_Image_Load *params, Slave_Msg_Image_Loaded *result, + const char *loader) +{ + Evas_Module *module; + Eina_File *fd; + Evas_Image_Load_Func *funcs = NULL; + Image_Load_Opts *opts = ¶ms->opts; + Evas_Image_Property property; + Evas_Image_Animated animated; + Error_Type ret = CSERVE2_GENERIC; + void *loader_data = NULL; + Eina_Bool ok; + int error; + + fd = eina_file_open(file, EINA_FALSE); + if (!fd) + { + return CSERVE2_DOES_NOT_EXIST; // FIXME: maybe check errno + } + + char *map = _cserve2_shm_map(shmfile, params->shm.mmap_size, + params->shm.mmap_offset); + if (map == MAP_FAILED) + { + eina_file_close(fd); + return CSERVE2_RESOURCE_ALLOCATION_FAILED; + } + + module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); + if (!module) + { + printf("LOAD failed at %s:%d: no module found for loader %s\n", + __FUNCTION__, __LINE__, loader); + goto done; + } + + memset(&property, 0, sizeof (property)); + property.w = params->w; + property.h = params->h; + + loader_data = _image_file_open(fd, key, opts, module, &property, &animated, &funcs); + if (!loader_data) + { + printf("LOAD failed at %s:%d: could not open image %s:%s\n", + __FUNCTION__, __LINE__, file, key); + goto done; + } + + ok = funcs->file_data(loader_data, &property, map, &error); + if (!ok || (error != EVAS_LOAD_ERROR_NONE)) + { + printf("LOAD failed at %s:%d: file_data failed for loader %s: error %d\n", + __FUNCTION__, __LINE__, loader, error); + goto done; + } + + result->w = property.w; + result->h = property.h; + + if (property.alpha) + { + result->alpha_sparse = evas_cserve2_image_premul_data((unsigned int *) map, + result->w * result->h); + } + + //printf("LOAD successful: %dx%d alpha_sparse %d\n", + // result->w, result->h, result->alpha_sparse); + + ret = CSERVE2_NONE; + +done: + eina_file_close(fd); + _cserve2_shm_unmap(map, params->shm.mmap_size); + if (funcs) + evas_module_unload(module); + + return ret; +} + +#else // Old cserve2 API + static Error_Type image_open(const char *file, const char *key, Image_Load_Opts *opts, Slave_Msg_Image_Opened *result, const char **use_loader) { @@ -355,11 +735,15 @@ image_load(const char *file, const char *key, const char *shmfile, Slave_Msg_Ima result->h = params->h; result->alpha_sparse = ilp.alpha_sparse; + //printf("LOAD successful: %dx%d alpha_sparse %d\n", + // result->w, result->h, result->alpha_sparse); + done: _cserve2_shm_unmap(map, params->shm.mmap_size); return ret; } +#endif static void handle_image_open(int wfd, void *params) @@ -388,6 +772,7 @@ handle_image_open(int wfd, void *params) if ((err = image_open(file, key, load_opts, &result, &loader)) != CSERVE2_NONE) { + printf("OPEN failed at %s:%d\n", __FUNCTION__, __LINE__); error_send(wfd, err); return; } @@ -412,6 +797,7 @@ handle_image_load(int wfd, void *params) if (!load_args->has_loader_data) { + printf("LOAD failed at %s:%d: no loader data\n", __FUNCTION__, __LINE__); error_send(wfd, CSERVE2_UNKNOWN_FORMAT); return; } @@ -425,6 +811,8 @@ handle_image_load(int wfd, void *params) if ((err = image_load(file, key, shmfile, load_args, &resp, loader)) != CSERVE2_NONE) { + printf("LOAD failed at %s:%d: load failed with error %d\n", + __FUNCTION__, __LINE__, err); error_send(wfd, err); return; } @@ -453,6 +841,10 @@ int main(int c, char **v) loaders = eina_hash_string_superfast_new(NULL); +#if USE_EVAS_MODULE_API + evas_module_init(); +#endif + wfd = atoi(v[1]); rfd = atoi(v[2]); @@ -466,19 +858,23 @@ int main(int c, char **v) switch (cmd) { case IMAGE_OPEN: - handle_image_open(wfd, params); - break; + handle_image_open(wfd, params); + break; case IMAGE_LOAD: - handle_image_load(wfd, params); - break; + handle_image_load(wfd, params); + break; case SLAVE_QUIT: - quit = EINA_TRUE; - break; + quit = EINA_TRUE; + break; default: - error_send(wfd, CSERVE2_INVALID_COMMAND); + error_send(wfd, CSERVE2_INVALID_COMMAND); } } +#if USE_EVAS_MODULE_API + evas_module_shutdown(); +#endif + eina_hash_free(loaders); EINA_LIST_FREE(modules, m) diff --git a/src/bin/evas/evas_cserve2_slave.h b/src/bin/evas/evas_cserve2_slave.h index de846e9442..9215d0bb98 100644 --- a/src/bin/evas/evas_cserve2_slave.h +++ b/src/bin/evas/evas_cserve2_slave.h @@ -48,6 +48,7 @@ typedef unsigned char DATA8; typedef struct _Evas_Loader_Module_Api Evas_Loader_Module_Api; typedef struct _Evas_Img_Load_Params Evas_Img_Load_Params; +#define USE_EVAS_MODULE_API 1 ///< Use common evas loaders. TEMPORARY DEFINE. #define EVAS_CSERVE2_MODULE_API_VERSION 1 struct _Evas_Loader_Module_Api { int version; @@ -80,6 +81,7 @@ struct _Evas_Img_Load_Params { EAPI Eina_Bool evas_cserve2_loader_register(Evas_Loader_Module_Api *api); +Eina_Bool evas_cserve2_image_premul_data(unsigned int *data, unsigned int len); EAPI void evas_cserve2_image_premul(Evas_Img_Load_Params *ilp); EAPI void evas_cserve2_image_alpha_sparse_set(Evas_Img_Load_Params *ilp); diff --git a/src/bin/evas/evas_cserve2_utils.c b/src/bin/evas/evas_cserve2_utils.c index 68fa216e19..f606974f3a 100644 --- a/src/bin/evas/evas_cserve2_utils.c +++ b/src/bin/evas/evas_cserve2_utils.c @@ -22,6 +22,15 @@ evas_cserve2_convert_argb_premul(unsigned int *data, unsigned int len) return nas; } +Eina_Bool +evas_cserve2_image_premul_data(unsigned int *data, unsigned int len) +{ + unsigned int nas; + + nas = evas_cserve2_convert_argb_premul(data, len); + return ((ALPHA_SPARSE_INV_FRACTION * nas) >= len); +} + EAPI void evas_cserve2_image_premul(Evas_Img_Load_Params *ilp) {