1. scale cache now allows you to hint at the object if its dynamic, static or

none (ie default) and the engines actually understand it and use it.
2. fixes to scalecache and cserver too. more toto's done and its now been
stress tested by me - and i think cserve is ready to go gold. just enable it
with export EVAS_CSERVE=1 in your env for any eflapps - and run evas_cserve
(cmd-line options avalable plus cmd-line tol to query settings change on the
fly and query statsitics and state)



SVN revision: 40536
This commit is contained in:
Carsten Haitzler 2009-05-07 13:29:56 +00:00
parent dc09494b26
commit 85bff718d6
21 changed files with 656 additions and 95 deletions

View File

@ -9,7 +9,6 @@
// fixme:'s
//
// add ops to get internal cache state (both)
// preload - make it work (both)
//
@ -60,6 +59,8 @@ static int stat_res_interval = 2;
static time_t t_now = 0;
static int server_id = 0;
static Evas_Cache_Image *cache = NULL;
static Eina_Hash *active_images = NULL;
@ -74,6 +75,8 @@ static Mem *stat_mem = NULL;
static int stat_mem_num = 0;
static Eina_List *stat_mems = NULL;
static void cache_clean(void);
#ifndef _WIN32
static double
get_time(void)
@ -435,6 +438,7 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const
img->stats.load1 = t;
img->key = eina_stringshare_add(bufkey);
img->file.modtime = st.st_mtime;
img->file.last_stat = t_now;
img->file.file = eina_stringshare_add(file);
if (key) img->file.key = eina_stringshare_add(key);
img->load_opts.scale_down_by = load_opts->scale_down_by;
@ -447,9 +451,9 @@ img_new(const char *file, const char *key, RGBA_Image_Loadopts *load_opts, const
img->ref = 1;
img->active = 1;
img->usage = sizeof(Img) + strlen(img->key) + 1 + strlen(img->file.file) + 1;
img->usage = sizeof(Img) + strlen(img->key) + 1 +
strlen(img->file.file) + 1;
if (img->file.key) img->usage += strlen(img->file.key) + 1;
// fixme: load img, get header
eina_hash_direct_add(active_images, img->key, img);
return img;
}
@ -459,15 +463,19 @@ img_loaddata(Img *img)
{
double t;
if (img->mem) return;
t = get_time();
evas_cache_image_load_data((Image_Entry *)img);
t = get_time() - t;
img->stats.load2 = t;
if (img->image.data)
msync(img->image.data, img->image.w * img->image.h * sizeof(DATA32), MS_SYNC | MS_INVALIDATE);
if (!img->active) cache_usage -= img->usage;
img->usage +=
(4096 * (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) / 4096)) +
sizeof(Mem);
if (!img->active) cache_usage += img->usage;
cache_clean();
}
static void
@ -484,7 +492,8 @@ img_free(Img *img)
static void
cache_clean(void)
{
while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) && (cache_images))
while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) &&
(cache_images))
{
Img *img;
Eina_List *l;
@ -522,12 +531,20 @@ mem_cache_adjust(void)
{
int pval = cache_max_adjust;
int max = 0;
int mem_used;
if (mem_total <= 0) return;
if ((mem_free + mem_cached + mem_buffers) < mem_total)
cache_max_adjust += mem_total - (mem_free + mem_cached + mem_buffers);
mem_used = mem_total - mem_free - mem_cached - mem_buffers;
#if 0 // this lets the image cache to grow to fill all real free ram, if
// there is any (ie ram unused by disk cache)
if (mem_free < mem_total)
{
cache_max_adjust = mem_free;
return;
}
#endif
max = (mem_free / 8) - cache_max_usage;
max = ((mem_free + mem_cached + mem_buffers) / 8) - cache_max_usage;
if (max < 0) max = 0;
if (max > cache_max_usage) max = cache_max_usage;
cache_max_adjust = max - cache_max_usage;
@ -541,15 +558,15 @@ static void
img_cache(Img *img)
{
eina_hash_del(active_images, img->key, img);
img->active = 0;
if (img->dead)
{
img_free(img);
return;
}
cache_images = eina_list_prepend(cache_images, img);
img->cached = t_now;
cache_usage += img->usage;
img->active = 0;
img->cached = t_now;
if (cache_usage > ((cache_max_usage + cache_max_adjust) * 1024))
cache_clean();
}
@ -559,6 +576,7 @@ img_dead(Img *img)
{
if (img->active) return;
cache_images = eina_list_remove(cache_images, img);
cache_usage -= img->usage;
img_free(img);
}
@ -573,6 +591,7 @@ img_ok(Img *img)
((t_now - img->file.last_stat) < stat_res_interval)) return 1;
img->file.last_stat = t_now;
ret = stat(img->file.file, &st);
img->file.last_stat = t_now;
if (ret < 0)
{
img->dead = 1;
@ -624,9 +643,11 @@ img_load(const char *file, const char *key, RGBA_Image_Loadopts *load_opts)
{
if (img_ok(img))
{
cache_images = eina_list_remove_list(cache_images, l);
cache_usage -= img->usage;
img->active = 1;
img->stats.load1saved++;
img->ref++;
cache_images = eina_list_remove_list(cache_images, l);
eina_hash_direct_add(active_images, img->key, img);
stats_update();
return img;
@ -649,11 +670,17 @@ img_unload(Img *img)
static void
img_unloaddata(Img *img)
{
if ((img->dref <= 0) && (img->useless))
if ((img->dref <= 0) && (img->useless) && (img->mem))
{
Image_Entry *ie = (Image_Entry *)img;
if (!img->active) cache_usage -= img->usage;
img->usage -=
(4096 * (((img->image.w * img->image.h * sizeof(DATA32)) + 4095) / 4096)) +
sizeof(Mem);
if (!img->active) cache_usage += img->usage;
evas_cserve_mem_free(img->mem);
stat_mems = eina_list_remove(stat_mems, img->mem);
img->mem = NULL;
img->image.data = NULL;
img->dref = 0;
@ -693,10 +720,23 @@ client_del(void *data, Client *c)
images = data;
EINA_LIST_FREE(images, img)
{
img_unloaddata(img);
img_unload(img);
}
}
static Eina_Bool
getinfo_hash_image_cb(const Eina_Hash *hash __UNUSED__,
const void *key __UNUSED__,
void *data, void *fdata __UNUSED__)
{
Img *img = data;
Eina_List **list = fdata;
*list = eina_list_append(*list, img);
return 1;
}
static int
message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data)
{
@ -710,6 +750,7 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
memset(&msg, 0, sizeof(msg));
msg.pid = getpid();
msg.server_id = server_id;
rep = (Op_Init *)data;
c->pid = rep->pid;
c->func = client_del;
@ -770,8 +811,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Unload *)data;
img = rep->handle;
c->data = eina_list_remove(c->data, img);
img_unload(img);
if ((img) && (rep->server_id == server_id))
{
c->data = eina_list_remove(c->data, img);
img_unload(img);
}
}
break;
case OP_LOADDATA:
@ -782,19 +826,26 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Loaddata *)data;
img = rep->handle;
if (img->mem)
if ((img) && (rep->server_id == server_id))
{
img->stats.load2saved++;
stats_update();
}
else
img_loaddata(img);
memset(&msg, 0, sizeof(msg));
if (img->mem)
{
msg.mem.id = img->mem->id;
msg.mem.offset = img->mem->offset;
msg.mem.size = img->mem->size;
if (img->mem)
{
img->stats.load2saved++;
stats_update();
}
else
{
img_loaddata(img);
}
memset(&msg, 0, sizeof(msg));
if (img->mem)
{
msg.mem.id = img->mem->id;
msg.mem.offset = img->mem->offset;
msg.mem.size = img->mem->size;
}
else
msg.mem.id = msg.mem.offset = msg.mem.size = 0;
}
else
msg.mem.id = msg.mem.offset = msg.mem.size = 0;
@ -808,8 +859,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Unloaddata *)data;
img = rep->handle;
img->dref--;
img_unloaddata(img);
if ((img) && (rep->server_id == server_id))
{
img->dref--;
img_unloaddata(img);
}
}
break;
case OP_USELESSDATA:
@ -819,8 +873,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Unloaddata *)data;
img = rep->handle;
img->dref--;
img_useless(img);
if ((img) && (rep->server_id == server_id))
{
img->dref--;
img_useless(img);
}
}
break;
case OP_PRELOAD:
@ -830,9 +887,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Preload *)data;
img = rep->handle;
c->data = eina_list_remove(c->data, img);
printf("preload %p\n", img);
img_preload(img);
if ((img) && (rep->server_id == server_id))
{
c->data = eina_list_remove(c->data, img);
img_preload(img);
}
}
case OP_FORCEDUNLOAD:
{
@ -841,8 +900,11 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
rep = (Op_Forcedunload *)data;
img = rep->handle;
c->data = eina_list_remove(c->data, img);
img_forcedunload(img);
if ((img) && (rep->server_id == server_id))
{
c->data = eina_list_remove(c->data, img);
img_forcedunload(img);
}
}
break;
case OP_GETCONFIG:
@ -863,6 +925,7 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
cache_max_usage = rep->cache_max_usage;
cache_item_timeout = rep->cache_item_timeout;
cache_item_timeout_check = rep->cache_item_timeout_check;
cache_timeout(t_now);
cache_clean();
}
break;
@ -882,18 +945,104 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
break;
case OP_GETINFO:
{
// get a list of all images in active hash and cache list, and their info like
// file + key
// width, height and alpha flag
// refcount
// data loaded flag
// active ot cached
// last active timestamp
// dead
// mod time
// last checked mod time time
// memory footprint
// Op_Getstats_Reply msg;
Op_Getinfo_Reply *msg;
int len;
Eina_List *imgs = NULL, *l;
Img *img;
len = sizeof(Op_Getinfo_Reply);
if (active_images)
eina_hash_foreach(active_images, getinfo_hash_image_cb, &imgs);
EINA_LIST_FOREACH(cache_images, l, img)
{
imgs = eina_list_append(imgs, img);
}
EINA_LIST_FOREACH(imgs, l, img)
{
len += sizeof(Op_Getinfo_Item);
if (img->file.file) len += strlen(img->file.file);
len++;
if (img->file.key) len += strlen(img->file.key);
len++;
}
msg = malloc(len);
if (msg)
{
unsigned char *p;
memset(msg, 0, len);
p = (unsigned char *)msg;
msg->active.mem_total = 0;
msg->active.count = 0;
msg->cached.mem_total = 0;
msg->cached.count = 0;
p += sizeof(Op_Getinfo_Reply);
EINA_LIST_FOREACH(imgs, l, img)
{
Op_Getinfo_Item *itt, it;
memset(&it, 0, sizeof(Op_Getinfo_Item));
itt = (Op_Getinfo_Item *)p;
it.file_key_size = 0;
if (img->file.file)
{
strcpy(p + sizeof(Op_Getinfo_Item) + it.file_key_size, img->file.file);
it.file_key_size += strlen(img->file.file);
}
p[sizeof(Op_Getinfo_Item) + it.file_key_size] = 0;
it.file_key_size += 1;
if (img->file.key)
{
strcpy(p + sizeof(Op_Getinfo_Item) + it.file_key_size, img->file.key);
it.file_key_size += strlen(img->file.key);
}
p[sizeof(Op_Getinfo_Item) + it.file_key_size] = 0;
it.file_key_size += 1;
it.w = img->image.w;
it.h = img->image.h;
it.file_mod_time = img->file.modtime;
it.file_checked_time = img->file.last_stat;
if (!img->active)
it.cached_time = img->cached;
else
it.cached_time = 0;
it.refcount = img->ref;
it.data_refcount = img->dref;
it.memory_footprint = img->usage;
it.head_load_time = img->stats.load1;
it.data_load_time = img->stats.load2;
it.alpha = img->image.alpha;
if (img->image.data)
it.data_loaded = 1;
else
it.data_loaded = 0;
it.active = img->active;
if (it.active)
{
msg->active.count++;
msg->active.mem_total += img->usage;
}
else
{
msg->cached.count++;
msg->cached.mem_total += img->usage;
}
it.dead = img->dead;
it.useless = img->useless;
memcpy(itt, &it, sizeof(Op_Getinfo_Item));
p += sizeof(Op_Getinfo_Item) + it.file_key_size;
}
msg->active.mem_total =
(msg->active.mem_total + 1023) / 1024;
msg->cached.mem_total =
(msg->cached.mem_total + 1023) / 1024;
evas_cserve_client_send(c, OP_GETINFO, len, msg);
free(msg);
}
else
evas_cserve_client_send(c, OP_GETINFO, 0, NULL);
if (imgs) eina_list_free(imgs);
}
break;
default:
@ -1003,7 +1152,14 @@ main(int argc, char **argv)
{
Server *s;
time_t last_check, t, t_next;
pid_t pid;
t = time(NULL);
pid = getpid();
t ^= (pid << 24) | (pid << 16) | (pid << 8) | (pid);
srand(t);
server_id = rand();
parse_args(argc, argv);
eina_init();
@ -1052,7 +1208,8 @@ main(int argc, char **argv)
if (exit_flag) break;
t = time(NULL);
t_next = t - last_check;
if ((t_next) >= cache_item_timeout_check)
if ((cache_item_timeout_check > 0) &&
((t_next) >= cache_item_timeout_check))
{
t_next = cache_item_timeout_check;
@ -1076,7 +1233,7 @@ main(int argc, char **argv)
evas_cserve_mem_free(stat_mem);
stat_mem = NULL;
}
if (s) evas_cserve_server_del(s);
evas_shutdown();
eina_shutdown();
return 0;

View File

@ -23,6 +23,7 @@ main(int argc, char **argv)
"\tgetconfig Get configuration values\n"
"\tsetconfig CSIZE CTIME CTIMECHECK Set the config values\n"
"\tgetstats Get current cache statistics\n"
"\tgetinfo Get current cache content info\n"
);
exit(0);
}
@ -35,6 +36,7 @@ main(int argc, char **argv)
printf("ERROR: cannot fetch config.\n");
exit(-1);
}
printf("-REPLY-\n");
printf("csize: %i\n", config.cache_max_usage);
printf("ctime: %i\n", config.cache_item_timeout);
printf("ctimecheck: %i\n", config.cache_item_timeout_check);
@ -65,6 +67,7 @@ main(int argc, char **argv)
printf("ERROR: cannot fetch stats.\n");
exit(-1);
}
printf("-REPLY-\n");
printf("saved_memory: %i Kb\n", stats.saved_memory / 1024);
printf("wasted_memory: %i Kb\n", stats.wasted_memory / 1024);
printf("saved_memory_peak: %i Kb\n", stats.saved_memory_peak / 1024);
@ -73,28 +76,80 @@ main(int argc, char **argv)
printf("saved_time_image_data_load: %1.3f sec\n", stats.saved_time_image_data_load);
printf("-OK-\n");
}
}
/*
{
Image_Entry *ie;
RGBA_Image_Loadopts lopt = { 0, 0.0, 0, 0};
ie = malloc(sizeof(Image_Entry));
if (evas_cserve_image_load(ie, argv[1], NULL, &lopt))
else if ((!strcmp(argv[i], "getinfo")))
{
printf("load ok\n");
if (evas_cserve_image_data_load(ie))
Op_Getinfo_Reply *info;
Op_Getinfo_Item *itt;
unsigned char *p;
int i, j;
info = evas_cserve_info_get();
if (!info)
{
Mem *m;
m = ie->data2;
printf("first pixel: %08x\n", *((int *)m->data));
printf("load data ok\n");
// evas_cserve_image_free(ie);
printf("ERROR: cannot fetch info.\n");
exit(-1);
}
j = info->active.count + info->cached.count;
printf("-REPLY-\n");
printf("active_count: %i\n", info->active.count);
printf("active_memory: %i Kb\n", info->active.mem_total);
printf("cache_count: %i\n", info->cached.count);
printf("cache_memory: %i Kb\n", info->cached.mem_total);
p = (unsigned char *)info;
p += sizeof(Op_Getinfo_Reply);
for (i = 0; i < j; i++)
{
Op_Getinfo_Item it;
char *file, *key, buf[512];
struct tm *ltm;
itt = (Op_Getinfo_Item *)p;
memcpy(&it, itt, sizeof(Op_Getinfo_Item));
file = p + sizeof(Op_Getinfo_Item);
key = file + strlen(file) + 1;
printf("-IMAGE- [#%i]\n", i);
printf(" file : %s\n", file);
printf(" key : %s\n", key);
printf(" size : %i x %i\n", it.w, it.h);
printf(" active : %i\n", (int)it.active);
printf(" memory used: %i bytes (%i Kb)\n", it.memory_footprint, (it.memory_footprint + 1023) / 1024);
printf(" has alpha : %i\n", (int)it.alpha);
printf(" data loaded: %i\n", (int)it.data_loaded);
printf(" dead : %i\n", (int)it.dead);
printf(" useless : %i\n", (int)it.useless);
printf(" image refs : %i\n", it.refcount);
printf(" data refs : %i\n", it.data_refcount);
printf(" header load: %1.5f sec\n", it.head_load_time);
printf(" data load : %1.5f sec\n", it.data_load_time);
if (it.cached_time == 0)
printf(" cached at : N/A\n");
else
{
ltm = localtime(&(it.cached_time));
if (ltm)
{
strftime(buf, sizeof(buf), "%Y.%m.%d %T", ltm);
printf(" cached at : %s\n", buf);
}
}
ltm = localtime(&(it.file_mod_time));
if (ltm)
{
strftime(buf, sizeof(buf), "%Y.%m.%d %T", ltm);
printf(" file mod at: %s\n", buf);
}
ltm = localtime(&(it.file_checked_time));
if (ltm)
{
strftime(buf, sizeof(buf), "%Y.%m.%d %T", ltm);
printf(" file check : %s\n", buf);
}
p += sizeof(Op_Getinfo_Item) + it.file_key_size;
}
free(info);
printf("-OK-\n");
}
}
*/
evas_cserve_shutdown();
evas_shutdown();
return 0;

