diff --git a/ChangeLog b/ChangeLog index a83354ffd1..f7b2f30897 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2012-11-22 Paulo Alcantara (pcacjr) + * Add scalecache support to Cserve2 + 2012-11-22 Sung W. Park (sung_) * Fixed a bug where if an image object rendered using Evas GL diff --git a/NEWS b/NEWS index f35cd73752..292adefad0 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ Additions: * Add eina_tmpstr_add() and eina_tmpstr_del() * Add eina_thread API * Add eina_list_last_data_get + * Add Cserve2 scalecache support Improvements: * Single EFL tree covering all EFL library components. diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index dbb66a091f..616c466b4e 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -1727,6 +1727,7 @@ bin/evas/evas_cserve2_shm.c \ bin/evas/evas_cserve2_cache.c \ bin/evas/evas_cserve2_requests.c \ bin/evas/evas_cserve2_fonts.c \ +bin/evas/evas_cserve2_scale.c \ bin/evas/evas_cserve2_main_loop_linux.c \ lib/evas/cserve2/evas_cs2_utils.h \ lib/evas/cserve2/evas_cs2_utils.c diff --git a/src/bin/evas/evas_cserve2.h b/src/bin/evas/evas_cserve2.h index 35603873be..af21ccab50 100644 --- a/src/bin/evas/evas_cserve2.h +++ b/src/bin/evas/evas_cserve2.h @@ -109,6 +109,7 @@ struct _Slave_Msg_Image_Load { }; struct _Slave_Msg_Image_Loaded { + int w, h; Eina_Bool alpha_sparse : 1; }; @@ -275,6 +276,9 @@ size_t cserve2_shm_size_normalize(size_t size); void cserve2_command_run(Client *client, Message_Type type); +void cserve2_scale_init(void); +void cserve2_scale_shutdown(void); + void cserve2_cache_init(void); void cserve2_cache_shutdown(void); void cserve2_cache_client_new(Client *client); @@ -282,6 +286,7 @@ void cserve2_cache_client_del(Client *client); int cserve2_cache_file_open(Client *client, unsigned int client_file_id, const char *path, const char *key, unsigned int rid); void cserve2_cache_file_close(Client *client, unsigned int client_file_id); int cserve2_cache_image_opts_set(Client *client, Msg_Setopts *msg); +void cserve2_rgba_image_scale_do(void *src_data, void *dst_data, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int alpha, int smooth); void cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned int rid); void cserve2_cache_image_preload(Client *client, unsigned int client_image_id, unsigned int rid); void cserve2_cache_image_unload(Client *client, unsigned int client_image_id); diff --git a/src/bin/evas/evas_cserve2_cache.c b/src/bin/evas/evas_cserve2_cache.c index 6ae8a42a6c..97c94440bc 100644 --- a/src/bin/evas/evas_cserve2_cache.c +++ b/src/bin/evas/evas_cserve2_cache.c @@ -3,6 +3,7 @@ #endif #include +#include #ifdef DEBUG_LOAD_TIME #include @@ -65,6 +66,10 @@ struct _Image_Data { int w, h; // w and h < -1 int scale_down; // scale_down < -1 int rx, ry, rw, rh; // rx, ry, rw, rh < -1 + int scale_src_x, scale_src_y, scale_src_w, scale_src_h; + int scale_dst_w, scale_dst_h; + int scale_smooth; + int scale_hint; Eina_Bool orientation; // orientation == 0 } opts; Shm_Handle *shm; @@ -179,7 +184,7 @@ static Eina_List *image_entries_lru = NULL; static Eina_List *font_shm_lru = NULL; -static int max_unused_mem_usage = 5 * 1024; /* in kbytes */ +static int max_unused_mem_usage = 5 * 4 * 1024; /* in kbytes */ static int unused_mem_usage = 0; static int max_font_usage = 10 * 4 * 1024; /* in kbytes */ static int font_mem_usage = 0; @@ -474,6 +479,78 @@ _load_request_build(Image_Data *i, int *bufsize) return buf; } +static inline Eina_Bool +_scaling_needed(Image_Data *entry, Slave_Msg_Image_Loaded *resp) +{ + return (((entry->opts.scale_dst_w) && (entry->opts.scale_dst_h)) && + ((entry->opts.scale_dst_w != resp->w) || + (entry->opts.scale_dst_h != resp->h))); +} + +static int +_scaling_do(Shm_Handle *scale_shm, Image_Data *entry) +{ + char *scale_map, *orig_map; + void *src_data, *dst_data; + + scale_map = cserve2_shm_map(scale_shm); + if (scale_map == MAP_FAILED) + { + ERR("Failed to memory map file for scale image."); + return -1; + } + + orig_map = cserve2_shm_map(entry->shm); + if (orig_map == MAP_FAILED) + { + ERR("Failed to memory map file for original image."); + + cserve2_shm_unmap(scale_shm); + return -1; + } + + src_data = orig_map + cserve2_shm_map_offset_get(entry->shm); + dst_data = scale_map + cserve2_shm_map_offset_get(scale_shm); + + DBG("Scaling image ([%d,%d:%dx%d] --> [%d,%d:%dx%d])", + entry->opts.scale_src_x, entry->opts.scale_src_y, + entry->opts.scale_src_w, entry->opts.scale_src_h, + 0, 0, + entry->opts.scale_dst_w, entry->opts.scale_dst_h); + + cserve2_rgba_image_scale_do(src_data, dst_data, + entry->opts.scale_src_x, entry->opts.scale_src_y, + entry->opts.scale_src_w, entry->opts.scale_src_h, + 0, 0, + entry->opts.scale_dst_w, entry->opts.scale_dst_h, + entry->file->alpha, entry->opts.scale_smooth); + + cserve2_shm_unmap(entry->shm); + cserve2_shm_unmap(scale_shm); + + return 0; +} + +static int +_scaling_prepare_and_do(Image_Data *orig) +{ + Shm_Handle *scale_shm; + + DBG("Original image's shm path %s", cserve2_shm_name_get(orig->shm)); + + scale_shm = + cserve2_shm_request(orig->opts.scale_dst_w * orig->opts.scale_dst_h * 4); + + DBG("Scale image's shm path %s", cserve2_shm_name_get(scale_shm)); + + if (_scaling_do(scale_shm, orig)) return -1; + + cserve2_shm_unref(orig->shm); /* unreference old shm */ + orig->shm = scale_shm; /* update shm */ + + return 0; +} + static Msg_Loaded * _load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size) { @@ -485,6 +562,20 @@ _load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size) if (!e->doload) DBG("Entry %d loaded by speculative preload.", e->base.id); + if (_scaling_needed(e, resp)) + { + DBG("About to scale down image '%s%s'", e->file->path, e->file->key); + + if (!_scaling_prepare_and_do(e)) + DBG("Image '%s:%s' has been scaled down.", + e->file->path, e->file->key); + else + ERR("Failed to scale down image '%s%s'", + e->file->path, e->file->key); + } + else + DBG("No scaling needed for image '%s%s'", e->file->path, e->file->key); + return _image_loaded_msg_create(e, size); } @@ -500,10 +591,15 @@ _img_opts_id_get(Image_Data *im, char *buf, int size) { uintptr_t image_id; - snprintf(buf, size, "%u:%0.3f:%dx%d:%d:%d,%d+%dx%d:%d", + snprintf(buf, size, + "%u:%0.3f:%dx%d:%d:%d,%d+%dx%d:!([%d,%d:%dx%d]-[%dx%d:%d]):%d", im->file_id, im->opts.dpi, im->opts.w, im->opts.h, im->opts.scale_down, im->opts.rx, im->opts.ry, - im->opts.rw, im->opts.rh, im->opts.orientation); + im->opts.rw, im->opts.rh, + im->opts.scale_src_x, im->opts.scale_src_y, + im->opts.scale_src_w, im->opts.scale_src_h, + im->opts.scale_dst_w, im->opts.scale_dst_h, im->opts.scale_smooth, + im->opts.orientation); image_id = (uintptr_t)eina_hash_find(image_ids, buf); @@ -972,6 +1068,14 @@ _image_msg_new(Client *client, Msg_Setopts *msg) im_entry->opts.ry = msg->opts.ry; im_entry->opts.rw = msg->opts.rw; im_entry->opts.rh = msg->opts.rh; + im_entry->opts.scale_src_x = msg->opts.scale_src_x; + im_entry->opts.scale_src_y = msg->opts.scale_src_y; + im_entry->opts.scale_src_w = msg->opts.scale_src_w; + im_entry->opts.scale_src_h = msg->opts.scale_src_h; + im_entry->opts.scale_dst_w = msg->opts.scale_dst_w; + im_entry->opts.scale_dst_h = msg->opts.scale_dst_h; + im_entry->opts.scale_smooth = msg->opts.scale_smooth; + im_entry->opts.scale_hint = msg->opts.scale_hint; im_entry->opts.orientation = msg->opts.orientation; return im_entry; @@ -2034,9 +2138,10 @@ cserve2_cache_image_opts_set(Client *client, Msg_Setopts *msg) fentry = entry->file; fentry->images = eina_list_append(fentry->images, entry); - entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD, - 0, NULL, fentry->base.request, - &_load_funcs, entry); + if ((!entry->opts.scale_dst_w) && (!entry->opts.scale_dst_h)) + entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD, + 0, NULL, fentry->base.request, + &_load_funcs, entry); return 0; } diff --git a/src/bin/evas/evas_cserve2_client.c b/src/bin/evas/evas_cserve2_client.c index 5ced01764e..14a6cff9eb 100644 --- a/src/bin/evas/evas_cserve2_client.c +++ b/src/bin/evas/evas_cserve2_client.c @@ -101,6 +101,10 @@ parse_input_setopts(int *size) int w, h; int scale; int rx, ry, rw, rh; + int scale_src_x, scale_src_y, scale_src_w, scale_src_h; + int scale_dst_w, scale_dst_h; + int scale_smooth; + int scale_hint; int orientation; // reading file_id, image_id @@ -123,11 +127,30 @@ parse_input_setopts(int *size) _read_line(line, sizeof(line)); sscanf(line, "%d %d %d %d", &rx, &ry, &rw, &rh); + // reading original image's source coord + _read_line(line, sizeof(line)); + sscanf(line, "%d %d", &scale_src_x, &scale_src_y); + + // reading original size + _read_line(line, sizeof(line)); + sscanf(line, "%d %d", &scale_src_w, &scale_src_h); + + // reading scale size + _read_line(line, sizeof(line)); + sscanf(line, "%d %d", &scale_dst_w, &scale_dst_h); + + // reading scale smooth + _read_line(line, sizeof(line)); + sscanf(line, "%d", &scale_smooth); + + // reading scale hint + _read_line(line, sizeof(line)); + sscanf(line, "%d", &scale_hint); + // reading orientation _read_line(line, sizeof(line)); sscanf(line, "%d", &orientation); - msg = calloc(1, sizeof(*msg)); msg->base.rid = _rid_count++; @@ -142,6 +165,14 @@ parse_input_setopts(int *size) msg->opts.ry = ry; msg->opts.rw = rw; msg->opts.rh = rh; + msg->opts.scale_src_x = scale_src_x; + msg->opts.scale_src_y = scale_src_y; + msg->opts.scale_src_w = scale_src_w; + msg->opts.scale_src_h = scale_src_h; + msg->opts.scale_dst_w = scale_dst_w; + msg->opts.scale_dst_h = scale_dst_h; + msg->opts.scale_smooth = scale_smooth; + msg->opts.scale_hint = scale_hint; msg->opts.orientation = !!orientation; *size = sizeof(*msg); diff --git a/src/bin/evas/evas_cserve2_main.c b/src/bin/evas/evas_cserve2_main.c index 8b72ecc4ed..5c57b72c27 100644 --- a/src/bin/evas/evas_cserve2_main.c +++ b/src/bin/evas/evas_cserve2_main.c @@ -105,7 +105,14 @@ _cserve2_client_setopts(Client *client) INF("\tsize: %dx%d", msg->opts.w, msg->opts.h); INF("\tscale down: %d", msg->opts.scale_down); INF("\tregion: %d,%d + %dx%d", - msg->opts.rx, msg->opts.ry, msg->opts.rw, msg->opts.rh); + msg->opts.rx, msg->opts.ry, msg->opts.rw, msg->opts.rh); + INF("\toriginal image's source coord: %d,%d", + msg->opts.scale_src_x, msg->opts.scale_src_y); + INF("\toriginal image size: %dx%d", + msg->opts.scale_src_w, msg->opts.scale_src_h); + INF("\tscale size: %dx%d", msg->opts.scale_dst_w, msg->opts.scale_dst_h); + INF("\tscale smooth: %d", msg->opts.scale_smooth); + INF("\tscale hint: %d", msg->opts.scale_hint); INF("\torientation: %d\n", msg->opts.orientation); if (cserve2_cache_image_opts_set(client, msg) != 0) @@ -336,6 +343,8 @@ main(int argc EINA_UNUSED, const char *argv[] EINA_UNUSED) cserve2_requests_init(); + cserve2_scale_init(); + cserve2_font_init(); cserve2_cache_init(); @@ -350,6 +359,8 @@ main(int argc EINA_UNUSED, const char *argv[] EINA_UNUSED) cserve2_font_shutdown(); + cserve2_scale_shutdown(); + cserve2_requests_shutdown(); cserve2_slaves_shutdown(); diff --git a/src/bin/evas/evas_cserve2_scale.c b/src/bin/evas/evas_cserve2_scale.c new file mode 100644 index 0000000000..c9863322a3 --- /dev/null +++ b/src/bin/evas/evas_cserve2_scale.c @@ -0,0 +1,61 @@ +#include "evas_common.h" +#include "evas_private.h" + +void +cserve2_scale_init(void) +{ + evas_common_cpu_init(); + evas_common_blend_init(); + evas_common_image_init(); + evas_common_convert_init(); + evas_common_scale_init(); +} + +void +cserve2_scale_shutdown(void) +{ + evas_common_image_shutdown(); +} + +static inline void +_cserve2_rgba_image_set(RGBA_Image *im, void *data, int w, int h, int alpha) +{ + memset(im, 0, sizeof *im); + + im->ref = 1; + im->cache_entry.w = w; + im->cache_entry.h = h; + im->cache_entry.space = EVAS_COLORSPACE_ARGB8888; + im->cache_entry.flags.alpha = alpha; + im->image.data = data; + im->cache_entry.allocated.w = w; + im->cache_entry.allocated.h = h; +} + +void +cserve2_rgba_image_scale_do(void *src_data, void *dst_data, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, + int alpha, int smooth) +{ + RGBA_Image src, dst; + RGBA_Draw_Context ct; + + _cserve2_rgba_image_set(&src, src_data, src_w, src_h, alpha); + + _cserve2_rgba_image_set(&dst, dst_data, dst_w, dst_h, alpha); + dst.flags = RGBA_IMAGE_NOTHING; + + memset(&ct, 0, sizeof(ct)); + ct.sli.h = 1; + ct.render_op = _EVAS_RENDER_COPY; + + if (smooth) + evas_common_scale_rgba_in_to_out_clip_smooth(&src, &dst, &ct, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + else + evas_common_scale_rgba_in_to_out_clip_sample(&src, &dst, &ct, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); +} diff --git a/src/bin/evas/evas_cserve2_slave.c b/src/bin/evas/evas_cserve2_slave.c index 317bc1441d..5a060173a8 100644 --- a/src/bin/evas/evas_cserve2_slave.c +++ b/src/bin/evas/evas_cserve2_slave.c @@ -349,6 +349,8 @@ image_load(const char *file, const char *key, const char *shmfile, Slave_Msg_Ima if (!api->data_load(&ilp, file, key, &err)) ret = err; + result->w = params->w; + result->h = params->h; result->alpha_sparse = ilp.alpha_sparse; done: diff --git a/src/lib/evas/cache2/evas_cache2.c b/src/lib/evas/cache2/evas_cache2.c index 1b9d05cbd8..6397f10981 100644 --- a/src/lib/evas/cache2/evas_cache2.c +++ b/src/lib/evas/cache2/evas_cache2.c @@ -25,6 +25,11 @@ Var = NULL; \ } +/* Size of characters used to determine a string that'll be used for load + * options in hash keys. + */ +#define HKEY_LOAD_OPTS_STR_LEN 215 + static void _evas_cache_image_dirty_add(Image_Entry *im); static void _evas_cache_image_dirty_del(Image_Entry *im); static void _evas_cache_image_activ_add(Image_Entry *im); @@ -567,7 +572,39 @@ _create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key, size += eina_convert_xtoa(lo->region.w, hkey + size); hkey[size] = 'x'; size += 1; + size += eina_convert_xtoa(lo->region.h, hkey + size); + hkey[size++] = '!'; + hkey[size++] = '('; + + hkey[size] = '['; + size += 1; + size += eina_convert_xtoa(lo->scale_load.src_x, hkey + size); + hkey[size] = ','; + size += 1; + size += eina_convert_xtoa(lo->scale_load.src_y, hkey + size); + hkey[size] = ':'; + size += 1; + size += eina_convert_xtoa(lo->scale_load.src_w, hkey + size); + hkey[size] = 'x'; + size += 1; + size += eina_convert_xtoa(lo->scale_load.src_h, hkey + size); + hkey[size++] = ']'; + + hkey[size++] = '-'; + + hkey[size] = '['; + size += 1; + size += eina_convert_xtoa(lo->scale_load.dst_w, hkey + size); + hkey[size] = 'x'; + size += 1; + size += eina_convert_xtoa(lo->scale_load.dst_h, hkey + size); + hkey[size] = ':'; + size += 1; + size += eina_convert_xtoa(lo->scale_load.smooth, hkey + size); + hkey[size++] = ']'; + + hkey[size++] = ')'; if (lo->orientation) { @@ -591,7 +628,8 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, RG int stat_done = 0, stat_failed = 0; struct stat st; Image_Timestamp tstamp; - Evas_Image_Load_Opts prevent = { 0, 0.0, 0, 0, 0, { 0, 0, 0, 0 }, EINA_FALSE }; + Evas_Image_Load_Opts prevent = { 0, 0.0, 0, 0, 0, { 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, EINA_FALSE }; if ((!path) || ((!path) && (!key))) { @@ -601,7 +639,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, RG pathlen = strlen(path); keylen = key ? strlen(key) : 6; - size = pathlen + keylen + 132; + size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN; hkey = alloca(sizeof(char) * size); _create_hash_key(hkey, path, pathlen, key, keylen, lo); @@ -614,6 +652,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, RG (lo->dpi == 0.0) && ((lo->w == 0) || (lo->h == 0)) && ((lo->region.w == 0) || (lo->region.h == 0)) && + ((lo->scale_load.dst_w == 0) || (lo->scale_load.dst_h == 0)) && (lo->orientation == 0) )) { @@ -731,6 +770,128 @@ evas_cache2_image_open_wait(Image_Entry *im) return EVAS_LOAD_ERROR_NONE; } +static Image_Entry * +_scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth) +{ + size_t pathlen, keylen, size; + char *hkey; + RGBA_Image_Loadopts lo; + Image_Entry *ret; + + if (((!im->file) || ((!im->file) && (!im->key))) || (!im->data1) || + ((src_w == dst_w) && (src_h == dst_h)) || + ((!im->flags.alpha) && (!smooth))) return NULL; + + pathlen = strlen(im->file); + keylen = im->key ? strlen(im->key) : 6; + size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN; + hkey = alloca(sizeof(char) * size); + + memcpy(&lo, &im->load_opts, sizeof lo); + lo.scale_load.src_x = src_x; + lo.scale_load.src_y = src_y; + lo.scale_load.src_w = src_w; + lo.scale_load.src_h = src_h; + lo.scale_load.dst_w = dst_w; + lo.scale_load.dst_h = dst_h; + lo.scale_load.smooth = smooth; + + if (!smooth) + { + lo.scale_load.smooth = 1; + _create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo); + + ret = eina_hash_find(im->cache2->activ, hkey); + if (ret) goto found; + + ret = eina_hash_find(im->cache2->inactiv, hkey); + if (ret) goto handle_inactiv; + + lo.scale_load.smooth = smooth; + } + + _create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo); + + ret = eina_hash_find(im->cache2->activ, hkey); + if (ret) goto found; + + ret = eina_hash_find(im->cache2->inactiv, hkey); + + handle_inactiv: + if (!ret) return NULL; + + /* Remove from lru and make it active again */ + _evas_cache_image_lru_del(ret); + _evas_cache_image_activ_add(ret); + + found: + evas_cache2_image_load_data(ret); + + return ret; +} + +EAPI Image_Entry * +evas_cache2_image_scale_load(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth) +{ + size_t pathlen, keylen, size; + char *hkey; + RGBA_Image_Loadopts lo; + int error = EVAS_LOAD_ERROR_NONE; + Image_Entry *ret; + + if (((!im->file) || ((!im->file) && (!im->key))) || + ((src_w == 0) || (src_h == 0) || (dst_w == 0) || (dst_h == 0)) || + (im->scale_hint == EVAS_IMAGE_SCALE_HINT_DYNAMIC)) goto parent_out; + + if (((src_w == dst_w) && (src_h == dst_h)) || + ((!im->flags.alpha) && (!smooth))) goto parent_out; + + ret = _scaled_image_find(im, src_x, src_y, src_w, src_h, + dst_w, dst_h, smooth); + if (ret) return ret; + + pathlen = strlen(im->file); + keylen = im->key ? strlen(im->key) : 6; + size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN; + hkey = alloca(sizeof(char) * size); + + memcpy(&lo, &im->load_opts, sizeof lo); + lo.scale_load.src_x = src_x; + lo.scale_load.src_y = src_y; + lo.scale_load.src_w = src_w; + lo.scale_load.src_h = src_h; + lo.scale_load.dst_w = dst_w; + lo.scale_load.dst_h = dst_h; + lo.scale_load.smooth = smooth; + lo.scale_load.scale_hint = im->scale_hint; + + _create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo); + + ret = _evas_cache_image_entry_new(im->cache2, hkey, NULL, im->file, im->key, + &lo, &error); + if (error != EVAS_LOAD_ERROR_NONE) + { + ERR("Failed to create scale image entry with error code %d.", error); + + if (ret) _evas_cache_image_entry_delete(im->cache2, ret); + goto parent_out; + } + + evas_cserve2_image_load_wait(ret); + evas_cache2_image_load_data(ret); + + ret->references++; + ret->w = dst_w; + ret->h = dst_h; + + return ret; + + parent_out: + evas_cache2_image_load_data(im); + + return im; +} + EAPI void evas_cache2_image_close(Image_Entry *im) { diff --git a/src/lib/evas/cache2/evas_cache2.h b/src/lib/evas/cache2/evas_cache2.h index 7028338e7b..8fc300aca7 100644 --- a/src/lib/evas/cache2/evas_cache2.h +++ b/src/lib/evas/cache2/evas_cache2.h @@ -59,6 +59,7 @@ extern "C" { EAPI Evas_Cache2* evas_cache2_init(const Evas_Cache2_Image_Func *cb); EAPI void evas_cache2_shutdown(Evas_Cache2 *cache); EAPI Image_Entry * evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, RGBA_Image_Loadopts *lo, int *error); +EAPI Image_Entry *evas_cache2_image_scale_load(Image_Entry *im, int src_x, int src_y, int src_w, int src_h, int dst_w, int dst_h, int smooth); EAPI int evas_cache2_image_open_wait(Image_Entry *im); EAPI void evas_cache2_image_close(Image_Entry *im); EAPI int evas_cache2_image_load_data(Image_Entry *ie); diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index f71f0e7ca1..ca9d8e4cb9 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -12,6 +12,9 @@ #include "evas_common.h" #include "evas_private.h" +#ifdef EVAS_CSERVE2 +#include "../cserve2/evas_cs2_private.h" +#endif #include "../common/evas_convert_color.h" #include "../common/evas_convert_colorspace.h" #include "../common/evas_convert_yuv.h" @@ -66,6 +69,12 @@ struct _Evas_Object_Image struct { short x, y, w, h; } region; + struct { + int src_x, src_y, src_w, src_h; + int dst_w, dst_h; + int smooth; + int scale_hint; + } scale_load; Eina_Bool orientation : 1; } load_opts; @@ -392,6 +401,14 @@ _image_file_set(Eo *eo_obj, void *_pd, va_list *list) lo.region.y = o->load_opts.region.y; lo.region.w = o->load_opts.region.w; lo.region.h = o->load_opts.region.h; + lo.scale_load.src_x = o->load_opts.scale_load.src_x; + lo.scale_load.src_y = o->load_opts.scale_load.src_y; + lo.scale_load.src_w = o->load_opts.scale_load.src_w; + lo.scale_load.src_h = o->load_opts.scale_load.src_h; + lo.scale_load.dst_w = o->load_opts.scale_load.dst_w; + lo.scale_load.dst_h = o->load_opts.scale_load.dst_h; + lo.scale_load.smooth = o->load_opts.scale_load.smooth; + lo.scale_load.scale_hint = o->load_opts.scale_load.scale_hint; lo.orientation = o->load_opts.orientation; o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output, o->cur.file, @@ -3490,17 +3507,48 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v (o->cur.border.t == 0) && (o->cur.border.b == 0) && (o->cur.border.fill != 0)) - obj->layer->evas->engine.func->image_draw(output, - context, - surface, - pixels, - 0, 0, - imagew, - imageh, - obj->cur.geometry.x + ix + x, - obj->cur.geometry.y + iy + y, - iw, ih, - o->cur.smooth_scale); + { +#ifdef EVAS_CSERVE2 + if (evas_cserve2_use_get()) + { + Image_Entry *ie; + void *data = pixels; + int w = imagew, h = imageh; + + ie = evas_cache2_image_scale_load + ((Image_Entry *)pixels, + 0, 0, + imagew, imageh, + iw, ih, o->cur.smooth_scale); + if (ie != &((RGBA_Image *)pixels)->cache_entry) + { + data = ie; + w = iw; + h = ih; + } + + obj->layer->evas->engine.func->image_draw + (output, context, surface, data, + 0, 0, + w, h, + obj->cur.geometry.x + ix + x, + obj->cur.geometry.y + iy + y, + iw, ih, + o->cur.smooth_scale); + } + else +#endif + { + obj->layer->evas->engine.func->image_draw + (output, context, surface, pixels, + 0, 0, + imagew, imageh, + obj->cur.geometry.x + ix + x, + obj->cur.geometry.y + iy + y, + iw, ih, + o->cur.smooth_scale); + } + } else { int inx, iny, inw, inh, outx, outy, outw, outh; diff --git a/src/lib/evas/common/evas_image_main.c b/src/lib/evas/common/evas_image_main.c index a8f7317e39..05cc9aaf2c 100644 --- a/src/lib/evas/common/evas_image_main.c +++ b/src/lib/evas/common/evas_image_main.c @@ -20,6 +20,7 @@ static Evas_Cache_Image * eci = NULL; #ifdef EVAS_CSERVE2 +#define EVAS_CSERVE2_SCALE_CACHE_SIZE (4 * 1024 * 1024) static Evas_Cache2 * eci2 = NULL; #endif static int reference = 0; @@ -743,7 +744,7 @@ evas_common_image_set_cache(unsigned int size) evas_cache_image_set(eci, size); #ifdef EVAS_CSERVE2 if (eci2) - evas_cache2_limit_set(eci2, size); + evas_cache2_limit_set(eci2, size + EVAS_CSERVE2_SCALE_CACHE_SIZE); #endif } diff --git a/src/lib/evas/cserve2/evas_cs2.h b/src/lib/evas/cserve2/evas_cs2.h index fc83a9276d..7bd4c51f4d 100644 --- a/src/lib/evas/cserve2/evas_cs2.h +++ b/src/lib/evas/cserve2/evas_cs2.h @@ -76,6 +76,10 @@ struct _Msg_Setopts { int w, h; int scale_down; int rx, ry, rw, rh; + int scale_src_x, scale_src_y, scale_src_w, scale_src_h; + int scale_dst_w, scale_dst_h; + int scale_smooth; + int scale_hint; Eina_Bool orientation; } opts; }; diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c index 004a5dbce6..7024de9a89 100644 --- a/src/lib/evas/cserve2/evas_cs2_client.c +++ b/src/lib/evas/cserve2/evas_cs2_client.c @@ -561,6 +561,14 @@ _image_setopts_server_send(Image_Entry *ie) msg.opts.ry = ie->load_opts.region.y; msg.opts.rw = ie->load_opts.region.w; msg.opts.rh = ie->load_opts.region.h; + msg.opts.scale_src_x = ie->load_opts.scale_load.src_x; + msg.opts.scale_src_y = ie->load_opts.scale_load.src_y; + msg.opts.scale_src_w = ie->load_opts.scale_load.src_w; + msg.opts.scale_src_h = ie->load_opts.scale_load.src_h; + msg.opts.scale_dst_w = ie->load_opts.scale_load.dst_w; + msg.opts.scale_dst_h = ie->load_opts.scale_load.dst_h; + msg.opts.scale_smooth = ie->load_opts.scale_load.smooth; + msg.opts.scale_hint = ie->load_opts.scale_load.scale_hint; msg.opts.orientation = ie->load_opts.orientation; if (!_server_send(&msg, sizeof(msg), 0, NULL)) diff --git a/src/lib/evas/include/evas_common.h b/src/lib/evas/include/evas_common.h index e4cfff99e6..cdc6a0e47a 100644 --- a/src/lib/evas/include/evas_common.h +++ b/src/lib/evas/include/evas_common.h @@ -500,6 +500,12 @@ struct _RGBA_Image_Loadopts struct { unsigned int x, y, w, h; } region; + struct { + int src_x, src_y, src_w, src_h; + int dst_w, dst_h; + int smooth; + Evas_Image_Scale_Hint scale_hint; + } scale_load; Eina_Bool orientation; // if EINA_TRUE => should honor orientation information provided by file (like jpeg exif info) }; diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 6d140b9f7f..cf213d75e3 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -923,22 +923,38 @@ eng_image_draw(void *data EINA_UNUSED, void *context, void *surface, void *image image_loaded: #endif - evas_common_rgba_image_scalecache_prepare(&im->cache_entry, surface, context, smooth, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h); - evas_common_rgba_image_scalecache_do(&im->cache_entry, surface, context, smooth, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h); -/* - if (smooth) - evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h); - else - evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context, - src_x, src_y, src_w, src_h, - dst_x, dst_y, dst_w, dst_h); - */ +#ifdef EVAS_CSERVE2 + if (evas_cserve2_use_get()) + { + if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888) + evas_cache2_image_load_data(&im->cache_entry); + + evas_common_image_colorspace_normalize(im); + + if (smooth) + evas_common_scale_rgba_in_to_out_clip_smooth + (im, surface, context, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + else + evas_common_scale_rgba_in_to_out_clip_sample + (im, surface, context, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + } + else +#endif + { + evas_common_rgba_image_scalecache_prepare + (&im->cache_entry, surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + evas_common_rgba_image_scalecache_do + (&im->cache_entry, surface, context, smooth, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h); + } + evas_common_cpu_end_opt(); } }