evas/cserve2: Add scalecache support

Signed-off-by: Paulo Alcantara <pcacjr@profusion.mobi>

Patch by: Paulo Alcantara <pcacjr@profusion.mobi>



SVN revision: 79754
This commit is contained in:
Paulo Alcantara 2012-11-27 18:23:25 +00:00 committed by Iván Briano
parent 8ac3152e89
commit f8f79f8599
17 changed files with 503 additions and 38 deletions

View File

@ -1,3 +1,6 @@
2012-11-22 Paulo Alcantara (pcacjr)
* Add scalecache support to Cserve2
2012-11-22 Sung W. Park (sung_) 2012-11-22 Sung W. Park (sung_)
* Fixed a bug where if an image object rendered using Evas GL * Fixed a bug where if an image object rendered using Evas GL

1
NEWS
View File

@ -11,6 +11,7 @@ Additions:
* Add eina_tmpstr_add() and eina_tmpstr_del() * Add eina_tmpstr_add() and eina_tmpstr_del()
* Add eina_thread API * Add eina_thread API
* Add eina_list_last_data_get * Add eina_list_last_data_get
* Add Cserve2 scalecache support
Improvements: Improvements:
* Single EFL tree covering all EFL library components. * Single EFL tree covering all EFL library components.

View File

@ -1727,6 +1727,7 @@ bin/evas/evas_cserve2_shm.c \
bin/evas/evas_cserve2_cache.c \ bin/evas/evas_cserve2_cache.c \
bin/evas/evas_cserve2_requests.c \ bin/evas/evas_cserve2_requests.c \
bin/evas/evas_cserve2_fonts.c \ bin/evas/evas_cserve2_fonts.c \
bin/evas/evas_cserve2_scale.c \
bin/evas/evas_cserve2_main_loop_linux.c \ bin/evas/evas_cserve2_main_loop_linux.c \
lib/evas/cserve2/evas_cs2_utils.h \ lib/evas/cserve2/evas_cs2_utils.h \
lib/evas/cserve2/evas_cs2_utils.c lib/evas/cserve2/evas_cs2_utils.c

View File

@ -109,6 +109,7 @@ struct _Slave_Msg_Image_Load {
}; };
struct _Slave_Msg_Image_Loaded { struct _Slave_Msg_Image_Loaded {
int w, h;
Eina_Bool alpha_sparse : 1; 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_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_init(void);
void cserve2_cache_shutdown(void); void cserve2_cache_shutdown(void);
void cserve2_cache_client_new(Client *client); 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); 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); void cserve2_cache_file_close(Client *client, unsigned int client_file_id);
int cserve2_cache_image_opts_set(Client *client, Msg_Setopts *msg); 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_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_preload(Client *client, unsigned int client_image_id, unsigned int rid);
void cserve2_cache_image_unload(Client *client, unsigned int client_image_id); void cserve2_cache_image_unload(Client *client, unsigned int client_image_id);

View File

@ -3,6 +3,7 @@
#endif #endif
#include <string.h> #include <string.h>
#include <sys/mman.h>
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
#include <sys/time.h> #include <sys/time.h>
@ -65,6 +66,10 @@ struct _Image_Data {
int w, h; // w and h < -1 int w, h; // w and h < -1
int scale_down; // scale_down < -1 int scale_down; // scale_down < -1
int rx, ry, rw, rh; // rx, ry, rw, rh < -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 Eina_Bool orientation; // orientation == 0
} opts; } opts;
Shm_Handle *shm; Shm_Handle *shm;
@ -179,7 +184,7 @@ static Eina_List *image_entries_lru = NULL;
static Eina_List *font_shm_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 unused_mem_usage = 0;
static int max_font_usage = 10 * 4 * 1024; /* in kbytes */ static int max_font_usage = 10 * 4 * 1024; /* in kbytes */
static int font_mem_usage = 0; static int font_mem_usage = 0;
@ -474,6 +479,78 @@ _load_request_build(Image_Data *i, int *bufsize)
return buf; 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 * static Msg_Loaded *
_load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size) _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) if (!e->doload)
DBG("Entry %d loaded by speculative preload.", e->base.id); 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); 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; 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->file_id, im->opts.dpi, im->opts.w, im->opts.h,
im->opts.scale_down, im->opts.rx, im->opts.ry, 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); 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.ry = msg->opts.ry;
im_entry->opts.rw = msg->opts.rw; im_entry->opts.rw = msg->opts.rw;
im_entry->opts.rh = msg->opts.rh; 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; im_entry->opts.orientation = msg->opts.orientation;
return im_entry; return im_entry;
@ -2034,9 +2138,10 @@ cserve2_cache_image_opts_set(Client *client, Msg_Setopts *msg)
fentry = entry->file; fentry = entry->file;
fentry->images = eina_list_append(fentry->images, entry); fentry->images = eina_list_append(fentry->images, entry);
entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD, if ((!entry->opts.scale_dst_w) && (!entry->opts.scale_dst_h))
0, NULL, fentry->base.request, entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD,
&_load_funcs, entry); 0, NULL, fentry->base.request,
&_load_funcs, entry);
return 0; return 0;
} }