View File

@ -296,6 +296,13 @@ typedef enum _Evas_Border_Fill_Mode
EVAS_BORDER_FILL_SOLID = 2
} Evas_Border_Fill_Mode;
typedef enum _Evas_Image_Scale_Hint
{
EVAS_IMAGE_SCALE_HINT_NONE = 0,
EVAS_IMAGE_SCALE_HINT_DYNAMIC = 1,
EVAS_IMAGE_SCALE_HINT_STATIC = 2
} Evas_Image_Scale_Hint;
struct _Evas_Engine_Info /** Generic engine information. Generic info is useless */
{
int magic; /**< Magic number */
@ -599,6 +606,8 @@ extern "C" {
EAPI Evas_Colorspace evas_object_image_colorspace_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void evas_object_image_native_surface_set (Evas_Object *obj, Evas_Native_Surface *surf) EINA_ARG_NONNULL(1, 2);
EAPI Evas_Native_Surface *evas_object_image_native_surface_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void evas_object_image_scale_hint_set (Evas_Object *obj, Evas_Image_Scale_Hint hint) EINA_ARG_NONNULL(1);
EAPI Evas_Image_Scale_Hint evas_object_image_scale_hint_get (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
/* image cache */
EAPI void evas_image_cache_flush (Evas *e) EINA_ARG_NONNULL(1);

View File

@ -53,6 +53,8 @@ struct _Evas_Object_Image
void *get_pixels_data;
} func;
Evas_Image_Scale_Hint scale_hint;
void *engine_data;
unsigned char changed : 1;
@ -1802,6 +1804,42 @@ evas_object_image_native_surface_get(const Evas_Object *obj)
o->engine_data);
}
/**
* To be documented.
*
* FIXME: To be fixed.
*
*/
EAPI void
evas_object_image_scale_hint_set(Evas_Object *obj, Evas_Image_Scale_Hint hint)
{
Evas_Object_Image *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return;
MAGIC_CHECK_END();
o = (Evas_Object_Image *)(obj->object_data);
MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
return;
MAGIC_CHECK_END();
o->scale_hint = hint;
}
EAPI Evas_Image_Scale_Hint
evas_object_image_scale_hint_get(const Evas_Object *obj)
{
Evas_Object_Image *o;
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
return EVAS_IMAGE_SCALE_HINT_NONE;
MAGIC_CHECK_END();
o = (Evas_Object_Image *)(obj->object_data);
MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
return EVAS_IMAGE_SCALE_HINT_NONE;
MAGIC_CHECK_END();
return o->scale_hint;
}
/**
* To be documented.
*
@ -2137,6 +2175,9 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
}
o->dirty_pixels = 0;
}
obj->layer->evas->engine.func->image_scale_hint_set(output,
o->engine_data,
o->scale_hint);
o->engine_data = obj->layer->evas->engine.func->image_border_set(output, o->engine_data,
o->cur.border.l, o->cur.border.r,
o->cur.border.t, o->cur.border.b);

View File

@ -63,6 +63,7 @@ struct _Server
int (*func) (void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *data);
void *data;
pid_t pid;
int server_id;
};
struct _Client
@ -116,6 +117,7 @@ enum
typedef struct
{
pid_t pid;
int server_id;
} Op_Init;
typedef struct
{
@ -128,6 +130,7 @@ typedef struct
typedef struct
{
void *handle;
int server_id;
struct {
int id;
int offset;
@ -141,14 +144,17 @@ typedef struct
typedef struct
{
void *handle;
int server_id;
} Op_Unload;
typedef struct
{
void *handle;
int server_id;
} Op_Unloaddata;
typedef struct
{
void *handle;
int server_id;
} Op_Loaddata;
typedef struct
{
@ -161,6 +167,7 @@ typedef struct
typedef struct
{
void *handle;
int server_id;
} Op_Preload;
typedef struct
{
@ -174,6 +181,7 @@ typedef struct
typedef struct
{
void *handle;
int server_id;
} Op_Forcedunload;
typedef struct
{
@ -196,6 +204,31 @@ typedef struct
double saved_time_image_header_load;
double saved_time_image_data_load;
} Op_Getstats_Reply;
typedef struct
{
struct {
int mem_total;
int count;
} active, cached;
} Op_Getinfo_Reply; // + N active Info Items + N cached items
typedef struct
{
int file_key_size;
int w, h;
time_t file_mod_time;
time_t file_checked_time;
time_t cached_time;
int refcount;
int data_refcount;
int memory_footprint;
double head_load_time;
double data_load_time;
Eina_Bool alpha : 1;
Eina_Bool data_loaded : 1;
Eina_Bool active : 1;
Eina_Bool dead : 1;
Eina_Bool useless : 1;
} Op_Getinfo_Item; // + "file""key"
// for clients to connect to cserve
@ -210,6 +243,7 @@ EAPI void evas_cserve_image_free(Image_Entry *ie);
EAPI Eina_Bool evas_cserve_config_get(Op_Getconfig_Reply *config);
EAPI Eina_Bool evas_cserve_config_set(Op_Setconfig *config);
EAPI Eina_Bool evas_cserve_stats_get(Op_Getstats_Reply *stats);
EAPI Op_Getinfo_Reply *evas_cserve_info_get(void);
// for the server
EAPI Server *evas_cserve_server_add(void);

View File

@ -3,6 +3,9 @@
#ifdef EVAS_CSERVE
static Server *cserve = NULL;
static int csrve_init = 0;
static void
pipe_handler(int x, siginfo_t *info, void *data)
{
@ -85,12 +88,16 @@ server_send(Server *s, int opcode, int size, unsigned char *data)
if (num < 0)
{
pipe_handle(0);
if (cserve) server_disconnect(cserve);
cserve = NULL;
return 0;
}
num = write(s->fd, data, size);
if (num < 0)
{
pipe_handle(0);
if (cserve) server_disconnect(cserve);
cserve = NULL;
return 0;
}
pipe_handle(0);
@ -100,22 +107,38 @@ server_send(Server *s, int opcode, int size, unsigned char *data)
static unsigned char *
server_read(Server *s, int *opcode, int *size)
{
int ints[2], num;
int ints[2], num, left;
unsigned char *data;
num = read(s->fd, ints, sizeof(int) * 2);
if (num != (sizeof(int) * 2)) return NULL;
if (num != (sizeof(int) * 2))
{
if (cserve) server_disconnect(cserve);
cserve = NULL;
return NULL;
}
*size = ints[0];
*opcode = ints[1];
if ((*size < 0) || (*size > (1024 * 1024))) return NULL;
data = malloc(*size);
if (!data) return NULL;
num = read(s->fd, data, *size);
if (num != *size)
if (num < 0)
{
free(data);
return NULL;
}
left = *size - num;
while (left > 0)
{
num = read(s->fd, data + (*size - left), left);
if (num < 0)
{
free(data);
return NULL;
}
left -= num;
}
return data;
}
@ -127,20 +150,21 @@ server_init(Server *s)
int size;
msg.pid = getpid();
msg.server_id = 0;
if (!server_send(s, OP_INIT, sizeof(msg), (unsigned char *)(&msg)))
return 0;
rep = (Op_Init *)server_read(s, &opcode, &size);
if (rep)
if ((rep) && (opcode == OP_INIT) && (size == sizeof(Op_Init)))
{
s->pid = rep->pid;
s->server_id = rep->server_id;
free(rep);
return 1;
}
return 1;
if (rep) free(rep);
return 0;
}
static Server *cserve = NULL;
static int csrve_init = 0;
EAPI Eina_Bool
evas_cserve_init(void)
{
@ -150,7 +174,7 @@ evas_cserve_init(void)
if (!cserve) return 0;
if (!server_init(cserve))
{
server_disconnect(cserve);
if (cserve) server_disconnect(cserve);
cserve = NULL;
return 0;
}
@ -182,7 +206,7 @@ server_reinit(void)
{
if (!server_init(cserve))
{
server_disconnect(cserve);
if (cserve) server_disconnect(cserve);
cserve = NULL;
}
}
@ -241,7 +265,10 @@ evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_
ie->flags.alpha = rep->image.alpha;
ie->data1 = rep->handle;
}
if (rep) free(rep);
if (ie->data1 == NULL) return 0;
if (cserve)
ie->server_id = cserve->server_id;
return 1;
}
@ -256,18 +283,31 @@ evas_cserve_image_data_load(Image_Entry *ie)
else return 0;
if (!cserve) return 0;
if (ie->data1 == NULL) return 0;
if (cserve->server_id != ie->server_id)
{
ie->data1 = NULL;
if (!evas_cserve_image_load(ie, ie->file, ie->key, &(ie->load_opts)))
return 0;
}
memset(&msg, 0, sizeof(msg));
msg.handle = ie->data1;
msg.server_id = cserve->server_id;
if (!server_send(cserve, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg)))
return 0;
if (!cserve) return 0;
rep = (Op_Loaddata_Reply *)server_read(cserve, &opcode, &size);
if ((rep) && (opcode == OP_LOADDATA) && (size == sizeof(Op_Loaddata_Reply)))
{
if (rep->mem.size <= 0) return 0;
if (rep->mem.size <= 0)
{
free(rep);
return 0;
}
ie->data2 = evas_cserve_mem_open(cserve->pid, rep->mem.id, NULL, rep->mem.size, 0);
free(rep);
return 1;
}
if (rep) free(rep);
return 0;
}
@ -282,8 +322,13 @@ evas_cserve_image_free(Image_Entry *ie)
if (ie->data1 == NULL) return;
memset(&msg, 0, sizeof(msg));
msg.handle = ie->data1;
msg.server_id = cserve->server_id;
if (ie->data2) evas_cserve_image_unload(ie);
server_send(cserve, OP_UNLOAD, sizeof(msg), (unsigned char *)(&msg));
if (cserve)
{
if (ie->server_id == cserve->server_id)
server_send(cserve, OP_UNLOAD, sizeof(msg), (unsigned char *)(&msg));
}
ie->data1 = NULL;
}
@ -298,9 +343,11 @@ evas_cserve_image_unload(Image_Entry *ie)
if (ie->data1 == NULL) return;
memset(&msg, 0, sizeof(msg));
msg.handle = ie->data1;
msg.server_id = cserve->server_id;
if (ie->data2) evas_cserve_mem_close(ie->data2);
ie->data2 = NULL;
server_send(cserve, OP_UNLOADDATA, sizeof(msg), (unsigned char *)(&msg));
if (ie->server_id == cserve->server_id)
server_send(cserve, OP_UNLOADDATA, sizeof(msg), (unsigned char *)(&msg));
}
EAPI void
@ -314,9 +361,11 @@ evas_cserve_image_useless(Image_Entry *ie)
if (ie->data1 == NULL) return;
memset(&msg, 0, sizeof(msg));
msg.handle = ie->data1;
msg.server_id = cserve->server_id;
if (ie->data2) evas_cserve_mem_close(ie->data2);
ie->data2 = NULL;
server_send(cserve, OP_USELESSDATA, sizeof(msg), (unsigned char *)(&msg));
if (ie->server_id == cserve->server_id)
server_send(cserve, OP_USELESSDATA, sizeof(msg), (unsigned char *)(&msg));
}
EAPI Eina_Bool
@ -333,8 +382,10 @@ evas_cserve_config_get(Op_Getconfig_Reply *config)
if ((rep) && (opcode == OP_GETCONFIG) && (size == sizeof(Op_Getconfig_Reply)))
{
memcpy(config, rep, sizeof(Op_Getconfig_Reply));
free(rep);
return 1;
}
if (rep) free(rep);
return 0;
}
@ -362,9 +413,30 @@ evas_cserve_stats_get(Op_Getstats_Reply *stats)
if ((rep) && (opcode == OP_GETSTATS) && (size == sizeof(Op_Getstats_Reply)))
{
memcpy(stats, rep, sizeof(Op_Getstats_Reply));
free(rep);
return 1;
}
if (rep) free(rep);
return 0;
}
EAPI Op_Getinfo_Reply *
evas_cserve_info_get(void)
{
Op_Getinfo_Reply *rep;
int opcode;
int size;
if (csrve_init > 0) server_reinit();
else return NULL;
if (!cserve) return NULL;
if (!server_send(cserve, OP_GETINFO, 0, NULL)) return NULL;
rep = (Op_Getinfo_Reply *)server_read(cserve, &opcode, &size);
if ((rep) && (opcode == OP_GETINFO) && (size >= sizeof(Op_Getinfo_Reply)))
{
return rep;
}
if (rep) free(rep);
return NULL;
}
#endif

View File

@ -60,7 +60,15 @@ evas_cserve_server_add(void)
EAPI void
evas_cserve_server_del(Server *s)
{
/* FIXME: del clients! */
Client *c;
EINA_LIST_FREE(s->clients, c)
{
close(c->fd);
if (c->buf) free(c->buf);
if (c->inbuf) free(c->inbuf);
free(c);
}
close(s->fd);
unlink(s->socket_path);
free(s->socket_path);
@ -102,7 +110,7 @@ client_flush(Client *c)
c->dead = 1;
return;
}
if (num != c->bufsize)
if (num < c->bufsize)
{
unsigned char *buf;
@ -130,11 +138,11 @@ client_buf_add(Client *c, unsigned char *data, int size)
{
int newsize;
unsigned char *buf;
newsize = c->bufalloc + size;
newsize = c->bufsize + size;
if (newsize > c->bufalloc)
{
c->bufalloc + newsize + 1024;
c->bufalloc = newsize + 16384;
buf = realloc(c->buf, c->bufalloc);
if (buf) c->buf = buf;
else return;
@ -148,9 +156,16 @@ client_write(Client *c, unsigned char *data, int size)
{
int num;
num = write(c->fd, data, size);
if (num != size)
client_buf_add(c, data + num, size - num);
if (!c->buf)
{
num = write(c->fd, data, size);
if (num != size)
client_buf_add(c, data + num, size - num);
}
else
{
client_buf_add(c, data, size);
}
}
EAPI void

View File

@ -250,7 +250,7 @@ _cache_prune(Scaleitem *notsci, Evas_Bool copies_only)
if (copies_only)
{
while ((sci) && (!sci->parent_im->image.data))
sci = ((Eina_Inlist *)sci)->next;
sci = (Scaleitem *)(((Eina_Inlist *)sci)->next);
if (!sci) return;
}
if (sci == notsci) return;
@ -352,6 +352,7 @@ evas_common_rgba_image_scalecache_prepare(Image_Entry *ie, RGBA_Image *dst,
// dst_region_x, dst_region_y, dst_region_w, dst_region_h,
// smooth);
if ((sci->usage >= MIN_SCALE_USES)
&& (ie->scale_hint != EVAS_IMAGE_SCALE_HINT_DYNAMIC)
// && (sci->usage_count > (use_counter - MIN_SCALE_AGE_GAP))
)
{
@ -475,8 +476,10 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
int size, osize, used;
size = dst_region_w * dst_region_h;
if (((dst_region_w > 640) || (dst_region_h > 640)) &&
(size > (480 * 480)))
if (((((dst_region_w > 640) || (dst_region_h > 640)) &&
(size > (480 * 480))) ||
(ie->scale_hint == EVAS_IMAGE_SCALE_HINT_STATIC)) &&
(ie->scale_hint != EVAS_IMAGE_SCALE_HINT_DYNAMIC))
{
Eina_List *l;
Scaleitem *sci2;

View File

@ -471,7 +471,9 @@ struct _Image_Entry
#endif
Image_Entry_Flags flags;
Evas_Image_Scale_Hint scale_hint;
void *data1, *data2;
int server_id;
};
struct _Engine_Image_Entry

View File

@ -682,6 +682,8 @@ struct _Evas_Func
/* void (*image_rotation_set) (void *data, void *image); */
void (*image_scale_hint_set) (void *data, void *image, int hint);
int (*image_scale_hint_get) (void *data, void *image);
};
struct _Evas_Image_Load_Func

View File

@ -95,7 +95,9 @@ static void *eng_image_native_get(void *data, void *image);
static void eng_image_cache_flush(void *data);
static void eng_image_cache_set(void *data, int bytes);
static int eng_image_cache_get(void *data);
static void eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint);
static int eng_image_scale_hint_get(void *data __UNUSED__, void *image);
static void *eng_font_load(void *data, char *name, int size);
static void *eng_font_memory_load(void *data, char *name, int size, const void *fdata, int fdata_size);
static void *eng_font_add(void *data, void *font, char *name, int size);
@ -239,7 +241,10 @@ static Evas_Func eng_func =
eng_font_cache_get,
eng_font_hinting_set,
eng_font_hinting_can_hint
eng_font_hinting_can_hint,
eng_image_scale_hint_set,
eng_image_scale_hint_get
};
static void *
@ -1257,6 +1262,17 @@ eng_image_cache_get(void *data)
return evas_common_image_get_cache();
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void *
eng_font_load(void *data, char *name, int size)
{

View File

@ -375,6 +375,17 @@ eng_image_border_get(void *data, void *image, int *l, int *r, int *t, int *b)
evas_direct3d_image_border_get(re->d3d, image, l, t, r, b);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
{
@ -558,6 +569,10 @@ module_open(Evas_Module *em)
ORD(image_border_get);
ORD(font_draw);
ORD(font_free);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/*
ORD(gradient2_color_np_stop_insert);
ORD(gradient2_clear);

View File

@ -1600,6 +1600,17 @@ evas_engine_dfb_image_comment_get(void *data __UNUSED__, void *image, char *key
return im->info.comment;
}
static void
evas_engine_dfb_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
evas_engine_dfb_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
EAPI int
module_open(Evas_Module *em)
{
@ -1648,6 +1659,8 @@ module_open(Evas_Module *em)
ORD(rectangle_draw);
ORD(polygon_draw);
ORD(gradient_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;

View File

@ -883,6 +883,17 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
smooth);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text)
{
@ -984,6 +995,10 @@ module_open(Evas_Module *em)
ORD(image_native_set);
ORD(image_native_get);
ORD(font_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;

View File

@ -1013,6 +1013,17 @@ eng_image_draw(void *data, void *context, void *surface __UNUSED__, void *image,
smooth);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
eng_font_draw(void *data, void *context, void *surface __UNUSED__, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
{
@ -1169,6 +1180,10 @@ module_open(Evas_Module *em)
ORD(image_native_set);
ORD(image_native_get);
ORD(font_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;

View File

@ -1101,6 +1101,18 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
CGContextDrawImage(re->ctx, CGRectMake(dst_x, dst_y, dst_w, dst_h), im->cgim);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
#pragma mark Text Manipulation & Drawing
static Evas_Quartz_Font *
@ -1491,6 +1503,9 @@ module_open(Evas_Module *em)
ORD(rectangle_draw);
ORD(setup);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out our api */
em->functions = (void *)(&func);
return 1;

View File

@ -647,6 +647,17 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
smooth);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
eng_image_cache_flush(void *data __UNUSED__)
{
@ -959,7 +970,9 @@ static Evas_Func func =
eng_font_cache_get,
/* font hinting functions */
eng_font_hinting_set,
eng_font_hinting_can_hint
eng_font_hinting_can_hint,
eng_image_scale_hint_set,
eng_image_scale_hint_get
/* FUTURE software generic calls go here */
};

View File

@ -821,6 +821,18 @@ evas_engine_sdl16_image_draw(void *data __UNUSED__, void *context, void *surface
SDL_UnlockSurface(dst->surface);
}
static void
evas_engine_sdl16_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
evas_engine_sdl16_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
evas_engine_sdl16_image_cache_flush(void *data)
{
@ -1058,6 +1070,10 @@ module_open(Evas_Module *em)
ORD(line_draw);
ORD(rectangle_draw);
ORD(polygon_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;

View File

@ -777,6 +777,26 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
}
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
Image_Entry *im;
if (!image) return;
im = image;
im->scale_hint = hint;
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
Image_Entry *im;
if (!image) return EVAS_IMAGE_SCALE_HINT_NONE;
im = image;
return im->scale_hint;
}
static void
eng_image_cache_flush(void *data __UNUSED__)
{
@ -1087,7 +1107,9 @@ static Evas_Func func =
eng_font_cache_get,
/* font hinting functions */
eng_font_hinting_set,
eng_font_hinting_can_hint
eng_font_hinting_can_hint,
eng_image_scale_hint_set,
eng_image_scale_hint_get
/* FUTURE software generic calls go here */
};

View File

@ -621,6 +621,17 @@ evas_engine_sdl_image_draw(void *data, void *context, void *surface, void *image
SDL_UnlockSurface(dst->surface);
}
static void
evas_engine_sdl_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
evas_engine_sdl_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
evas_engine_sdl_image_cache_flush(void *data)
{
@ -856,6 +867,10 @@ EAPI int module_open(Evas_Module *em)
ORD(rectangle_draw);
ORD(polygon_draw);
ORD(gradient_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;

View File

@ -1325,6 +1325,18 @@ eng_image_draw(void *data, void *context, void *surface, void *image, int src_x,
smooth);
}
static void
eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
{
}
static int
eng_image_scale_hint_get(void *data __UNUSED__, void *image)
{
return EVAS_IMAGE_SCALE_HINT_NONE;
}
static void
eng_image_cache_flush(void *data)
{
@ -1479,6 +1491,10 @@ module_open(Evas_Module *em)
ORD(image_cache_set);
ORD(image_cache_get);
ORD(font_draw);
ORD(image_scale_hint_set);
ORD(image_scale_hint_get);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;