// fixme:'s
//
-// add ops to get internal cache state (both)
// preload - make it work (both)
//
static time_t t_now = 0;
+static int server_id = 0;
+
static Evas_Cache_Image *cache = NULL;
static Eina_Hash *active_images = 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)
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;
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;
}
{
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
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;
{
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;
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();
}
{
if (img->active) return;
cache_images = eina_list_remove(cache_images, img);
+ cache_usage -= img->usage;
img_free(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;
{
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;
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;
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)
{
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;
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:
rep = (Op_Loaddata *)data;
img = rep->handle;
- if (img->mem)
- {
- img->stats.load2saved++;
- stats_update();
- }
- else
- img_loaddata(img);
- memset(&msg, 0, sizeof(msg));
- if (img->mem)
+ if ((img) && (rep->server_id == server_id))
{
- 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;
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:
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:
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:
{
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:
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;
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:
{
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();
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;
evas_cserve_mem_free(stat_mem);
stat_mem = NULL;
}
-
+ if (s) evas_cserve_server_del(s);
evas_shutdown();
eina_shutdown();
return 0;
"\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);
}
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);
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);
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;
+ 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;
- m = ie->data2;
- printf("first pixel: %08x\n", *((int *)m->data));
- printf("load data ok\n");
-// evas_cserve_image_free(ie);
+ 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;
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 */
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);
void *get_pixels_data;
} func;
+ Evas_Image_Scale_Hint scale_hint;
+
void *engine_data;
unsigned char changed : 1;
*
*/
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.
+ *
+ * FIXME: To be fixed.
+ *
+ */
+EAPI void
evas_image_cache_flush(Evas *e)
{
MAGIC_CHECK(e, Evas, MAGIC_EVAS);
}
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);
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
typedef struct
{
pid_t pid;
+ int server_id;
} Op_Init;
typedef struct
{
typedef struct
{
void *handle;
+ int server_id;
struct {
int id;
int offset;
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
{
typedef struct
{
void *handle;
+ int server_id;
} Op_Preload;
typedef struct
{
typedef struct
{
void *handle;
+ int server_id;
} Op_Forcedunload;
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
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);
#ifdef EVAS_CSERVE
+static Server *cserve = NULL;
+static int csrve_init = 0;
+
static void
pipe_handler(int x, siginfo_t *info, void *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);
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;
}
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)
{
if (!cserve) return 0;
if (!server_init(cserve))
{
- server_disconnect(cserve);
+ if (cserve) server_disconnect(cserve);
cserve = NULL;
return 0;
}
{
if (!server_init(cserve))
{
- server_disconnect(cserve);
+ if (cserve) server_disconnect(cserve);
cserve = NULL;
}
}
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;
}
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;
}
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;
}
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
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
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;
}
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
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);
c->dead = 1;
return;
}
- if (num != c->bufsize)
+ if (num < c->bufsize)
{
unsigned char *buf;
{
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;
{
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
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;
// 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))
)
{
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;
#endif
Image_Entry_Flags flags;
+ Evas_Image_Scale_Hint scale_hint;
void *data1, *data2;
+ int server_id;
};
struct _Engine_Image_Entry
/* 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
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);
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 *
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)
{
}
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)
{
Render_Engine *re = (Render_Engine *)data;
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);
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)
{
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;
}
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)
{
Render_Engine *re;
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;
}
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)
{
Render_Engine *re;
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;
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 *
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;
}
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__)
{
evas_cache_image_flush(evas_common_soft16_image_cache_get());
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 */
};
}
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)
{
Render_Engine *re = (Render_Engine*) data;
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;
}
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__)
{
int tmp_size;
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 */
};
}
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)
{
Render_Engine *re = (Render_Engine*) data;
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;
}
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)
{
Render_Engine *re;
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;