View File

@ -101,6 +101,10 @@ parse_input_setopts(int *size)
int w, h; int w, h;
int scale; int scale;
int rx, ry, rw, rh; 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; int orientation;
// reading file_id, image_id // reading file_id, image_id
@ -123,11 +127,30 @@ parse_input_setopts(int *size)
_read_line(line, sizeof(line)); _read_line(line, sizeof(line));
sscanf(line, "%d %d %d %d", &rx, &ry, &rw, &rh); 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 // reading orientation
_read_line(line, sizeof(line)); _read_line(line, sizeof(line));
sscanf(line, "%d", &orientation); sscanf(line, "%d", &orientation);
msg = calloc(1, sizeof(*msg)); msg = calloc(1, sizeof(*msg));
msg->base.rid = _rid_count++; msg->base.rid = _rid_count++;
@ -142,6 +165,14 @@ parse_input_setopts(int *size)
msg->opts.ry = ry; msg->opts.ry = ry;
msg->opts.rw = rw; msg->opts.rw = rw;
msg->opts.rh = rh; 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; msg->opts.orientation = !!orientation;
*size = sizeof(*msg); *size = sizeof(*msg);

View File

@ -105,7 +105,14 @@ _cserve2_client_setopts(Client *client)
INF("\tsize: %dx%d", msg->opts.w, msg->opts.h); INF("\tsize: %dx%d", msg->opts.w, msg->opts.h);
INF("\tscale down: %d", msg->opts.scale_down); INF("\tscale down: %d", msg->opts.scale_down);
INF("\tregion: %d,%d + %dx%d", 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); INF("\torientation: %d\n", msg->opts.orientation);
if (cserve2_cache_image_opts_set(client, msg) != 0) 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_requests_init();
cserve2_scale_init();
cserve2_font_init(); cserve2_font_init();
cserve2_cache_init(); cserve2_cache_init();
@ -350,6 +359,8 @@ main(int argc EINA_UNUSED, const char *argv[] EINA_UNUSED)
cserve2_font_shutdown(); cserve2_font_shutdown();
cserve2_scale_shutdown();
cserve2_requests_shutdown(); cserve2_requests_shutdown();
cserve2_slaves_shutdown(); cserve2_slaves_shutdown();

View File

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

View File

@ -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)) if (!api->data_load(&ilp, file, key, &err))
ret = err; ret = err;
result->w = params->w;
result->h = params->h;
result->alpha_sparse = ilp.alpha_sparse; result->alpha_sparse = ilp.alpha_sparse;
done: done:

View File

@ -25,6 +25,11 @@
Var = NULL; \ 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_add(Image_Entry *im);
static void _evas_cache_image_dirty_del(Image_Entry *im); static void _evas_cache_image_dirty_del(Image_Entry *im);
static void _evas_cache_image_activ_add(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); size += eina_convert_xtoa(lo->region.w, hkey + size);
hkey[size] = 'x'; hkey[size] = 'x';
size += 1; size += 1;
size += eina_convert_xtoa(lo->region.h, hkey + size); 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) 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; int stat_done = 0, stat_failed = 0;
struct stat st; struct stat st;
Image_Timestamp tstamp; 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))) 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); pathlen = strlen(path);
keylen = key ? strlen(key) : 6; keylen = key ? strlen(key) : 6;
size = pathlen + keylen + 132; size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN;
hkey = alloca(sizeof(char) * size); hkey = alloca(sizeof(char) * size);
_create_hash_key(hkey, path, pathlen, key, keylen, lo); _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->dpi == 0.0) &&
((lo->w == 0) || (lo->h == 0)) && ((lo->w == 0) || (lo->h == 0)) &&
((lo->region.w == 0) || (lo->region.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) (lo->orientation == 0)
)) ))
{ {
@ -731,6 +770,128 @@ evas_cache2_image_open_wait(Image_Entry *im)
return EVAS_LOAD_ERROR_NONE; 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 EAPI void
evas_cache2_image_close(Image_Entry *im) evas_cache2_image_close(Image_Entry *im)
{ {

View File

@ -59,6 +59,7 @@ extern "C" {
EAPI Evas_Cache2* evas_cache2_init(const Evas_Cache2_Image_Func *cb); EAPI Evas_Cache2* evas_cache2_init(const Evas_Cache2_Image_Func *cb);
EAPI void evas_cache2_shutdown(Evas_Cache2 *cache); 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_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 int evas_cache2_image_open_wait(Image_Entry *im);
EAPI void evas_cache2_image_close(Image_Entry *im); EAPI void evas_cache2_image_close(Image_Entry *im);
EAPI int evas_cache2_image_load_data(Image_Entry *ie); EAPI int evas_cache2_image_load_data(Image_Entry *ie);

View File

@ -12,6 +12,9 @@
#include "evas_common.h" #include "evas_common.h"
#include "evas_private.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_color.h"
#include "../common/evas_convert_colorspace.h" #include "../common/evas_convert_colorspace.h"
#include "../common/evas_convert_yuv.h" #include "../common/evas_convert_yuv.h"
@ -66,6 +69,12 @@ struct _Evas_Object_Image
struct { struct {
short x, y, w, h; short x, y, w, h;
} region; } 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; Eina_Bool orientation : 1;
} load_opts; } 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.y = o->load_opts.region.y;
lo.region.w = o->load_opts.region.w; lo.region.w = o->load_opts.region.w;
lo.region.h = o->load_opts.region.h; 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; lo.orientation = o->load_opts.orientation;
o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output, o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
o->cur.file, 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.t == 0) &&
(o->cur.border.b == 0) && (o->cur.border.b == 0) &&
(o->cur.border.fill != 0)) (o->cur.border.fill != 0))
obj->layer->evas->engine.func->image_draw(output, {
context, #ifdef EVAS_CSERVE2
surface, if (evas_cserve2_use_get())
pixels, {
0, 0, Image_Entry *ie;
imagew, void *data = pixels;
imageh, int w = imagew, h = imageh;
obj->cur.geometry.x + ix + x,
obj->cur.geometry.y + iy + y, ie = evas_cache2_image_scale_load
iw, ih, ((Image_Entry *)pixels,
o->cur.smooth_scale); 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 else
{ {
int inx, iny, inw, inh, outx, outy, outw, outh; int inx, iny, inw, inh, outx, outy, outw, outh;

View File

@ -20,6 +20,7 @@
static Evas_Cache_Image * eci = NULL; static Evas_Cache_Image * eci = NULL;
#ifdef EVAS_CSERVE2 #ifdef EVAS_CSERVE2
#define EVAS_CSERVE2_SCALE_CACHE_SIZE (4 * 1024 * 1024)
static Evas_Cache2 * eci2 = NULL; static Evas_Cache2 * eci2 = NULL;
#endif #endif
static int reference = 0; static int reference = 0;
@ -743,7 +744,7 @@ evas_common_image_set_cache(unsigned int size)
evas_cache_image_set(eci, size); evas_cache_image_set(eci, size);
#ifdef EVAS_CSERVE2 #ifdef EVAS_CSERVE2
if (eci2) if (eci2)
evas_cache2_limit_set(eci2, size); evas_cache2_limit_set(eci2, size + EVAS_CSERVE2_SCALE_CACHE_SIZE);
#endif #endif
} }

View File

@ -76,6 +76,10 @@ struct _Msg_Setopts {
int w, h; int w, h;
int scale_down; int scale_down;
int rx, ry, rw, rh; 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; Eina_Bool orientation;
} opts; } opts;
}; };

View File

@ -561,6 +561,14 @@ _image_setopts_server_send(Image_Entry *ie)
msg.opts.ry = ie->load_opts.region.y; msg.opts.ry = ie->load_opts.region.y;
msg.opts.rw = ie->load_opts.region.w; msg.opts.rw = ie->load_opts.region.w;
msg.opts.rh = ie->load_opts.region.h; 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; msg.opts.orientation = ie->load_opts.orientation;
if (!_server_send(&msg, sizeof(msg), 0, NULL)) if (!_server_send(&msg, sizeof(msg), 0, NULL))

View File

@ -500,6 +500,12 @@ struct _RGBA_Image_Loadopts
struct { struct {
unsigned int x, y, w, h; unsigned int x, y, w, h;
} region; } 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) Eina_Bool orientation; // if EINA_TRUE => should honor orientation information provided by file (like jpeg exif info)
}; };

View File

@ -923,22 +923,38 @@ eng_image_draw(void *data EINA_UNUSED, void *context, void *surface, void *image
image_loaded: image_loaded:
#endif #endif
evas_common_rgba_image_scalecache_prepare(&im->cache_entry, surface, context, smooth, #ifdef EVAS_CSERVE2
src_x, src_y, src_w, src_h, if (evas_cserve2_use_get())
dst_x, dst_y, dst_w, dst_h); {
evas_common_rgba_image_scalecache_do(&im->cache_entry, surface, context, smooth, if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
src_x, src_y, src_w, src_h, evas_cache2_image_load_data(&im->cache_entry);
dst_x, dst_y, dst_w, dst_h);
/* evas_common_image_colorspace_normalize(im);
if (smooth)
evas_common_scale_rgba_in_to_out_clip_smooth(im, surface, context, if (smooth)
src_x, src_y, src_w, src_h, evas_common_scale_rgba_in_to_out_clip_smooth
dst_x, dst_y, dst_w, dst_h); (im, surface, context,
else src_x, src_y, src_w, src_h,
evas_common_scale_rgba_in_to_out_clip_sample(im, surface, context, dst_x, dst_y, dst_w, dst_h);
src_x, src_y, src_w, src_h, else
dst_x, dst_y, dst_w, dst_h); 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(); evas_common_cpu_end_opt();
} }
} }