Evas/cserve2: Merge branch 'devs/jpeg/cserve2'

Improve stability, performance and overall support of
evas cserve2.

In particular:
- Implement shared indexes and memory pools to share cserve's
  internal state with all clients. Apps can then scan these
  indexes and avoid waiting for socket responses when loading
  resources.
- Implement crash resiliency in evas. If cserve2 crashes, apps
  can safely reconnect and continue working as if nothing
  happened.
- Implement support for the GL engine (very basic support so
  far, "just works").
- Improve performance by reusing the scalecache logic.
This commit is contained in:
Jean-Philippe Andre 2013-10-28 15:50:57 +09:00
commit 7338164468
33 changed files with 6434 additions and 1775 deletions

View File

@ -999,7 +999,8 @@ bin/evas/dummy_slave
bin_PROGRAMS += \
bin/evas/evas_cserve2_client \
bin/evas/evas_cserve2_usage \
bin/evas/evas_cserve2_debug
bin/evas/evas_cserve2_debug \
bin/evas/evas_cserve2_shm_debug
bin_evas_evas_cserve2_SOURCES = \
bin/evas/evas_cserve2.h \
@ -1013,6 +1014,7 @@ bin/evas/evas_cserve2_requests.c \
bin/evas/evas_cserve2_fonts.c \
bin/evas/evas_cserve2_scale.c \
bin/evas/evas_cserve2_main_loop_linux.c \
bin/evas/evas_cserve2_index.c \
lib/evas/cserve2/evas_cs2_utils.h \
lib/evas/cserve2/evas_cs2_utils.c
@ -1055,6 +1057,15 @@ bin_evas_evas_cserve2_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
bin_evas_evas_cserve2_debug_LDADD = @USE_EINA_LIBS@
bin_evas_evas_cserve2_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
bin_evas_evas_cserve2_shm_debug_SOURCES = \
bin/evas/evas_cserve2_shm_debug.c
bin_evas_evas_cserve2_shm_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_srcdir)/src/lib/evas \
-I$(top_srcdir)/src/lib/evas/cserve2 \
@EINA_CFLAGS@
bin_evas_evas_cserve2_shm_debug_LDADD = @USE_EINA_LIBS@
bin_evas_evas_cserve2_shm_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
bin_evas_evas_cserve2_slave_SOURCES = \
bin/evas/evas_cserve2_slave.c \
bin/evas/evas_cserve2_utils.c \

View File

@ -4,22 +4,54 @@
#include <Eina.h>
#include "evas_cs2.h"
#ifndef CSERVE2_LOG_LEVEL
#define CSERVE2_LOG_LEVEL 4
#endif
#ifdef CRIT
#undef CRIT
#endif
#if CSERVE2_LOG_LEVEL >= 0
#define CRIT(...) EINA_LOG_DOM_CRIT(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#else
#define CRIT(...) do {} while(0)
#endif
#ifdef ERR
#undef ERR
#endif
#if CSERVE2_LOG_LEVEL >= 1
#define ERR(...) EINA_LOG_DOM_ERR(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#ifdef DBG
#undef DBG
#else
#define ERR(...) do {} while(0)
#endif
#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#ifdef WRN
#undef WRN
#endif
#if CSERVE2_LOG_LEVEL >= 2
#define WRN(...) EINA_LOG_DOM_WARN(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#else
#define WRN(...) do {} while(0)
#endif
#ifdef INF
#undef INF
#endif
#if CSERVE2_LOG_LEVEL >= 3
#define INF(...) EINA_LOG_DOM_INFO(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#else
#define INF(...) do {} while(0)
#endif
#ifdef DBG
#undef DBG
#endif
#if CSERVE2_LOG_LEVEL >= 4
#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve2_bin_log_dom, __VA_ARGS__)
#else
#define DBG(...) do {} while(0)
#endif
#define DEBUG_LOAD_TIME 1
@ -30,6 +62,8 @@ extern Eina_Prefix *_evas_cserve2_pfx;
typedef struct _Slave Slave;
typedef struct _Slave_Thread_Data Slave_Thread_Data;
typedef struct _Shm_Handle Shm_Handle;
typedef struct _Shared_Array Shared_Array;
typedef struct _Shared_Mempool Shared_Mempool;
typedef enum {
FD_READ = 1,
@ -69,8 +103,17 @@ typedef enum {
} Slave_Command;
struct _Slave_Msg_Image_Open {
Eina_Bool has_loader_data : 1;
// Optionally followed by:
struct {
struct {
unsigned int x, y, w, h;
} region;
double dpi;
unsigned int w, h;
int scale_down_by;
Eina_Bool orientation;
} lo;
// const char path[];
// const char key[];
// const char loader[];
};
@ -103,6 +146,7 @@ struct _Slave_Msg_Image_Load {
struct _Slave_Msg_Image_Loaded {
int w, h;
Eina_Bool alpha : 1;
Eina_Bool alpha_sparse : 1;
};
@ -140,14 +184,13 @@ struct _Slave_Msg_Font_Glyphs_Load {
unsigned int *glyphs;
} glyphs;
struct {
Shm_Handle *shm;
unsigned int usage;
unsigned int nglyphs;
Shared_Mempool *mempool;
} cache;
};
struct _Slave_Msg_Glyph {
unsigned int index;
unsigned int buffer_id;
unsigned int offset;
unsigned int size;
unsigned int rows;
@ -159,21 +202,13 @@ struct _Slave_Msg_Glyph {
typedef struct _Slave_Msg_Glyph Slave_Msg_Glyph;
struct _Slave_Msg_Font_Cache {
unsigned int nglyphs;
Slave_Msg_Glyph *glyphs;
Shm_Handle *shm;
unsigned int usage;
};
typedef struct _Slave_Msg_Font_Cache Slave_Msg_Font_Cache;
struct _Slave_Msg_Font_Glyphs_Loaded {
unsigned int ncaches;
Shared_Mempool *mempool;
unsigned int gl_load_time;
unsigned int gl_render_time;
unsigned int gl_slave_time;
Slave_Msg_Font_Cache **caches;
Slave_Msg_Glyph *glyphs;
unsigned int nglyphs;
};
typedef struct _Slave_Msg_Font_Load Slave_Msg_Font_Load;
@ -229,6 +264,7 @@ void cserve2_client_del(Client *client);
void cserve2_client_deliver(Client *client);
void cserve2_client_error_send(Client *client, unsigned int rid, int error_code);
ssize_t cserve2_client_send(Client *client, const void *data, size_t size);
void cserve2_index_list_send(int generation_id, const char *strings_index_path, const char *strings_entries_path, const char *files_index_path, const char *images_index_path, const char *fonts_index_path, Client *client);
Eina_Bool cserve2_fd_watch_add(int fd, Fd_Flags flags, Fd_Watch_Cb cb, const void *data);
Eina_Bool cserve2_fd_watch_del(int fd);
@ -260,15 +296,18 @@ void cserve2_message_handler(int fd, Fd_Flags flags, void *data);
void cserve2_shm_init();
void cserve2_shm_shutdown();
Shm_Handle *cserve2_shm_request(const char *infix, size_t size);
Shm_Handle *cserve2_shm_segment_request(Shm_Handle *shm, size_t size);
Shm_Handle *cserve2_shm_resize(Shm_Handle *shm, size_t newsize);
void cserve2_shm_unref(Shm_Handle *shm);
const char *cserve2_shm_name_get(const Shm_Handle *shm);
int cserve2_shm_id_get(const Shm_Handle *shm);
off_t cserve2_shm_map_offset_get(const Shm_Handle *shm);
off_t cserve2_shm_offset_get(const Shm_Handle *shm);
size_t cserve2_shm_map_size_get(const Shm_Handle *shm);
size_t cserve2_shm_size_get(const Shm_Handle *shm);
void *cserve2_shm_map(Shm_Handle *shm);
void cserve2_shm_unmap(Shm_Handle *shm);
size_t cserve2_shm_size_normalize(size_t size);
size_t cserve2_shm_size_normalize(size_t size, size_t align);
void cserve2_command_run(Client *client, Message_Type type);
@ -279,10 +318,10 @@ void cserve2_cache_init(void);
void cserve2_cache_shutdown(void);
void cserve2_cache_client_new(Client *client);
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, Evas_Image_Load_Opts *lo);
void cserve2_cache_file_close(Client *client, unsigned int client_file_id);
int cserve2_cache_image_entry_create(Client *client, int rid, unsigned int file_id, unsigned int image_id, Evas_Image_Load_Opts *opts);
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);
int cserve2_cache_image_entry_create(Client *client, int rid, unsigned int client_file_id, unsigned int image_id, const Evas_Image_Load_Opts *opts);
void cserve2_rgba_image_scale_do(void *src_data, int src_full_w, int src_full_h, void *dst_data, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int alpha, int smooth);
void cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned int rid);
void cserve2_cache_image_preload(Client *client, unsigned int client_image_id, unsigned int rid);
void cserve2_cache_image_unload(Client *client, unsigned int client_image_id);
@ -302,6 +341,8 @@ void cserve2_request_cancel(Slave_Request *req, Client *client, Error_Type err);
void cserve2_request_cancel_all(Slave_Request *req, Error_Type err);
void cserve2_requests_init(void);
void cserve2_requests_shutdown(void);
void cserve2_request_dependents_drop(Slave_Request *req, Slave_Request_Type type);
void cserve2_entry_request_drop(void *data, Slave_Request_Type type);
void cserve2_font_init(void);
void cserve2_font_shutdown(void);
@ -309,4 +350,57 @@ void *cserve2_font_slave_cb(Slave_Thread_Data *sd, Slave_Command *cmd, const voi
void cserve2_font_source_ft_free(void *fontsource);
void cserve2_font_ft_free(void *fontinfo);
// Shared buffers & indexes
void cserve2_shared_index_init(void);
void cserve2_shared_index_shutdown(void);
typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *sa,
const void *elem,
void *user_data);
// Shared arrays (arrays of fixed size object)
Shared_Array *cserve2_shared_array_new(int tag, int generation_id, int elemsize, int initcount);
const char *cserve2_shared_array_name_get(Shared_Array *sa);
void cserve2_shared_array_del(Shared_Array *sa);
int cserve2_shared_array_size_get(Shared_Array *sa);
int cserve2_shared_array_count_get(Shared_Array *sa);
int cserve2_shared_array_map_size_get(Shared_Array *sa);
int cserve2_shared_array_item_size_get(Shared_Array *sa);
int cserve2_shared_array_generation_id_get(Shared_Array *sa);
int cserve2_shared_array_generation_id_set(Shared_Array *sa, int generation_id);
int cserve2_shared_array_size_set(Shared_Array *sa, int newcount);
int cserve2_shared_array_item_new(Shared_Array *sa);
void *cserve2_shared_array_item_data_get(Shared_Array *sa, int elemid);
Shared_Array *cserve2_shared_array_repack(Shared_Array *sa, int generation_id,
Shared_Array_Repack_Skip_Cb skip,
Eina_Compare_Cb cmp, void *user_data);
int cserve2_shared_array_item_find(Shared_Array *sa, void *data,
Eina_Compare_Cb cmp);
void *cserve2_shared_array_item_data_find(Shared_Array *sa, void *data,
Eina_Compare_Cb cmp);
int cserve2_shared_array_foreach(Shared_Array *sa, Eina_Each_Cb cb, void *data);
// Shared buffers and memory pools
Shared_Mempool *cserve2_shared_mempool_new(int indextag, int index_elemsize, int generation_id, int initsize);
void cserve2_shared_mempool_del(Shared_Mempool *sm);
int cserve2_shared_mempool_buffer_new(Shared_Mempool *sm, int size);
int cserve2_shared_mempool_buffer_ref(Shared_Mempool *sm, int bufferid);
void cserve2_shared_mempool_buffer_del(Shared_Mempool *sm, int bufferid);
void *cserve2_shared_mempool_buffer_get(Shared_Mempool *sm, int bufferid);
int cserve2_shared_mempool_buffer_offset_get(Shared_Mempool *sm, int bufferid);
size_t cserve2_shared_mempool_size_get(Shared_Mempool *sm);
const char *cserve2_shared_mempool_name_get(Shared_Mempool *sm);
int cserve2_shared_mempool_generation_id_get(Shared_Mempool *sm);
int cserve2_shared_mempool_generation_id_set(Shared_Mempool *sm, int generation_id);
Shared_Array *cserve2_shared_mempool_index_get(Shared_Mempool *sm);
// Shared strings
const char *cserve2_shared_strings_table_name_get();
const char *cserve2_shared_strings_index_name_get();
int cserve2_shared_string_add(const char *str);
int cserve2_shared_string_ref(int id);
void cserve2_shared_string_del(int id);
const char *cserve2_shared_string_get(int id);
int cserve2_shared_strings_repack(Shared_Array_Repack_Skip_Cb skip, Eina_Compare_Cb cmp);
#endif /* _EVAS_CSERVE2_H */

File diff suppressed because it is too large Load Diff

View File

@ -177,8 +177,6 @@ _debug_msg_send(void)
}
typedef struct _Font_Entry Font_Entry;
typedef struct _Cache_Entry Cache_Entry;
typedef struct _Glyph_Entry Glyph_Entry;
struct _Font_Entry
{
@ -188,27 +186,9 @@ struct _Font_Entry
unsigned int size;
unsigned int dpi;
unsigned int unused;
Eina_List *caches;
};
struct _Cache_Entry
{
const char *shmname;
unsigned int size;
unsigned int usage;
Eina_List *glyphs;
};
struct _Glyph_Entry
{
unsigned int index;
unsigned int offset;
unsigned int size;
unsigned int rows;
unsigned int width;
unsigned int pitch;
unsigned int num_grays;
unsigned int pixel_mode;
char glyph_data_shm[64];
char glyph_mempool_shm[64];
Eina_List *glyphs; // Glyph_Data
};
#define READIT(_dst, _src) \
@ -217,57 +197,6 @@ struct _Glyph_Entry
_src += sizeof(_dst); \
} while(0)
static Glyph_Entry *
_parse_glyph_entry(char **msg)
{
Glyph_Entry *ge;
char *buf = *msg;
ge = calloc(1, sizeof(*ge));
READIT(ge->index, buf);
READIT(ge->offset, buf);
READIT(ge->size, buf);
READIT(ge->rows, buf);
READIT(ge->width, buf);
READIT(ge->pitch, buf);
READIT(ge->num_grays, buf);
READIT(ge->pixel_mode, buf);
*msg = buf;
return ge;
}
static Cache_Entry *
_parse_cache_entry(char **msg)
{
Cache_Entry *ce;
char *buf = *msg;
unsigned int n;
ce = calloc(1, sizeof(*ce));
READIT(n, buf);
ce->shmname = eina_stringshare_add_length(buf, n);
buf += n;
READIT(ce->size, buf);
READIT(ce->usage, buf);
READIT(n, buf);
while (n--)
{
Glyph_Entry *ge;
ge = _parse_glyph_entry(&buf);
ce->glyphs = eina_list_append(ce->glyphs, ge);
}
*msg = buf;
return ce;
}
static Font_Entry *
_parse_font_entry(char **msg)
{
@ -291,12 +220,18 @@ _parse_font_entry(char **msg)
READIT(fe->dpi, buf);
READIT(fe->unused, buf);
eina_strlcpy(fe->glyph_data_shm, buf, 64);
buf += 64;
eina_strlcpy(fe->glyph_mempool_shm, buf, 64);
buf += 64;
READIT(n, buf);
while (n--)
{
Cache_Entry *ce;
ce = _parse_cache_entry(&buf);
fe->caches = eina_list_append(fe->caches, ce);
Glyph_Data *gd = calloc(1, sizeof(Glyph_Data));
memcpy(gd, buf, sizeof(Glyph_Data));
buf += sizeof(Glyph_Data);
fe->glyphs = eina_list_append(fe->glyphs, gd);
}
*msg = buf;
@ -307,7 +242,7 @@ _parse_font_entry(char **msg)
static Eina_List *
_debug_msg_read(void)
{
Msg_Base *msg = NULL;
Msg_Font_Debug *msg = NULL;
char *buf;
int size;
unsigned int nfonts;
@ -317,16 +252,16 @@ _debug_msg_read(void)
while (!msg)
msg = _server_read(&size);
if (msg->type != CSERVE2_FONT_DEBUG)
if (msg->base.type != CSERVE2_FONT_DEBUG)
{
ERR("Invalid message received from server."
ERR("Invalid message received from server. "
"Something went badly wrong.");
return NULL;
}
buf = (char *)msg + sizeof(*msg);
READIT(nfonts, buf);
nfonts = msg->nfonts;
while (nfonts--)
{
Font_Entry *fe;
@ -334,34 +269,18 @@ _debug_msg_read(void)
fonts = eina_list_append(fonts, fe);
}
printf("Font index table: %s\n", msg->fonts_index_path);
printf("Contains %u fonts\n\n", msg->nfonts);
return fonts;
}
static void
_glyph_entry_free(Glyph_Entry *ge)
{
free(ge);
}
static void
_cache_entry_free(Cache_Entry *ce)
{
Glyph_Entry *ge;
EINA_LIST_FREE(ce->glyphs, ge)
_glyph_entry_free(ge);
eina_stringshare_del(ce->shmname);
free(ce);
}
static void
_font_entry_free(Font_Entry *fe)
{
Cache_Entry *ce;
Glyph_Data *gd;
EINA_LIST_FREE(fe->caches, ce)
_cache_entry_free(ce);
EINA_LIST_FREE(fe->glyphs, gd)
free(gd);
eina_stringshare_del(fe->name);
eina_stringshare_del(fe->file);
@ -369,7 +288,7 @@ _font_entry_free(Font_Entry *fe)
}
static void
_glyph_entry_print(Glyph_Entry *ge)
_glyph_data_print(Glyph_Data *gd)
{
const char *pxmode[] = {
"FT_PIXEL_MODE_NONE",
@ -380,29 +299,18 @@ _glyph_entry_print(Glyph_Entry *ge)
"FT_PIXEL_MODE_LCD",
"FT_PIXEL_MODE_LCD_V"
};
printf("\t\tGLYPH %u offset: %u size: %u %ux%u pitch: %u grays: %u "
"pixel mode: %s\n",
ge->index, ge->offset, ge->size, ge->width, ge->rows, ge->pitch,
ge->num_grays, pxmode[ge->pixel_mode]);
}
static void
_cache_entry_print(Cache_Entry *ce)
{
Eina_List *l;
Glyph_Entry *ge;
printf("\tSHM %s used %u/%u\n", ce->shmname, ce->usage, ce->size);
EINA_LIST_FOREACH(ce->glyphs, l, ge)
_glyph_entry_print(ge);
printf(" GLYPH id: %-4u refcount %-2u: index: %-6u offset: %-6u size: %-3u "
"%2ux%-3u pitch: %-2u grays: %-3u pixel mode: %s hint: %d\n",
gd->id, gd->refcount, gd->index, gd->offset, gd->size,
gd->width, gd->rows, gd->pitch,
gd->num_grays, pxmode[gd->pixel_mode], gd->hint);
}
static void
_font_entry_print(Font_Entry *fe)
{
Eina_List *l;
Cache_Entry *ce;
Glyph_Data *gd;
printf("FONT %s:%s size: %u dpi: %u %s%s%s %s\n",
fe->file, fe->name, fe->size, fe->dpi,
@ -410,18 +318,46 @@ _font_entry_print(Font_Entry *fe)
fe->rend_flags & 1 ? "SLANT " : "",
fe->rend_flags & 2 ? "WEIGHT" : "",
fe->unused ? "(unused)" : "");
printf(" Index: %s\n"
" Mempool: %s\n"
" Glyph count: %u\n",
fe->glyph_data_shm, fe->glyph_mempool_shm,
eina_list_count(fe->glyphs));
EINA_LIST_FOREACH(fe->caches, l, ce)
_cache_entry_print(ce);
EINA_LIST_FOREACH(fe->glyphs, l, gd)
_glyph_data_print(gd);
putchar('\n');
}
static void
_shared_index_print(Msg_Index_List *msg, size_t size)
{
if (size < sizeof(*msg) || msg->base.type != CSERVE2_INDEX_LIST)
{
ERR("Invalid message received from server. "
"Something went wrong.");
return;
}
printf("Printing shared indexes status.\n");
printf("===============================\n\n");
printf("Generation ID: %-4d\n", msg->generation_id);
printf("Strings entries path: %s\n", msg->strings_entries_path);
printf("Strings index path: %s\n", msg->strings_index_path);
printf("Files index path: %s\n", msg->files_index_path);
printf("Images index path: %s\n", msg->images_index_path);
printf("Fonts index path: %s\n", msg->fonts_index_path);
printf("\n\n\n");
}
int
main(void)
{
Eina_List *fonts;
Font_Entry *fe;
Msg_Index_List *msg = NULL;
int size;
eina_init();
_evas_cserve2_debug_log_dom = eina_log_domain_register
@ -431,6 +367,11 @@ main(void)
ERR("Could not connect to server.");
return -1;
}
while (!msg)
msg = _server_read(&size);
_shared_index_print(msg, size);
_debug_msg_send();
fonts = _debug_msg_read();
EINA_LIST_FREE(fonts, fe)

View File

@ -26,7 +26,7 @@
#define _EVAS_FONT_SLANT_TAN 0.221694663
#define CHECK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
#define MIN_GLYPHS 50
#define MIN_GLYPHS 100 // 26*2 + a nice margin :)
#define MAX_CACHE_SIZE 1 * 1024 * 1024 // 1MB
#define EVAS_FONT_ROUND_26_6_TO_INT(x) \
@ -47,7 +47,6 @@ struct _Font_Info
int dpi;
int max_h;
unsigned int runtime_rend;
int shmsize;
};
struct _Font_Source_Info
@ -281,14 +280,6 @@ _font_slave_load(const void *cmddata, void *data EINA_UNUSED)
return response;
}
static Shm_Handle *
_font_slave_memory_alloc(Font_Info *fi)
{
Shm_Handle *shm = cserve2_shm_request("font", fi->shmsize);
return shm;
}
/* This function will load the "index" glyph to the glyph slot of the font.
* In order to use or render it, one should access it from the glyph slot,
* or get the glyph using FT_Get_Glyph().
@ -326,43 +317,65 @@ _font_slave_glyph_load(Font_Info *fi, unsigned int idx, unsigned int hint)
* given Font Cache.
*/
static Eina_Bool
_font_slave_glyph_render(Font_Info *fi, Slave_Msg_Font_Cache *c, unsigned int idx)
_font_slave_glyph_render(Font_Info *fi, Slave_Msg_Font_Glyphs_Loaded *response,
unsigned int idx)
{
Font_Source_Info *fsi = fi->fsi;
unsigned int glyphsize;
char *cachedata = cserve2_shm_map(c->shm);
FT_Glyph glyph;
FT_BitmapGlyph bglyph;
char *data;
int buffer_id = 0;
FT_Get_Glyph(fsi->face->glyph, &glyph);
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
bglyph = (FT_BitmapGlyph)glyph;
glyphsize = bglyph->bitmap.pitch * bglyph->bitmap.rows;
if (c->usage + glyphsize > cserve2_shm_size_get(c->shm))
if (!glyphsize)
{
FT_Done_Glyph(glyph);
return EINA_FALSE;
goto on_error;
}
memcpy(cachedata + c->usage, bglyph->bitmap.buffer, glyphsize);
buffer_id = cserve2_shared_mempool_buffer_new(response->mempool, glyphsize);
data = cserve2_shared_mempool_buffer_get(response->mempool, buffer_id);
if (!data)
{
FT_Done_Glyph(glyph);
goto on_error;
}
memcpy(data, bglyph->bitmap.buffer, glyphsize);
// TODO: Check if we have problems with alignment
c->glyphs[c->nglyphs].index = idx;
c->glyphs[c->nglyphs].offset = c->usage;
c->glyphs[c->nglyphs].size = glyphsize;
c->glyphs[c->nglyphs].rows = bglyph->bitmap.rows;
c->glyphs[c->nglyphs].width = bglyph->bitmap.width;
c->glyphs[c->nglyphs].pitch = bglyph->bitmap.pitch;
c->glyphs[c->nglyphs].num_grays = bglyph->bitmap.num_grays;
c->glyphs[c->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode;
c->usage += glyphsize;
c->nglyphs++;
response->glyphs[response->nglyphs].index = idx;
response->glyphs[response->nglyphs].buffer_id = buffer_id;
response->glyphs[response->nglyphs].offset =
cserve2_shared_mempool_buffer_offset_get(response->mempool, buffer_id);
response->glyphs[response->nglyphs].size = glyphsize;
response->glyphs[response->nglyphs].rows = bglyph->bitmap.rows;
response->glyphs[response->nglyphs].width = bglyph->bitmap.width;
response->glyphs[response->nglyphs].pitch = bglyph->bitmap.pitch;
response->glyphs[response->nglyphs].num_grays = bglyph->bitmap.num_grays;
response->glyphs[response->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode;
response->nglyphs++;
FT_Done_Glyph(glyph);
return EINA_TRUE;
on_error:
// Create invalid entry for this index. There will be an empty slot in
// the mempool (usually 8 bytes) because we need the Glyph_Data index entry.
ERR("Could not load glyph %d. Creating empty invalid entry.", idx);
memset(&response->glyphs[response->nglyphs], 0, sizeof(Slave_Msg_Glyph));
if (buffer_id > 0)
cserve2_shared_mempool_buffer_del(response->mempool, buffer_id);
buffer_id = cserve2_shared_mempool_buffer_new(response->mempool, 1);
response->glyphs[response->nglyphs].index = idx;
response->glyphs[response->nglyphs].buffer_id = buffer_id;
response->nglyphs++;
return EINA_FALSE;
}
static void
@ -398,24 +411,6 @@ end:
if (depth) *depth = 0;
}
static unsigned int
_font_slave_int_shm_prev_calculate(unsigned int size, unsigned int nglyphs)
{
unsigned int average;
unsigned int newsize;
if (!nglyphs) return cserve2_shm_size_normalize(1);
average = size / nglyphs;
newsize = MIN_GLYPHS * average;
newsize = cserve2_shm_size_normalize(newsize);
if (newsize > MAX_CACHE_SIZE)
return MAX_CACHE_SIZE;
return newsize;
}
static unsigned int
_font_slave_int_shm_calculate(Font_Info *fi, unsigned int hint)
{
@ -434,7 +429,7 @@ _font_slave_int_shm_calculate(Font_Info *fi, unsigned int hint)
average = size / i; // average glyph size
size = MIN_GLYPHS * average;
size = cserve2_shm_size_normalize(size);
size = cserve2_shm_size_normalize(size, 0);
if (size > MAX_CACHE_SIZE)
return MAX_CACHE_SIZE; // Assumes no glyph will be bigger than this
@ -465,15 +460,12 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
Slave_Msg_Font_Glyphs_Loaded *response;
Font_Info *fi;
unsigned int i;
unsigned int total_glyphs = 0;
#ifdef DEBUG_LOAD_TIME
unsigned int gl_load_time = 0;
unsigned int gl_render_time = 0;
struct timeval tv_start, tv_end;
struct timeval rstart, rfinish;
#endif
Eina_List *caches = NULL;
Slave_Msg_Font_Cache *c = NULL;
fi = msg->font.ftdata2;
@ -483,41 +475,24 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
_font_slave_size_use(fi);
if (msg->cache.shm)
response = malloc(sizeof(*response)
+ sizeof(Slave_Msg_Glyph) * (msg->glyphs.nglyphs));
if (!response) return NULL;
response->nglyphs = 0;
response->glyphs = (void *) (response + 1);
response->mempool = msg->cache.mempool;
if (!response->mempool)
{
c = malloc(sizeof(*c) + sizeof(Slave_Msg_Glyph) *
(msg->glyphs.nglyphs));
c->nglyphs = 0;
c->glyphs = (void *)(c + 1);
c->shm = msg->cache.shm;
c->usage = msg->cache.usage;
caches = eina_list_append(caches, c);
total_glyphs = msg->cache.nglyphs;
unsigned shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
response->mempool = cserve2_shared_mempool_new(GLYPH_DATA_ARRAY_TAG,
sizeof(Glyph_Data), 0,
shmsize);
if (!response->mempool) return NULL;
}
if (!fi->shmsize)
fi->shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
i = 0;
while (i < msg->glyphs.nglyphs)
for (i = 0; i < msg->glyphs.nglyphs; i++)
{
Eina_Bool r = EINA_TRUE;
if (!c)
{
Shm_Handle *shm;
shm = _font_slave_memory_alloc(fi);
c = malloc(sizeof(*c) + sizeof(Slave_Msg_Glyph) *
(msg->glyphs.nglyphs - i));
c->nglyphs = 0;
c->glyphs = (void *)(c + 1);
c->shm = shm;
c->usage = 0;
caches = eina_list_append(caches, c);
total_glyphs = 0;
}
#ifdef DEBUG_LOAD_TIME
gettimeofday(&tv_start, NULL);
#endif
@ -530,32 +505,14 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
tv_start.tv_sec = tv_end.tv_sec;
tv_start.tv_usec = tv_end.tv_usec;
#endif
r = _font_slave_glyph_render(fi, c, msg->glyphs.glyphs[i]);
_font_slave_glyph_render(fi, response, msg->glyphs.glyphs[i]);
#ifdef DEBUG_LOAD_TIME
gettimeofday(&tv_end, NULL);
gl_render_time += _timeval_sub(&tv_end, &tv_start);
#endif
}
if (!r) // SHM is full
{
fi->shmsize = _font_slave_int_shm_prev_calculate
(c->usage, total_glyphs);
c = NULL;
continue;
}
i++;
total_glyphs++;
}
response = malloc(sizeof(*response) +
sizeof(c) * eina_list_count(caches));
response->ncaches = eina_list_count(caches);
response->caches = (void *)(response + 1);
i = 0;
EINA_LIST_FREE(caches, c)
response->caches[i++] = c;
#ifdef DEBUG_LOAD_TIME
response->gl_load_time = gl_load_time;
response->gl_render_time = gl_render_time;
@ -630,6 +587,8 @@ cserve2_font_source_ft_free(void *fontsource)
{
Font_Source_Info *fsi = fontsource;
if (!fsi) return;
FT_Done_Face(fsi->face);
free(fsi->data);
free(fsi);
@ -640,6 +599,8 @@ cserve2_font_ft_free(void *fontinfo)
{
Font_Info *fi = fontinfo;
if (!fi) return;
FT_Done_Size(fi->size);
free(fi);
}

File diff suppressed because it is too large Load Diff

View File

@ -24,15 +24,68 @@ cserve2_client_error_send(Client *client, unsigned int rid, int error_code)
int size;
Msg_Error msg;
// clear the struct with possible paddings, since it is not aligned.
memset(&msg, 0, sizeof(msg));
msg.base.rid = rid;
msg.base.type = CSERVE2_ERROR;
msg.error = error_code;
// clear the struct with possible paddings, since it is not aligned.
memset(&msg, 0, sizeof(msg));
msg.base.rid = rid;
msg.base.type = CSERVE2_ERROR;
msg.error = error_code;
size = sizeof(msg);
cserve2_client_send(client, &size, sizeof(size));
cserve2_client_send(client, &msg, sizeof(msg));
size = sizeof(msg);
cserve2_client_send(client, &size, sizeof(size));
cserve2_client_send(client, &msg, sizeof(msg));
}
void
cserve2_index_list_send(int generation_id,
const char *strings_index_path,
const char *strings_entries_path,
const char *files_index_path,
const char *images_index_path,
const char *fonts_index_path,
Client *client)
{
Eina_Iterator *iter;
Msg_Index_List msg;
const int size = sizeof(msg);
if (!client_list)
return;
INF("New shared index: strings: '%s':'%s' files: '%s' images: '%s', fonts: '%s'",
strings_index_path, strings_entries_path,
files_index_path, images_index_path, fonts_index_path);
memset(&msg, 0, size);
msg.base.type = CSERVE2_INDEX_LIST;
msg.generation_id = generation_id;
if (strings_index_path)
eina_strlcpy(msg.strings_index_path, strings_index_path, 64);
if (strings_entries_path)
eina_strlcpy(msg.strings_entries_path, strings_entries_path, 64);
if (files_index_path)
eina_strlcpy(msg.files_index_path, files_index_path, 64);
if (images_index_path)
eina_strlcpy(msg.images_index_path, images_index_path, 64);
if (fonts_index_path)
eina_strlcpy(msg.fonts_index_path, fonts_index_path, 64);
if (!client)
{
iter = eina_hash_iterator_data_new(client_list);
EINA_ITERATOR_FOREACH(iter, client)
{
DBG("Sending updated list of indexes to client %d", client->id);
cserve2_client_send(client, &size, sizeof(size));
cserve2_client_send(client, &msg, sizeof(msg));
}
eina_iterator_free(iter);
}
else
{
DBG("Sending updated list of indexes to client %d", client->id);
cserve2_client_send(client, &size, sizeof(size));
cserve2_client_send(client, &msg, sizeof(msg));
}
}
static void
@ -82,16 +135,27 @@ static void
_cserve2_client_open(Client *client)
{
Msg_Open *msg = (Msg_Open *)client->msg.buf;
const char *path, *key;
const char *path, *key, *end;
Evas_Image_Load_Opts *opts = NULL;
Evas_Image_Load_Opts opts_copy;
path = ((const char *)msg) + sizeof(*msg) + msg->path_offset;
key = ((const char *)msg) + sizeof(*msg) + msg->key_offset;
end = key + strlen(key) + 1;
INF("Received OPEN command: RID=%d", msg->base.rid);
INF("File_ID: %d, path=\"%s\", key=\"%s\", has_load_opts=%d",
msg->file_id, path, key, (int) msg->has_load_opts);
cserve2_cache_file_open(client, msg->file_id, path, key, msg->base.rid);
if (!key[0]) key = NULL;
if (msg->has_load_opts)
{
opts = &opts_copy;
memcpy(&opts_copy, end, sizeof(opts_copy));
}
cserve2_cache_file_open(client, msg->file_id, path, key, msg->base.rid,
opts);
if (!msg->has_load_opts)
cserve2_cache_image_entry_create(client, msg->base.rid,
@ -99,8 +163,6 @@ _cserve2_client_open(Client *client)
else
{
// FIXME: Check message size first?
Evas_Image_Load_Opts *opts =
(Evas_Image_Load_Opts*) (key + strlen(key) + 1);
DBG("Load Options:");
DBG("\tdpi: %03.1f", opts->dpi);
@ -172,8 +234,8 @@ _cserve2_client_font_glyphs_request(Client *client)
if (msg->base.type == CSERVE2_FONT_GLYPHS_LOAD)
{
INF("Received CSERVE2_FONT_GLYPHS_LOAD command: RID=%d",
msg->base.rid);
INF("Received CSERVE2_FONT_GLYPHS_LOAD command: RID=%d (%d glyphs)",
msg->base.rid, msg->nglyphs);
cserve2_cache_font_glyphs_load(client, source, fontpath,
msg->hint, msg->rend_flags, msg->size,
msg->dpi, glyphs, msg->nglyphs,
@ -181,8 +243,8 @@ _cserve2_client_font_glyphs_request(Client *client)
}
else
{
INF("Received CSERVE2_FONT_GLYPHS_USED command: RID=%d",
msg->base.rid);
INF("Received CSERVE2_FONT_GLYPHS_USED command: RID=%d (%d glyphs)",
msg->base.rid, msg->nglyphs);
cserve2_cache_font_glyphs_used(client, source, fontpath,
msg->hint, msg->rend_flags, msg->size,
msg->dpi, glyphs, msg->nglyphs,
@ -291,6 +353,7 @@ static void
_clients_finish(void)
{
eina_hash_free(client_list);
client_list = NULL;
}
int
@ -327,34 +390,26 @@ main(int argc EINA_UNUSED, const char *argv[])
goto error;
}
cserve2_requests_init();
cserve2_scale_init();
cserve2_font_init();
cserve2_cache_init();
cserve2_shm_init();
cserve2_shared_index_init();
cserve2_requests_init();
cserve2_scale_init();
cserve2_font_init();
cserve2_cache_init();
_clients_setup();
cserve2_main_loop_run();
_clients_finish();
cserve2_cache_shutdown();
cserve2_font_shutdown();
cserve2_scale_shutdown();
cserve2_requests_shutdown();
cserve2_slaves_shutdown();
cserve2_main_loop_finish();
cserve2_shared_index_shutdown();
cserve2_shm_shutdown();
eina_prefix_free(_evas_cserve2_pfx);

View File

@ -90,8 +90,9 @@ _signal_handle_child(struct signalfd_siginfo *sinfo EINA_UNUSED)
}
static void
_signal_handle_exit(struct signalfd_siginfo *sinfo)
_signal_handle_exit(struct signalfd_siginfo *sinfo EINA_UNUSED)
{
#if CSERVE2_LOG_LEVEL >= 4
const char *name;
switch (sinfo->ssi_signo)
@ -103,6 +104,7 @@ _signal_handle_exit(struct signalfd_siginfo *sinfo)
}
DBG("Received %s. Honoring request.", name);
#endif
terminate = EINA_TRUE;
}
@ -129,8 +131,6 @@ _signalfd_handler(int fd, Fd_Flags flags EINA_UNUSED, void *data EINA_UNUSED)
_signal_handle_child(&sinfo);
break;
case SIGINT:
case SIGTERM:
case SIGQUIT:
_signal_handle_exit(&sinfo);
break;
case SIGUSR1:
@ -159,10 +159,8 @@ _signalfd_setup(void)
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGUSR1);
sigaddset(&mask, SIGUSR2);
sigaddset(&mask, SIGUSR1); // ignored
sigaddset(&mask, SIGUSR2); // ignored
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
{

View File

@ -172,9 +172,6 @@ cserve2_client_send(Client *client, const void *data, size_t size)
// so we must close the connection to the client and remove
// its references inside our cache.
WRN("Error on socket with client %d: %s", client->id, strerror(errno));
if (client->msg.reading)
_client_msg_free(client);
cserve2_client_del(client);
return sent;
}
if (sent < 0)

View File

@ -288,6 +288,38 @@ cserve2_request_cancel_all(Slave_Request *req, Error_Type err)
free(req);
}
void
cserve2_request_dependents_drop(Slave_Request *req, Slave_Request_Type type)
{
Slave_Request *dep;
Eina_List *l, *l_next;
if (type != CSERVE2_REQ_IMAGE_SPEC_LOAD)
{
CRIT("Only CSERVE2_REQ_IMAGE_SPEC_LOAD is supported.");
return;
}
EINA_LIST_FOREACH_SAFE(req->dependents, l, l_next, dep)
{
if (dep->type == type)
{
req->dependents = eina_list_remove_list(req->dependents, l);
if (dep->processing)
dep->cancelled = EINA_TRUE;
else
{
cserve2_entry_request_drop(dep->data, type);
requests[type].waiting = eina_inlist_remove(
requests[type].waiting, EINA_INLIST_GET(dep));
dep->funcs->msg_free(dep->msg, dep->data);
free(dep);
}
}
}
}
void
cserve2_requests_init(void)
{

View File

@ -32,7 +32,8 @@ _cserve2_rgba_image_set(RGBA_Image *im, void *data, int w, int h, int alpha)
}
void
cserve2_rgba_image_scale_do(void *src_data, void *dst_data,
cserve2_rgba_image_scale_do(void *src_data, int src_full_w, int src_full_h,
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)
@ -40,8 +41,7 @@ cserve2_rgba_image_scale_do(void *src_data, void *dst_data,
RGBA_Image src, dst;
RGBA_Draw_Context ct;
_cserve2_rgba_image_set(&src, src_data, src_w, src_h, alpha);
_cserve2_rgba_image_set(&src, src_data, src_full_w, src_full_h, alpha);
_cserve2_rgba_image_set(&dst, dst_data, dst_w, dst_h, alpha);
dst.flags = RGBA_IMAGE_NOTHING;

View File

@ -28,13 +28,14 @@ struct _Shm_Handle
size_t map_size;
size_t image_size;
int refcount;
int shmid;
void *data;
};
static int id = 0;
size_t
cserve2_shm_size_normalize(size_t size)
cserve2_shm_size_normalize(size_t size, size_t align)
{
long pagesize;
size_t normalized;
@ -46,7 +47,11 @@ cserve2_shm_size_normalize(size_t size)
pagesize = 4096;
}
normalized = ((size + pagesize - 1) / pagesize) * pagesize;
if (align)
align = ((align + pagesize - 1) / pagesize) * pagesize;
else
align = pagesize;
normalized = ((size + align - 1) / align) * align;
return normalized;
}
@ -76,8 +81,8 @@ cserve2_shm_request(const char *infix, size_t size)
}
do {
snprintf(shmname, sizeof(shmname), "/evas-shm-%x-%s-%08x",
(int) getuid(), infix, id++);
snprintf(shmname, sizeof(shmname), "/evas-shm-%05d-%05d-%s-%08x",
(int) getuid(), (int) getpid(), infix, ++id);
fd = shm_open(shmname, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd == -1 && errno != EEXIST)
{
@ -88,7 +93,7 @@ cserve2_shm_request(const char *infix, size_t size)
}
} while (fd == -1);
map_size = cserve2_shm_size_normalize(size);
map_size = cserve2_shm_size_normalize(size, 0);
if (ftruncate(fd, map_size) == -1)
{
@ -110,6 +115,100 @@ cserve2_shm_request(const char *infix, size_t size)
shm->image_size = size;
shm->map_size = map_size;
shm->shmid = id;
return shm;
}
Shm_Handle *
cserve2_shm_segment_request(Shm_Handle *shm, size_t size)
{
Shm_Handle *segment;
size_t map_size;
Shm_Mapping *map = shm->mapping;
int fd;
segment = calloc(1, sizeof (Shm_Handle));
if (!segment) return NULL;
fd = shm_open(map->name, O_RDWR, S_IRUSR | S_IWUSR);
if (!fd)
{
ERR("Could not reopen shm handle: %m");
free(segment);
return NULL;
}
map_size = cserve2_shm_size_normalize(size, 0);
map_size += map->length;
if (ftruncate(fd, map_size) == -1)
{
ERR("Could not set the size of the shm: %m");
close(fd);
free(segment);
return NULL;
}
close(fd);
segment->mapping = map;
segment->map_offset = map->length;
segment->map_size = map_size - map->length;
segment->image_size = size;
segment->image_offset = segment->map_offset;
map->length = map_size;
map->segments = eina_inlist_append(map->segments, EINA_INLIST_GET(segment));
return segment;
}
Shm_Handle *
cserve2_shm_resize(Shm_Handle *shm, size_t newsize)
{
size_t map_size;
int fd;
if (!shm)
return NULL;
if (shm->map_offset || shm->image_offset)
{
CRIT("Can not resize shm with non-zero offset");
return NULL;
}
if (eina_inlist_count(shm->mapping->segments) > 1)
{
CRIT("Can not resize shm with more than one segment");
return NULL;
}
fd = shm_open(shm->mapping->name, O_RDWR, S_IRUSR | S_IWUSR);
if (!fd)
{
ERR("Could not reopen shm handle: %m");
return NULL;
}
map_size = cserve2_shm_size_normalize(newsize, 0);
if (ftruncate(fd, map_size))
{
ERR("Could not set the size of the shm: %m");
close(fd);
return NULL;
}
if (shm->data)
{
munmap(shm->data, shm->image_size);
shm->data = mmap(NULL, shm->image_size, PROT_WRITE, MAP_SHARED,
fd, shm->image_offset);
}
close(fd);
shm->map_size = map_size;
shm->image_size = newsize;
shm->mapping->length = map_size;
return shm;
}
@ -139,6 +238,12 @@ cserve2_shm_name_get(const Shm_Handle *shm)
return shm->mapping->name;
}
int
cserve2_shm_id_get(const Shm_Handle *shm)
{
return shm->shmid;
}
off_t
cserve2_shm_map_offset_get(const Shm_Handle *shm)
{
@ -203,7 +308,7 @@ _cserve2_shm_cleanup()
const Eina_File_Direct_Info *f_info;
char pattern[NAME_MAX];
sprintf(pattern, "evas-shm-%x-", (int) getuid());
sprintf(pattern, "evas-shm-%05d-", (int) getuid());
iter = eina_file_direct_ls("/dev/shm");
EINA_ITERATOR_FOREACH(iter, f_info)
{
@ -220,6 +325,7 @@ _cserve2_shm_cleanup()
else
DBG("cserve2 cleanup: ignoring %s", f_info->path);
}
eina_iterator_free(iter);
}
void

View File

@ -0,0 +1,811 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <sys/ioctl.h>
#include <Eina.h>
#include "evas_cs2.h"
#define SHM_FOLDER "/dev/shm"
static int _evas_cserve2_shm_debug_log_dom = -1;
#define ERR(...) EINA_LOG_DOM_ERR(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define DBG(...) EINA_LOG_DOM_DBG(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_evas_cserve2_shm_debug_log_dom, __VA_ARGS__)
typedef struct _Shm_File Shm_File;
struct _Shm_File
{
Eina_File *f;
char *data;
size_t size;
int tag;
Eina_Bool strings;
Shared_Array_Header *header;
};
Shm_File *sf_strindex = NULL;
Shm_File *sf_strpool = NULL;
Shm_File *sf_fonts = NULL;
Shm_File *sf_files = NULL;
Shm_File *sf_images = NULL;
static int _termsize = 0;
static void
nprintf(int n, const char *fmt, ...)
{
char buf[n+1];
va_list arg;
int len;
va_start(arg, fmt);
if (!n)
vprintf(fmt, arg);
else
{
len = vsnprintf(buf, n+1, fmt, arg);
buf[n] = 0;
fputs(buf, stdout);
if ((len > 0) && (buf[len-1] != '\n'))
fputc('\n', stdout);
}
va_end(arg);
}
#define printf(...) nprintf(_termsize, __VA_ARGS__)
static Shm_File *
_shm_file_open(const char *path)
{
Shm_File *sf;
Eina_File *f;
char *data;
f = eina_file_open(path, EINA_TRUE);
if (!f)
{
ERR("Could not open file %s: [%d] %m", path, errno);
return NULL;
}
data = eina_file_map_all(f, EINA_FILE_RANDOM);
if (!data)
{
ERR("Could not map the file %s", path);
eina_file_close(f);
return NULL;
}
sf = calloc(1, sizeof(*sf));
sf->data = data;
sf->f = f;
sf->size = eina_file_size_get(f);
DBG("Successfully opened %s", path);
return sf;
}
static void
_shm_file_close(Shm_File *sf)
{
if (!sf) return;
eina_file_map_free(sf->f, sf->data);
eina_file_close(sf->f);
free(sf);
}
static Eina_Bool
_shm_file_probe(Shm_File *sf)
{
if (!sf || !sf->data)
return EINA_FALSE;
if (sf->size < sizeof(Shared_Array_Header))
{
sf->header = NULL;
return EINA_TRUE;
}
sf->header = (Shared_Array_Header *) sf->data;
switch (sf->header->tag)
{
case STRING_INDEX_ARRAY_TAG:
DBG("Found string index: %s", eina_file_filename_get(sf->f));
if (sf->header->elemsize != sizeof(Index_Entry))
{
ERR("String index looks invalid: elemsize %d",
sf->header->elemsize);
return EINA_FALSE;
}
sf->tag = STRING_INDEX_ARRAY_TAG;
sf_strindex = sf;
break;
case STRING_MEMPOOL_FAKETAG:
DBG("Found string mempool: %s", eina_file_filename_get(sf->f));
sf->strings = EINA_TRUE;
sf->tag = STRING_MEMPOOL_FAKETAG;
sf->header = NULL;
sf_strpool = sf;
break;
case FILE_DATA_ARRAY_TAG:
DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
sf->tag = sf->header->tag;
sf_files = sf;
break;
case IMAGE_DATA_ARRAY_TAG:
DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
sf->tag = sf->header->tag;
sf_images = sf;
break;
case FONT_DATA_ARRAY_TAG:
DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
sf->tag = sf->header->tag;
sf_fonts = sf;
break;
case GLYPH_DATA_ARRAY_TAG:
DBG("Found index table with tag '%4.4s'", (char *) &sf->header->tag);
sf->tag = sf->header->tag;
break;
default:
//DBG("Unknown tag found: %d", sf->header->tag);
sf->header = NULL;
break;
}
return EINA_TRUE;
}
static Eina_List *
_shm_files_list(const char *folder)
{
Eina_List *lst = NULL;
Eina_Iterator *iter;
const Eina_File_Direct_Info *f_info;
char pattern[64];
sprintf(pattern, "/evas-shm-%05d-", (int) getuid());
iter = eina_file_direct_ls(folder);
EINA_ITERATOR_FOREACH(iter, f_info)
{
if (strstr(f_info->path, pattern))
{
const char *shmname = strrchr(f_info->path, '/');
if (!shmname) continue;
lst = eina_list_append(lst, strdup(shmname));
}
else
DBG("cserve2 scan: ignoring %s", f_info->path);
}
eina_iterator_free(iter);
return lst;
}
static void
printf_newline(Eina_Bool flush)
{
printf("----------------------------------------------------------------"
"----------------\n");
if (flush)
{
printf("\n\n");
fflush(stdout);
}
}
static void
_index_tables_summary_print(void)
{
printf("Shared index tables\n\n");
printf("Table Tag MapSize Gen ElSz Count Last Sort Path\n");
printf_newline(0);
printf("StrIdx %4.4s %7d %4d %4d %5d %5d %5d %s\n",
(char *) &sf_strindex->tag,
(int) eina_file_size_get(sf_strindex->f),
sf_strindex->header->generation_id, sf_strindex->header->elemsize,
sf_strindex->header->count, sf_strindex->header->emptyidx,
sf_strindex->header->sortedidx,
eina_file_filename_get(sf_strindex->f));
printf("StrData %4.4s %7d %s\n",
(char *) &sf_strpool->tag,
(int) eina_file_size_get(sf_strpool->f),
eina_file_filename_get(sf_strpool->f));
if (sf_files)
printf("FileIdx %4.4s %7d %4d %4d %5d %5d %5d %s\n",
(char *) &sf_files->tag,
(int) eina_file_size_get(sf_files->f),
sf_files->header->generation_id, sf_files->header->elemsize,
sf_files->header->count, sf_files->header->emptyidx,
sf_files->header->sortedidx,
eina_file_filename_get(sf_files->f));
else
printf("FileIdx <not found>\n");
if (sf_images)
printf("Images %4.4s %7d %4d %4d %5d %5d %5d %s\n",
(char *) &sf_images->tag,
(int) eina_file_size_get(sf_images->f),
sf_images->header->generation_id, sf_images->header->elemsize,
sf_images->header->count, sf_images->header->emptyidx,
sf_images->header->sortedidx,
eina_file_filename_get(sf_images->f));
else
printf("Images <not found>\n");
if (sf_fonts)
printf("FontIdx %4.4s %7d %4d %4d %5d %5d %5d %s\n",
(char *) &sf_fonts->tag,
(int) eina_file_size_get(sf_fonts->f),
sf_fonts->header->generation_id, sf_fonts->header->elemsize,
sf_fonts->header->count, sf_fonts->header->emptyidx,
sf_fonts->header->sortedidx,
eina_file_filename_get(sf_fonts->f));
else
printf("FontIdx <not found>\n");
printf_newline(1);
}
static const Shm_Object *
_shared_index_item_get_by_id(Shm_File *si, int elemsize, unsigned int id)
{
const Shm_Object *obj;
const char *base;
int low = 0, high, start_high;
int cur;
if (!si || elemsize <= 0 || !id)
return NULL;
// FIXME: HACK (consider all arrays always sorted by id)
high = si->header->emptyidx; // Should be si->header->sortedidx
if (high > si->header->count)
high = si->header->count;
base = si->data + sizeof(Shared_Array_Header);
// Direct access, works for non-repacked arrays
if ((int) id < high)
{
obj = (Shm_Object *) (base + (elemsize * id));
if (obj->id == id)
return obj;
}
// Binary search
start_high = high;
while(high != low)
{
cur = low + ((high - low) / 2);
obj = (Shm_Object *) (base + (elemsize * cur));
if (obj->id == id)
return obj;
if (obj->id < id)
low = cur + 1;
else
high = cur;
}
// Linear search
for (cur = start_high; cur < si->header->count; cur++)
{
obj = (Shm_Object *) (base + (elemsize * cur));
if (!obj->id)
return NULL;
if (obj->id == id)
return obj;
}
return NULL;
}
static void *
_shared_array_item_get(Shm_File *sf, int idx)
{
if (!sf || !sf->header || idx < 0)
return NULL;
if ((idx + 1) * sf->header->elemsize > (int) sf->size)
return NULL;
return (sf->data + sizeof(Shared_Array_Header) + idx * sf->header->elemsize);
}
static const char *
_shared_string_get(int id)
{
Index_Entry *ie;
ie = (Index_Entry *)
_shared_index_item_get_by_id(sf_strindex, sizeof(*ie), id);
if (!ie) return NULL;
if (ie->offset < 0) return NULL;
if (!ie->refcount) return NULL;
if (ie->offset + ie->length > (int) sf_strpool->size) return NULL;
return sf_strpool->data + ie->offset;
}
static void
_strings_all_print(Eina_Bool full)
{
int k;
const char *mindata = sf_strpool->data;
const char *maxdata = sf_strpool->data + sf_strpool->size;
printf("List of strings\n");
printf("Indexes: %s\n", eina_file_filename_get(sf_strindex->f));
printf("Data: %s\n", eina_file_filename_get(sf_strpool->f));
printf(" String BufID Refcnt Offset Buflen Content\n");
printf_newline(0);
for (k = 0; k < sf_strindex->header->count; k++)
{
Index_Entry *ie;
const char *data;
ie = _shared_array_item_get(sf_strindex, k);
if (!ie) break;
if (!ie->id || (!full && !ie->refcount))
continue;
data = sf_strpool->data + ie->offset;
if ((data < mindata) || (data + ie->length > maxdata))
data = "<invalid offset>";
printf("%7d %7d %7d %7d %7d '%s'\n",
k, ie->id, ie->refcount, ie->offset, ie->length, data);
}
printf_newline(1);
}
static void
_files_all_print_short()
{
int k;
if (!sf_files) return;
printf("List of image files: %s\n", eina_file_filename_get(sf_files->f));
printf("A: Alpha, I: Invalid.\n\n");
printf(" Index FileID WIDTHxHEIGHT A I Loader PathID KeyID Path:Key\n");
printf_newline(0);
for (k = 0; k < sf_files->header->count; k++)
{
File_Data *fd;
fd = _shared_array_item_get(sf_files, k);
if (!fd) break;
if (!fd->id || !fd->refcount) continue;
printf("%7d %7d %5dx%-6d %d %d %6.6s %6d %6d '%s':'%s'\n",
k, fd->id, fd->w, fd->h, !!fd->alpha, !!fd->invalid,
fd->loader_data ? _shared_string_get(fd->loader_data) : "",
fd->path, fd->key, _shared_string_get(fd->path),
_shared_string_get(fd->key));
}
printf_newline(1);
}
static void
_files_all_print_all(void)
{
int k;
if (!sf_files) return;
printf("List of opened image files: %s\n", eina_file_filename_get(sf_files->f));
printf_newline(0);
for (k = 0; k < sf_files->header->count; k++)
{
File_Data *fd;
fd = _shared_array_item_get(sf_files, k);
if (!fd) break;
if (!fd->id) continue;
printf("File #%-8d %d\n", k, fd->id);
printf("Path:Key: '%s':'%s'\n",
_shared_string_get(fd->path), _shared_string_get(fd->key));
printf("LoadOpts: Region: %d,%d-%dx%d\n",
fd->lo.region.x, fd->lo.region.y, fd->lo.region.w, fd->lo.region.h);
if (fd->lo.dpi != 0)
printf(" DPI: %f\n");
else
printf(" DPI: 0\n");
printf(" Requested: %dx%d\n", fd->lo.w, fd->lo.h);
printf(" Scale down: %d\n", fd->lo.scale_down_by);
printf(" Orientation: %s\n", fd->lo.orientation ? "YES" : "NO");
printf("Loader: %s\n", _shared_string_get(fd->loader_data));
printf("Geometry: %dx%d\n", fd->w, fd->h);
printf("Animation: anim: %s, frames: %d, loop: %d, hint: %d\n",
fd->animated ? "YES" : "NO",
fd->frame_count, fd->loop_count, fd->loop_hint);
printf("Alpha: %s\n", fd->alpha ? "YES" : "NO");
printf("Invalid: %s\n", fd->invalid ? "YES" : "NO");
printf_newline(0);
}
printf("\n\n");
fflush(stdout);
}
static void
_images_all_print_short(void)
{
int k;
if (!sf_images) return;
printf("List of loaded images: %s\n", eina_file_filename_get(sf_images->f));
printf("A: Sparse alpha, U: Unused, L: Load requested.\n\n");
printf(" Index ImageID FileID Refcnt A U L ShmID ShmPath\n");
printf_newline(0);
for (k = 0; k < sf_images->header->count; k++)
{
Image_Data *id;
id = _shared_array_item_get(sf_images, k);
if (!id) break;
if (!id->id || !id->refcount) continue;
printf("%7d %7d %7d %7d %d %d %d %7d '%s'\n",
k, id->id, id->file_id, id->refcount,
!!id->alpha_sparse, !!id->unused, !!id->doload, id->shm_id,
id->shm_id ? _shared_string_get(id->shm_id) : "");
}
printf_newline(1);
}
static void
_images_all_print_full(void)
{
int k;
if (!sf_images) return;
printf("List of loaded images: %s\n\n",
eina_file_filename_get(sf_images->f));
printf_newline(0);
for (k = 0; k < sf_images->header->count; k++)
{
Image_Data *id;
File_Data *fd;
const char *scale_hint;
id = _shared_array_item_get(sf_images, k);
if (!id) break;
if (!id->id) continue;
printf("Image #%-8d %d\n", k, id->id);
printf("Refcount %d\n", id->refcount);
printf("Sparse alpha %s\n"
"Unused: %s\n"
"Load requested: %s\n"
"Valid: %s\n",
id->alpha_sparse ? "YES" : "NO",
id->unused ? "YES" : "NO",
id->doload ? "YES" : "NO",
id->valid ? "YES" : "NO");
printf("Shm Path: '%s'\n",
id->shm_id ? _shared_string_get(id->shm_id) : "");
printf("LoadOpts: width %d\n", id->opts.w);
printf(" height %d\n", id->opts.h);
printf(" degree %d\n", id->opts.degree);
printf(" scale_down_by %d\n", id->opts.scale_down_by);
if (id->opts.dpi)
printf(" dpi %.2f\n", id->opts.dpi);
else
printf(" dpi 0\n");
printf(" orientation %s\n", id->opts.orientation ? "YES" : "NO");
printf(" region (%d,%d) %dx%d\n",
id->opts.region.x, id->opts.region.y,
id->opts.region.w, id->opts.region.h);
switch (id->opts.scale_load.scale_hint)
{
case EVAS_IMAGE_SCALE_HINT_NONE:
scale_hint = "EVAS_IMAGE_SCALE_HINT_NONE"; break;
case EVAS_IMAGE_SCALE_HINT_DYNAMIC:
scale_hint = "EVAS_IMAGE_SCALE_HINT_DYNAMIC"; break;
case EVAS_IMAGE_SCALE_HINT_STATIC:
scale_hint = "EVAS_IMAGE_SCALE_HINT_STATIC"; break;
default:
scale_hint = "<invalid>"; break;
}
printf(" scale src (%d,%d) %dx%d\n",
id->opts.scale_load.src_x, id->opts.scale_load.src_y,
id->opts.scale_load.src_w, id->opts.scale_load.src_h);
printf(" scale dst %dx%d\n",
id->opts.scale_load.dst_w, id->opts.scale_load.dst_h);
printf(" scale smooth %s\n",
id->opts.scale_load.smooth ? "YES" : "NO");
printf(" scale hint %s (%d)\n",
scale_hint, id->opts.scale_load.scale_hint);
fd = (File_Data *)
_shared_index_item_get_by_id(sf_files, sizeof(*fd), id->file_id);
if (fd)
{
printf("File: ID %d\n", id->file_id);
printf(" Path:Key: '%s':'%s'\n",
_shared_string_get(fd->path), _shared_string_get(fd->key));
printf(" Loader: %s\n",
_shared_string_get(fd->loader_data));
printf(" Geometry: %dx%d\n", fd->w, fd->h);
printf(" Animation: anim: %s, frames: %d, loop: %d, hint: %d\n",
fd->animated ? "YES" : "NO",
fd->frame_count, fd->loop_count, fd->loop_hint);
printf(" Alpha: %s\n", fd->alpha ? "YES" : "NO");
printf(" Invalid: %s\n", fd->invalid ? "YES" : "NO");
}
else
printf("File: ID %d not found\n", id->file_id);
printf_newline(0);
}
printf("\n\n");
fflush(stdout);
}
static void
_fonts_all_print_short(void)
{
int k;
static const char *rend_flags[] = { "R", "S", "W", "SW", "X" };
if (!sf_fonts) return;
printf("List of loaded fonts: %s\n", eina_file_filename_get(sf_fonts->f));
printf("Rendering flags (RF): "
"R: Regular, S: Slanted, W: Weight, X: Invalid\n\n");
printf(" Index FontID Refcnt Size DPI RF GlIdx GlData File[:Name]\n");
printf_newline(0);
for (k = 0; k < sf_fonts->header->count; k++)
{
Font_Data *fd;
int rflag;
const char *rf;
fd = _shared_array_item_get(sf_fonts, k);
if (!fd) break;
if (!fd->id || !fd->refcount) continue;
rflag = fd->rend_flags;
if (rflag < 0 || rflag > 3) rflag = 4;
rf = rend_flags[rflag];
if (fd->name)
printf("%6d %6d %6d %5d %5d %-2s %6d %6d '%s':'%s'\n",
k, fd->id, fd->refcount, fd->size, fd->dpi, rf,
fd->glyph_index_shm, fd->mempool_shm,
fd->file ? _shared_string_get(fd->file) : "",
_shared_string_get(fd->name));
else
printf("%6d %6d %6d %5d %5d %-2s %6d %6d '%s'\n",
k, fd->id, fd->refcount, fd->size, fd->dpi, rf,
fd->glyph_index_shm, fd->mempool_shm,
fd->file ? _shared_string_get(fd->file) : "");
}
printf_newline(1);
}
static void
_glyphs_all_print(Shm_File *sf)
{
int k;
int nglyphs = 0;
int mem_used = 0;
printf(" GlyphID Refcnt Index Size Rows Width Pitch Grays H M "
"BufID Offset ShmPath\n");
for (k = 0; k < sf->header->count; k++)
{
Glyph_Data *gd;
gd = _shared_array_item_get(sf, k);
if (!gd) break;
if (!gd->id) continue;
printf(" %8u %6u %6u %5u %5u %5u %5u %5u %1u %1u %6u %6u '%s'\n",
gd->id, gd->refcount, gd->index, gd->size, gd->rows, gd->width,
gd->pitch, gd->num_grays, gd->hint, gd->pixel_mode, gd->buffer_id,
gd->offset, _shared_string_get(gd->mempool_id));
nglyphs++;
mem_used += gd->size;
}
printf("Total %d glyph(s) loaded, using %d bytes (w/o padding)\n",
nglyphs, mem_used);
}
static void
_fonts_all_print_full(void)
{
int k;
static const char *rend_flags[] = { "R", "S", "W", "SW", "X" };
if (!sf_fonts) return;
printf("List of loaded fonts: %s\n", eina_file_filename_get(sf_fonts->f));
printf("Rendering flags: "
"R: Regular, S: Slanted, W: Weight, X: Invalid\n");
printf("H: Hint, M: Pixel mode\n\n");
printf_newline(0);
for (k = 0; k < sf_fonts->header->count; k++)
{
Shm_File *sf;
Font_Data *fd;
int rflag;
const char *rf;
fd = _shared_array_item_get(sf_fonts, k);
if (!fd) break;
if (!fd->id) continue;
if (!fd->glyph_index_shm) continue;
sf = _shm_file_open(_shared_string_get(fd->glyph_index_shm));
if (!_shm_file_probe(sf))
{
_shm_file_close(sf);
continue;
}
rflag = fd->rend_flags;
if (rflag < 0 || rflag > 3) rflag = 4;
rf = rend_flags[rflag];
printf("Font #%-8d %d\n", k, fd->id);
printf("Refcount %d\n", fd->refcount);
printf("File '%s'\n", _shared_string_get(fd->file));
printf("Name '%s'\n",
fd->name ? _shared_string_get(fd->name) : "");
printf("Size %d\n", fd->size);
printf("DPI %d\n", fd->dpi);
printf("Rendering flag %s (%d)\n", rf, fd->rend_flags);
printf("Glyph index '%s'\n", _shared_string_get(fd->glyph_index_shm));
printf("Glyph data '%s'\n", _shared_string_get(fd->mempool_shm));
_glyphs_all_print(sf);
_shm_file_close(sf);
printf_newline(0);
}
printf("\n\n");
fflush(stdout);
}
int
main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
{
Eina_List *opened_sf = NULL;
Eina_List *shmfiles = NULL, *l1, *l2;
const char *shmfolder = SHM_FOLDER;
Eina_Bool full = EINA_FALSE;
Shm_File *sf;
char *name;
struct winsize w;
if (isatty(STDOUT_FILENO))
{
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
_termsize = w.ws_col;
}
if (argc > 1)
{
if (!strcmp(argv[1], "-h"))
{
printf("Usage: %s [-f] [folder]\n", argv[0]);
return 0;
}
else if (!strcmp(argv[1], "-f"))
{
full = EINA_TRUE;
if (argc > 2)
shmfolder = argv[2];
}
else
shmfolder = argv[1];
}
eina_init();
_evas_cserve2_shm_debug_log_dom = eina_log_domain_register
("evas_cserve2_shm_debug", EINA_COLOR_BLUE);
shmfiles = _shm_files_list(shmfolder);
if (!shmfiles)
{
WRN("No shm file was found in %s", shmfolder);
goto finish;
}
DBG("Found %d files in %s", eina_list_count(shmfiles), shmfolder);
// Look for strings index & mempool
EINA_LIST_FOREACH_SAFE(shmfiles, l1, l2, name)
{
sf = _shm_file_open(name);
if (!_shm_file_probe(sf))
{
shmfiles = eina_list_remove_list(shmfiles, l1);
_shm_file_close(sf);
free(name);
continue;
}
if (!sf->tag)
_shm_file_close(sf);
else
opened_sf = eina_list_append(opened_sf, sf);
if (!!sf_strindex
&& !!sf_strpool
&& !!sf_fonts
&& !!sf_images
&& !!sf_files)
break;
}
if (!sf_strindex || !sf_strpool)
{
ERR("Could not identify strings memory pool");
goto finish;
}
_index_tables_summary_print();
_strings_all_print(full);
_files_all_print_short();
if (full) _files_all_print_all();
_images_all_print_short();
if (full) _images_all_print_full();
_fonts_all_print_short();
if (full) _fonts_all_print_full();
finish:
EINA_LIST_FREE(opened_sf, sf)
_shm_file_close(sf);
EINA_LIST_FREE(shmfiles, name)
free(name);
eina_shutdown();
return 0;
}

View File

@ -318,7 +318,8 @@ _image_file_header(Eina_File *fd, Eina_Stringshare *key, Evas_Image_Load_Opts *l
static Error_Type
image_open(const char *file, const char *key,
Slave_Msg_Image_Opened *result, const char **use_loader)
Slave_Msg_Image_Opened *result, const char **use_loader,
Evas_Image_Load_Opts *load_opts)
{
Evas_Module *module;
Eina_File *fd;
@ -327,9 +328,6 @@ image_open(const char *file, const char *key,
unsigned int i;
Error_Type ret = CSERVE2_NONE;
Eina_Stringshare *skey = eina_stringshare_add(key);
Evas_Image_Load_Opts load_opts;
memset(&load_opts, 0, sizeof(load_opts));
fd = eina_file_open(file, EINA_FALSE);
if (!fd)
@ -344,7 +342,7 @@ image_open(const char *file, const char *key,
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (module)
{
if (_image_file_header(fd, skey, &load_opts, result, module))
if (_image_file_header(fd, skey, load_opts, result, module))
goto success;
}
@ -364,7 +362,7 @@ try_extension:
if (loader)
{
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (_image_file_header(fd, skey, &load_opts, result, module))
if (module && _image_file_header(fd, skey, load_opts, result, module))
goto success;
loader = NULL;
module = NULL;
@ -376,7 +374,7 @@ try_extension:
loader = loaders_name[i];
module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (!module) continue;
if (_image_file_header(fd, skey, &load_opts, result, module))
if (_image_file_header(fd, skey, load_opts, result, module))
goto success;
}
@ -436,8 +434,8 @@ image_load(const char *file, const char *key, const char *shmfile,
}
memset(&property, 0, sizeof (property));
property.w = params->w;
property.h = params->h;
property.w = params->opts.w; // Should we rather use params->w ?
property.h = params->opts.h;
skey = eina_stringshare_add(key);
loader_data = _image_file_open(fd, skey, opts, module, &property, &animated, &funcs);
@ -448,6 +446,14 @@ image_load(const char *file, const char *key, const char *shmfile,
goto done;
}
if (params->shm.mmap_size < (int) (property.w * property.h * 4))
{
printf("LOAD failed at %s:%d: shm map is too small (%d) for this image (%ux%u)\n",
__FUNCTION__, __LINE__,
params->shm.mmap_size, property.w , property.h);
goto done;
}
ok = funcs->file_data(loader_data, &property, map, &error);
if (!ok || (error != EVAS_LOAD_ERROR_NONE))
{
@ -458,8 +464,9 @@ image_load(const char *file, const char *key, const char *shmfile,
result->w = property.w;
result->h = property.h;
result->alpha = property.alpha;
if (property.alpha)
if (property.alpha && property.premul)
{
result->alpha_sparse = evas_cserve2_image_premul_data((unsigned int *) map,
result->w * result->h);
@ -487,22 +494,32 @@ done:
static void
handle_image_open(int wfd, void *params)
{
Slave_Msg_Image_Open *p;
Slave_Msg_Image_Open *msg = params;
Slave_Msg_Image_Opened result;
Evas_Image_Load_Opts load_opts;
Error_Type err;
const char *loader = NULL, *file, *key, *ptr;
char *resp;
size_t resp_size;
p = params;
file = (const char *)(p + sizeof(Slave_Msg_Image_Open));
memset(&load_opts, 0, sizeof(load_opts));
load_opts.region.x = msg->lo.region.x;
load_opts.region.y = msg->lo.region.y;
load_opts.region.w = msg->lo.region.w;
load_opts.region.h = msg->lo.region.h;
load_opts.dpi = msg->lo.dpi;
load_opts.w = msg->lo.w;
load_opts.h = msg->lo.h;
load_opts.scale_down_by = msg->lo.scale_down_by;
load_opts.orientation = msg->lo.orientation;
file = (const char *) (msg + 1);
key = file + strlen(file) + 1;
ptr = key + strlen(key) + 1;
if (p->has_loader_data)
loader = ptr;
loader = ptr;
memset(&result, 0, sizeof(result));
if ((err = image_open(file, key, &result, &loader))
if ((err = image_open(file, key, &result, &loader, &load_opts))
!= CSERVE2_NONE)
{
printf("OPEN failed at %s:%d\n", __FUNCTION__, __LINE__);

View File

@ -128,7 +128,8 @@ _slave_proc_dead_cb(int pid, int status EINA_UNUSED)
{
Slave_Proc *s;
DBG("Child dead with pid '%d'.", pid);
INF("Child dead with pid '%d': signal %d",
pid, WIFSIGNALED(status) ? WTERMSIG(status) : 0);
s = _slave_proc_find(pid);
if (!s)
{

View File

@ -176,48 +176,81 @@ _usage_msg_send(void)
}
}
static void
_shared_index_print(Msg_Base *data, size_t size)
{
Msg_Index_List *msg = (Msg_Index_List *) data;
if (size < sizeof(*msg) || msg->base.type != CSERVE2_INDEX_LIST)
{
ERR("Invalid message received from server. "
"Something went wrong.");
return;
}
printf("Printing shared indexes status.\n");
printf("===============================\n\n");
printf("Generation ID: %-4d\n", msg->generation_id);
printf("Strings entries path: %s\n", msg->strings_entries_path);
printf("Strings index path: %s\n", msg->strings_index_path);
printf("Files index path: %s\n", msg->files_index_path);
printf("Images index path: %s\n", msg->images_index_path);
printf("Fonts index path: %s\n", msg->fonts_index_path);
printf("\n\n\n");
}
static void
_usage_msg_read(void)
{
Msg_Stats *msg = NULL;
Msg_Stats *stats = NULL;
int size;
printf("Requesting server statistics.\n\n");
while (!msg)
msg = _server_read(&size);
if (msg->base.type != CSERVE2_STATS)
while (!stats)
{
ERR("Invalid message received from server."
"Something went badly wrong.");
return;
Msg_Base *msg = _server_read(&size);
if (!msg) continue;
switch (msg->type)
{
case CSERVE2_INDEX_LIST:
_shared_index_print(msg, size);
break;
case CSERVE2_STATS:
stats = (Msg_Stats *) msg;
break;
default:
ERR("Invalid message received from server. "
"Something went badly wrong.");
return;
}
}
printf("Printing server usage.\n");
printf("======================\n\n");
printf("\nImage Usage Statistics:\n");
printf("----------------------\n\n");
printf("Image headers usage: %d bytes\n", msg->images.files_size);
printf("Image data requested: %d kbytes\n", msg->images.requested_size / 1024);
printf("Image data usage: %d kbytes\n", msg->images.images_size / 1024);
printf("Image data unused: %d kbytes\n", msg->images.unused_size / 1024);
printf("Image headers load time: %dus\n", msg->images.files_load_time);
printf("Image headers saved time: %dus\n", msg->images.files_saved_time);
printf("Image data load time: %dus\n", msg->images.images_load_time);
printf("Image data saved time: %dus\n", msg->images.images_saved_time);
printf("Image headers usage: %d bytes\n", stats->images.files_size);
printf("Image data requested: %d kbytes\n", stats->images.requested_size / 1024);
printf("Image data usage: %d kbytes\n", stats->images.images_size / 1024);
printf("Image data unused: %d kbytes\n", stats->images.unused_size / 1024);
printf("Image headers load time: %dus\n", stats->images.files_load_time);
printf("Image headers saved time: %dus\n", stats->images.files_saved_time);
printf("Image data load time: %dus\n", stats->images.images_load_time);
printf("Image data saved time: %dus\n", stats->images.images_saved_time);
printf("\nFont Usage Statistics:\n");
printf("----------------------\n\n");
printf("Requested usage: %d bytes\n", msg->fonts.requested_size);
printf("Real usage: %d bytes\n", msg->fonts.real_size);
printf("Unused size: %d bytes\n", msg->fonts.unused_size);
printf("Fonts load time: %dus\n", msg->fonts.fonts_load_time);
printf("Fonts used load time: %dus\n", msg->fonts.fonts_used_load_time);
printf("Fonts used saved time: %dus\n", msg->fonts.fonts_used_saved_time);
printf("Glyphs load time: %dus\n", msg->fonts.glyphs_load_time);
printf("Glyphs render time: %dus\n", msg->fonts.glyphs_render_time);
printf("Glyphs saved time: %dus\n", msg->fonts.glyphs_saved_time);
printf("Glyphs request time: %dus\n", msg->fonts.glyphs_request_time);
printf("Glyphs slave time: %dus\n", msg->fonts.glyphs_slave_time);
printf("Requested usage: %d bytes\n", stats->fonts.requested_size);
printf("Real usage: %d bytes\n", stats->fonts.real_size);
printf("Unused size: %d bytes\n", stats->fonts.unused_size);
printf("Fonts load time: %dus\n", stats->fonts.fonts_load_time);
printf("Fonts used load time: %dus\n", stats->fonts.fonts_used_load_time);
printf("Fonts used saved time: %dus\n", stats->fonts.fonts_used_saved_time);
printf("Glyphs load time: %dus\n", stats->fonts.glyphs_load_time);
printf("Glyphs render time: %dus\n", stats->fonts.glyphs_render_time);
printf("Glyphs saved time: %dus\n", stats->fonts.glyphs_saved_time);
printf("Glyphs request time: %dus\n", stats->fonts.glyphs_request_time);
printf("Glyphs slave time: %dus\n", stats->fonts.glyphs_slave_time);
printf("\n");
}

View File

@ -33,23 +33,23 @@
// Default LRU size. If 0, all scaled images will be dropped instantly.
#define DEFAULT_CACHE_LRU_SIZE (4*1024*1024)
static void _evas_cache_image_dirty_add(Image_Entry *im);
static void _evas_cache_image_dirty_del(Image_Entry *im);
static void _evas_cache_image_activ_add(Image_Entry *im);
static void _evas_cache_image_activ_del(Image_Entry *im);
static void _evas_cache_image_lru_add(Image_Entry *im);
static void _evas_cache_image_lru_del(Image_Entry *im);
static void _evas_cache2_image_dirty_add(Image_Entry *im);
static void _evas_cache2_image_dirty_del(Image_Entry *im);
static void _evas_cache2_image_activ_add(Image_Entry *im);
static void _evas_cache2_image_activ_del(Image_Entry *im);
static void _evas_cache2_image_lru_add(Image_Entry *im);
static void _evas_cache2_image_lru_del(Image_Entry *im);
static void _evas_cache2_image_entry_preload_remove(Image_Entry *ie, const void *target);
// static void _evas_cache_image_lru_nodata_add(Image_Entry *im);
// static void _evas_cache_image_lru_nodata_del(Image_Entry *im);
// static void _evas_cache2_image_lru_nodata_add(Image_Entry *im);
// static void _evas_cache2_image_lru_nodata_del(Image_Entry *im);
static void
_evas_cache_image_dirty_add(Image_Entry *im)
_evas_cache2_image_dirty_add(Image_Entry *im)
{
if (im->flags.dirty) return;
_evas_cache_image_activ_del(im);
_evas_cache_image_lru_del(im);
// _evas_cache_image_lru_nodata_del(im);
_evas_cache2_image_activ_del(im);
_evas_cache2_image_lru_del(im);
// _evas_cache2_image_lru_nodata_del(im);
im->flags.dirty = 1;
im->flags.cached = 1;
im->cache2->dirty = eina_inlist_prepend(im->cache2->dirty, EINA_INLIST_GET(im));
@ -61,7 +61,7 @@ _evas_cache_image_dirty_add(Image_Entry *im)
}
static void
_evas_cache_image_dirty_del(Image_Entry *im)
_evas_cache2_image_dirty_del(Image_Entry *im)
{
if (!im->flags.dirty) return;
if (!im->cache2) return;
@ -71,12 +71,12 @@ _evas_cache_image_dirty_del(Image_Entry *im)
}
static void
_evas_cache_image_activ_add(Image_Entry *im)
_evas_cache2_image_activ_add(Image_Entry *im)
{
if (im->flags.activ) return;
_evas_cache_image_dirty_del(im);
_evas_cache_image_lru_del(im);
// _evas_cache_image_lru_nodata_del(im);
_evas_cache2_image_dirty_del(im);
_evas_cache2_image_lru_del(im);
// _evas_cache2_image_lru_nodata_del(im);
if (!im->cache_key) return;
im->flags.activ = 1;
im->flags.cached = 1;
@ -84,7 +84,7 @@ _evas_cache_image_activ_add(Image_Entry *im)
}
static void
_evas_cache_image_activ_del(Image_Entry *im)
_evas_cache2_image_activ_del(Image_Entry *im)
{
if (!im->flags.activ) return;
if (!im->cache_key) return;
@ -94,12 +94,12 @@ _evas_cache_image_activ_del(Image_Entry *im)
}
static void
_evas_cache_image_lru_add(Image_Entry *im)
_evas_cache2_image_lru_add(Image_Entry *im)
{
if (im->flags.lru) return;
_evas_cache_image_dirty_del(im);
_evas_cache_image_activ_del(im);
// _evas_cache_image_lru_nodata_del(im);
_evas_cache2_image_dirty_del(im);
_evas_cache2_image_activ_del(im);
// _evas_cache2_image_lru_nodata_del(im);
if (!im->cache_key) return;
im->flags.lru = 1;
im->flags.cached = 1;
@ -109,7 +109,7 @@ _evas_cache_image_lru_add(Image_Entry *im)
}
static void
_evas_cache_image_lru_del(Image_Entry *im)
_evas_cache2_image_lru_del(Image_Entry *im)
{
if (!im->flags.lru) return;
if (!im->cache_key) return;
@ -122,19 +122,19 @@ _evas_cache_image_lru_del(Image_Entry *im)
/*
static void
_evas_cache_image_lru_nodata_add(Image_Entry *im)
_evas_cache2_image_lru_nodata_add(Image_Entry *im)
{
if (im->flags.lru_nodata) return;
_evas_cache_image_dirty_del(im);
_evas_cache_image_activ_del(im);
_evas_cache_image_lru_del(im);
_evas_cache2_image_dirty_del(im);
_evas_cache2_image_activ_del(im);
_evas_cache2_image_lru_del(im);
im->flags.lru = 1;
im->flags.cached = 1;
im->cache2->lru_nodata = eina_inlist_prepend(im->cache2->lru_nodata, EINA_INLIST_GET(im));
}
static void
_evas_cache_image_lru_nodata_del(Image_Entry *im)
_evas_cache2_image_lru_nodata_del(Image_Entry *im)
{
if (!im->flags.lru_nodata) return;
im->flags.lru = 0;
@ -177,7 +177,7 @@ _timestamp_build(Image_Timestamp *tstamp, struct stat *st)
}
static void
_evas_cache_image_entry_delete(Evas_Cache2 *cache, Image_Entry *ie)
_evas_cache2_image_entry_delete(Evas_Cache2 *cache, Image_Entry *ie)
{
if (!ie) return;
@ -191,10 +191,10 @@ _evas_cache_image_entry_delete(Evas_Cache2 *cache, Image_Entry *ie)
return;
}
_evas_cache_image_dirty_del(ie);
_evas_cache_image_activ_del(ie);
_evas_cache_image_lru_del(ie);
// _evas_cache_image_lru_nodata_del(ie);
_evas_cache2_image_dirty_del(ie);
_evas_cache2_image_activ_del(ie);
_evas_cache2_image_lru_del(ie);
// _evas_cache2_image_lru_nodata_del(ie);
if (ie->data1)
@ -220,7 +220,7 @@ _evas_cache_image_entry_delete(Evas_Cache2 *cache, Image_Entry *ie)
}
static Image_Entry *
_evas_cache_image_entry_new(Evas_Cache2 *cache,
_evas_cache2_image_entry_new(Evas_Cache2 *cache,
const char *hkey,
Image_Timestamp *tstamp,
const char *file,
@ -264,15 +264,15 @@ _evas_cache_image_entry_new(Evas_Cache2 *cache,
{
ERR("couldn't load '%s' '%s' with cserve2!",
ie->file, ie->key ? ie->key : "");
_evas_cache_image_entry_delete(cache, ie);
_evas_cache2_image_entry_delete(cache, ie);
if (error)
*error = EVAS_LOAD_ERROR_GENERIC;
return NULL;
}
}
if (ie->cache_key) _evas_cache_image_activ_add(ie);
else _evas_cache_image_dirty_add(ie);
if (ie->cache_key) _evas_cache2_image_activ_add(ie);
else _evas_cache2_image_dirty_add(ie);
if (error)
*error = EVAS_LOAD_ERROR_NONE;
@ -319,7 +319,7 @@ _evas_cache2_image_preloaded_cb(void *data, Eina_Bool success)
}
if (ie->flags.delete_me)
_evas_cache_image_entry_delete(ie->cache2, ie);
_evas_cache2_image_entry_delete(ie->cache2, ie);
}
static Eina_Bool
@ -393,7 +393,7 @@ evas_cache2_image_copied_data(Evas_Cache2 *cache, unsigned int w, unsigned int h
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache2_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im)
return NULL;
@ -402,7 +402,7 @@ evas_cache2_image_copied_data(Evas_Cache2 *cache, unsigned int w, unsigned int h
evas_cache2_image_surface_alloc(im, w, h);
if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
{
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
return NULL;
}
@ -423,14 +423,14 @@ evas_cache2_image_data(Evas_Cache2 *cache, unsigned int w, unsigned int h, DATA3
(cspace == EVAS_COLORSPACE_YCBCR422601_PL))
w &= ~0x1;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache2_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im) return NULL;
im->w = w;
im->h = h;
im->flags.alpha = alpha;
if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
{
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
return NULL;
}
im->references = 1;
@ -444,7 +444,7 @@ evas_cache2_image_empty(Evas_Cache2 *cache)
{
Image_Entry *im;
im = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
im = _evas_cache2_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL, NULL);
if (!im)
return NULL;
@ -467,7 +467,7 @@ evas_cache2_image_size_set(Image_Entry *im, unsigned int w, unsigned h)
if ((im->w == w) && (im->h == h)) return im;
cache = im->cache2;
im2 = _evas_cache_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL,
im2 = _evas_cache2_image_entry_new(cache, NULL, NULL, NULL, NULL, NULL,
NULL);
if (!im2) goto on_error;
@ -486,7 +486,7 @@ evas_cache2_image_size_set(Image_Entry *im, unsigned int w, unsigned h)
on_error:
if (im2)
_evas_cache_image_entry_delete(cache, im2);
_evas_cache2_image_entry_delete(cache, im2);
return NULL;
}
@ -510,7 +510,7 @@ evas_cache2_init(const Evas_Cache2_Image_Func *cb)
}
static Eina_Bool
_evas_cache_image_free_cb(EINA_UNUSED const Eina_Hash *hash, EINA_UNUSED const void *key, void *data, void *fdata)
_evas_cache2_image_free_cb(EINA_UNUSED const Eina_Hash *hash, EINA_UNUSED const void *key, void *data, void *fdata)
{
Eina_List **delete_list = fdata;
*delete_list = eina_list_prepend(*delete_list, data);
@ -526,20 +526,20 @@ evas_cache2_shutdown(Evas_Cache2 *cache)
while (cache->lru)
{
im = (Image_Entry *)cache->lru;
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
}
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
while (cache->dirty)
{
im = (Image_Entry *)cache->dirty;
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
}
delete_list = NULL;
eina_hash_foreach(cache->activ, _evas_cache_image_free_cb, &delete_list);
eina_hash_foreach(cache->activ, _evas_cache2_image_free_cb, &delete_list);
while (delete_list)
{
_evas_cache_image_entry_delete(cache, eina_list_data_get(delete_list));
_evas_cache2_image_entry_delete(cache, eina_list_data_get(delete_list));
delete_list = eina_list_remove_list(delete_list, delete_list);
}
@ -549,8 +549,17 @@ evas_cache2_shutdown(Evas_Cache2 *cache)
free(cache);
}
static void
_create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key, size_t keylen, Evas_Image_Load_Opts *lo)
EAPI Eina_Bool
evas_cache2_image_cached(Image_Entry *ie)
{
if (!ie) return EINA_FALSE;
return (ie->cache2 != NULL);
}
EAPI void
evas_cache2_image_cache_key_create(char *hkey, const char *path, size_t pathlen,
const char *key, size_t keylen,
const Evas_Image_Load_Opts *lo)
{
const char *ckey = "(null)";
size_t size;
@ -561,6 +570,7 @@ _create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key,
memcpy(hkey + size, "//://", 5);
size += 5;
if (key) ckey = key;
else keylen = 6;
memcpy(hkey + size, ckey, keylen);
size += keylen;
if (lo)
@ -634,7 +644,8 @@ _create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key,
}
EAPI Image_Entry *
evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Evas_Image_Load_Opts *lo, int *error)
evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key,
Evas_Image_Load_Opts *lo, int *error)
{
size_t size;
size_t pathlen;
@ -659,7 +670,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Ev
size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN;
hkey = alloca(sizeof(char) * size);
_create_hash_key(hkey, path, pathlen, key, keylen, lo);
evas_cache2_image_cache_key_create(hkey, path, pathlen, key, keylen, lo);
DBG("Looking at the hash for key '%s'", hkey);
/* use local var to copy default load options to the image entry */
@ -697,7 +708,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Ev
* of an image at a given key. we wither find it and keep re-reffing
* it or we dirty it and get it out */
DBG("Entry on inactive hash was invalid (file changed or deleted).");
_evas_cache_image_dirty_add(im);
_evas_cache2_image_dirty_add(im);
im = NULL;
}
@ -723,15 +734,15 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Ev
if (ok)
{
/* remove from lru and make it active again */
_evas_cache_image_lru_del(im);
_evas_cache_image_activ_add(im);
_evas_cache2_image_lru_del(im);
_evas_cache2_image_activ_add(im);
goto on_ok;
}
DBG("Entry on inactive hash was invalid (file changed or deleted).");
/* as avtive cache find - if we match in lru and its invalid, dirty */
_evas_cache_image_dirty_add(im);
_evas_cache2_image_dirty_add(im);
/* this image never used, so it have to be deleted */
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
im = NULL;
}
if (stat_failed) goto on_stat_error;
@ -742,7 +753,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Ev
}
_timestamp_build(&tstamp, &st);
DBG("Creating a new entry for key '%s'.", hkey);
im = _evas_cache_image_entry_new(cache, hkey, &tstamp, path, key,
im = _evas_cache2_image_entry_new(cache, hkey, &tstamp, path, key,
lo, error);
if (!im) goto on_stat_error;
@ -773,7 +784,7 @@ on_stat_error:
else
*error = EVAS_LOAD_ERROR_GENERIC;
if (im) _evas_cache_image_entry_delete(cache, im);
if (im) _evas_cache2_image_entry_delete(cache, im);
return NULL;
}
@ -788,7 +799,8 @@ evas_cache2_image_open_wait(Image_Entry *im)
}
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)
_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;
@ -816,7 +828,8 @@ _scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h,
if (!smooth)
{
lo.scale_load.smooth = 1;
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
im->key, keylen, &lo);
ret = eina_hash_find(im->cache2->activ, hkey);
if (ret) goto found;
@ -827,7 +840,8 @@ _scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h,
lo.scale_load.smooth = smooth;
}
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
im->key, keylen, &lo);
ret = eina_hash_find(im->cache2->activ, hkey);
if (ret) goto found;
@ -838,8 +852,8 @@ _scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h,
if (!ret) return NULL;
/* Remove from lru and make it active again */
_evas_cache_image_lru_del(ret);
_evas_cache_image_activ_add(ret);
_evas_cache2_image_lru_del(ret);
_evas_cache2_image_activ_add(ret);
found:
ret->references++;
@ -860,6 +874,9 @@ evas_cache2_image_scale_load(Image_Entry *im,
int error = EVAS_LOAD_ERROR_NONE;
Image_Entry *ret;
if (!im->cache2)
return im;
if (!smooth && im->scale_hint != EVAS_IMAGE_SCALE_HINT_STATIC)
goto parent_out;
@ -896,15 +913,16 @@ evas_cache2_image_scale_load(Image_Entry *im,
lo.scale_load.smooth = smooth;
lo.scale_load.scale_hint = im->scale_hint;
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
im->key, keylen, &lo);
ret = _evas_cache_image_entry_new(im->cache2, hkey, NULL, im->file, im->key,
ret = _evas_cache2_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);
if (ret) _evas_cache2_image_entry_delete(im->cache2, ret);
goto parent_out;
}
@ -948,13 +966,13 @@ evas_cache2_image_close(Image_Entry *im)
if (references > 0)
return;
if (im->flags.dirty)
if (im->flags.dirty || im->animated.animated)
{
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
return;
}
_evas_cache_image_lru_add(im);
_evas_cache2_image_lru_add(im);
if (cache)
evas_cache2_flush(cache);
}
@ -965,7 +983,10 @@ evas_cache2_image_load_data(Image_Entry *ie)
int error = EVAS_LOAD_ERROR_NONE;
if ((ie->flags.loaded) && (!ie->animated.animated))
return error;
{
evas_cserve2_image_hit(ie);
return EVAS_LOAD_ERROR_NONE;
}
ie->flags.in_progress = EINA_TRUE;
@ -976,10 +997,10 @@ evas_cache2_image_load_data(Image_Entry *ie)
error = evas_cserve2_image_load_data_wait(ie);
RGBA_Image *im = (RGBA_Image *)ie;
DBG("try cserve2 image data '%s' '%s' loaded!",
ie->file, ie->key ? ie->key : "");
if ((error == CSERVE2_NONE) && im->image.data)
{
DBG("try cserve2 image data '%s' '%s' loaded!",
ie->file, ie->key ? ie->key : "");
error = EVAS_LOAD_ERROR_NONE;
}
else
@ -1060,7 +1081,7 @@ evas_cache2_image_writable(Image_Entry *im)
if (!im->cache_key)
{
if (!im->flags.dirty)
_evas_cache_image_dirty_add(im);
_evas_cache2_image_dirty_add(im);
return im;
}
@ -1075,7 +1096,7 @@ evas_cache2_image_writable(Image_Entry *im)
on_error:
if (im2)
_evas_cache_image_entry_delete(cache, im2);
_evas_cache2_image_entry_delete(cache, im2);
return NULL;
}
@ -1088,7 +1109,7 @@ evas_cache2_image_dirty(Image_Entry *im, unsigned int x, unsigned int y, unsigne
if (!im->cache_key)
{
if (!im->flags.dirty)
_evas_cache_image_dirty_add(im);
_evas_cache2_image_dirty_add(im);
im2 = im;
}
else
@ -1123,7 +1144,7 @@ evas_cache2_flush(Evas_Cache2 *cache)
im = (Image_Entry *)cache->lru->last;
DBG("Remove unused entry from cache.");
_evas_cache_image_entry_delete(cache, im);
_evas_cache2_image_entry_delete(cache, im);
}
return cache->usage;

View File

@ -66,6 +66,7 @@ EAPI void evas_cache2_image_close(Image_Entry *im);
EAPI int evas_cache2_image_load_data(Image_Entry *ie);
EAPI void evas_cache2_image_unload_data(Image_Entry *im);
EAPI void evas_cache2_image_preload_data(Image_Entry *im, const void *target);
EAPI void evas_cache2_image_cache_key_create(char *hkey, const char *path, size_t pathlen, const char *key, size_t keylen, const Evas_Image_Load_Opts *lo);
EAPI DATA32 * evas_cache2_image_pixels(Image_Entry *im);
EAPI Image_Entry * evas_cache2_image_writable(Image_Entry *im);
@ -75,6 +76,7 @@ EAPI Image_Entry * evas_cache2_image_size_set(Image_Entry *im, unsigned int w, u
EAPI Image_Entry * evas_cache2_image_dirty(Image_Entry *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
EAPI Image_Entry * evas_cache2_image_empty(Evas_Cache2 *cache);
EAPI void evas_cache2_image_surface_alloc(Image_Entry *ie, int w, int h);
EAPI Eina_Bool evas_cache2_image_cached(Image_Entry *ie);
EAPI int evas_cache2_flush(Evas_Cache2 *cache);
EAPI void evas_cache2_limit_set(Evas_Cache2 *cache, int limit);

View File

@ -55,7 +55,11 @@ evas_init(void)
if (!evas_async_events_init())
goto shutdown_module;
#ifdef EVAS_CSERVE2
if (getenv("EVAS_CSERVE2")) evas_cserve2_init();
{
const char *env;
env = getenv("EVAS_CSERVE2");
if (env && atoi(env)) evas_cserve2_init();
}
#endif
_evas_preload_thread_init();
@ -95,6 +99,11 @@ evas_shutdown(void)
EINA_LOG_STATE_START,
EINA_LOG_STATE_SHUTDOWN);
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cserve2_shutdown();
#endif
eina_cow_del(evas_object_proxy_cow);
eina_cow_del(evas_object_map_cow);
eina_cow_del(evas_object_state_cow);

View File

@ -3998,53 +3998,15 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
(o->cur->border.b == 0) &&
(o->cur->border.fill != 0))
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
Image_Entry *ie;
void *data = pixels;
int w = imagew, h = imageh;
Eina_Bool mustclose = EINA_FALSE;
ie = evas_cache2_image_scale_load
((Image_Entry *)pixels,
0, 0,
imagew, imageh,
iw, ih, o->cur->smooth_scale);
if (ie != &((RGBA_Image *)pixels)->cache_entry)
{
data = ie;
w = iw;
h = ih;
mustclose = EINA_TRUE;
}
_draw_image
(obj, 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,
do_async);
if (mustclose)
evas_cache2_image_close(ie);
}
else
#endif
{
_draw_image
(obj, 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,
do_async);
}
_draw_image
(obj, 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,
do_async);
}
else
{

View File

@ -66,6 +66,8 @@ void
evas_object_inform_call_image_preloaded(Evas_Object *eo_obj)
{
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
EINA_SAFETY_ON_NULL_RETURN(obj);
if (!_evas_object_image_preloading_get(eo_obj)) return;
_evas_object_image_preloading_check(eo_obj);
_evas_object_image_preloading_set(eo_obj, 0);

View File

@ -1571,7 +1571,7 @@ static Eina_Bool
_drop_image_cache_ref(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(data))
evas_cache2_image_close((Image_Entry *)data);
else
#endif

View File

@ -7,6 +7,10 @@
#include "evas_font_ot.h"
#ifdef EVAS_CSERVE2
#include "../cserve2/evas_cs2_private.h"
#endif
struct _Evas_Glyph
{
RGBA_Font_Glyph *fg;
@ -227,6 +231,19 @@ evas_common_font_rgba_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, int x, int y,
void
evas_common_font_glyphs_ref(Evas_Glyph_Array *array)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get() && !array->refcount)
{
Eina_Iterator *iter;
Evas_Glyph *glyph;
iter = eina_inarray_iterator_new(array->array);
EINA_ITERATOR_FOREACH(iter, glyph)
evas_cserve2_font_glyph_ref(glyph->fg->glyph_out, EINA_TRUE);
eina_iterator_free(iter);
}
#endif
array->refcount++;
}
@ -235,6 +252,19 @@ evas_common_font_glyphs_unref(Evas_Glyph_Array *array)
{
if (--array->refcount) return;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
Eina_Iterator *iter;
Evas_Glyph *glyph;
iter = eina_inarray_iterator_new(array->array);
EINA_ITERATOR_FOREACH(iter, glyph)
evas_cserve2_font_glyph_ref(glyph->fg->glyph_out, EINA_FALSE);
eina_iterator_free(iter);
}
#endif
eina_inarray_free(array->array);
evas_common_font_int_unref(array->fi);
free(array);
@ -274,6 +304,18 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props)
if (text_props->len < unit) unit = text_props->len;
if (text_props->glyphs && text_props->glyphs->refcount == 1)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
Eina_Iterator *iter;
Evas_Glyph *glyph;
iter = eina_inarray_iterator_new(text_props->glyphs->array);
EINA_ITERATOR_FOREACH(iter, glyph)
evas_cserve2_font_glyph_ref(glyph->fg->glyph_out, EINA_FALSE);
eina_iterator_free(iter);
}
#endif
glyphs = text_props->glyphs->array;
glyphs->len = 0;
reused_glyphs = EINA_TRUE;
@ -304,7 +346,16 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props)
fg = evas_common_font_int_cache_glyph_get(fi, idx);
if (!fg) continue;
if (!fg->glyph_out) evas_common_font_int_cache_glyph_render(fg);
if (!evas_common_font_int_cache_glyph_render(fg))
{
fg = NULL;
goto error;
}
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cserve2_font_glyph_ref(fg->glyph_out, EINA_TRUE);
#endif
glyph = eina_inarray_grow(glyphs, 1);
if (!glyph) goto error;

View File

@ -548,12 +548,21 @@ evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg)
fg->glyph_out = evas_cserve2_font_glyph_bitmap_get(fi->cs2_handler,
fg->index,
fg->fi->hinting);
if (fg->glyph_out)
return EINA_TRUE;
if (!fg->glyph_out)
{
if (!fi->fash) fi->fash = _fash_gl_new();
if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1));
free(fg);
return EINA_FALSE;
}
return EINA_TRUE;
}
#endif
/* no cserve2 case */
if (fg->glyph_out)
return EINA_TRUE;
FTLOCK();
error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
if (error)

View File

@ -243,18 +243,10 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
struct evas_image_foreach_loader_data fdata;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
ERR("This function shouldn't be called anymore!");
// DBG("try cserve2 '%s' '%s'", ie->file, ie->key ? ie->key : "");
// if (evas_cserve2_image_load(ie, ie->file, ie->key, &(ie->load_opts)))
// {
// DBG("try cserve2 '%s' '%s' loaded!",
// ie->file, ie->key ? ie->key : "");
// return EVAS_LOAD_ERROR_NONE;
// }
}
if (evas_cserve2_use_get() && evas_cache2_image_cached(ie))
CRIT("This function shouldn't be called anymore!");
#endif
if (ie->f)
{
len = strlen(eina_file_filename_get(ie->f));
@ -368,25 +360,8 @@ evas_common_load_rgba_image_data_from_file(Image_Entry *ie)
if ((ie->flags.loaded) && (!ie->animated.animated)) return EVAS_LOAD_ERROR_GENERIC;
#ifdef EVAS_CSERVE2
if (ie->data1)
{
ERR("This function shouldn't be called anymore!");
// DBG("try cserve2 image data '%s' '%s'",
// ie->file, ie->key ? ie->key : "");
// if (evas_cserve2_image_data_load(ie))
// {
// RGBA_Image *im = (RGBA_Image *)ie;
// im->image.data = evas_cserve2_image_data_get(ie);
// DBG("try cserve2 image data '%s' '%s' loaded!",
// ie->file, ie->key ? ie->key : "");
// if (im->image.data)
// {
// im->image.no_free = 1;
// return EVAS_LOAD_ERROR_NONE;
// }
// }
// return EVAS_LOAD_ERROR_GENERIC;
}
if (evas_cserve2_use_get() && evas_cache2_image_cached(ie))
CRIT("This function shouldn't be called anymore!");
#endif
if (!ie->info.module) return EVAS_LOAD_ERROR_GENERIC;

View File

@ -663,7 +663,7 @@ evas_common_rgba_image_scalecache_do_cbs(Image_Entry *ie, RGBA_Image *dst,
if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
evas_cache2_image_load_data(&im->cache_entry);
else
#endif
@ -759,6 +759,26 @@ evas_common_rgba_image_scalecache_do_cbs(Image_Entry *ie, RGBA_Image *dst,
}
}
}
#ifdef EVAS_CSERVE2
if (sci->populate_me && (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
&& evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
{
RGBA_Image *im2 = (RGBA_Image *) evas_cache2_image_scale_load
(&im->cache_entry, src_region_x, src_region_y,
src_region_w, src_region_h, dst_region_w, dst_region_h, smooth);
SLKL(cache_lock);
if (im2 != im)
{
sci->im = im2;
sci->populate_me = 0;
cache_list = eina_inlist_append(cache_list, (Eina_Inlist *)sci);
didpop = 1;
}
SLKU(cache_lock);
}
#endif
if (sci->populate_me)
{
// INF("##! populate!");

View File

@ -23,6 +23,7 @@ typedef enum {
CSERVE2_FONT_GLYPHS_USED,
CSERVE2_STATS,
CSERVE2_FONT_DEBUG,
CSERVE2_INDEX_LIST,
CSERVE2_ERROR
} Message_Type;
@ -38,6 +39,7 @@ typedef enum {
CSERVE2_LOADER_DIED,
CSERVE2_LOADER_EXEC_ERR,
CSERVE2_INVALID_CACHE, // invalid cserve cache entry
CSERVE2_NOT_LOADED,
CSERVE2_FILE_CHANGED,
CSERVE2_REQUEST_CANCEL
} Error_Type;
@ -72,6 +74,7 @@ struct _Msg_Opened {
int loop_count;
int loop_hint; /* include Evas.h? Copy the enum around? */
Eina_Bool alpha : 1;
Eina_Bool animated : 1;
} image;
};
@ -88,6 +91,10 @@ struct _Msg_Loaded {
int mmap_size;
int image_size;
} shm;
struct {
unsigned int w, h; // Real dimensions of this image. May differ from Msg_Opened::image::{w,h} after scaling.
} image;
Eina_Bool alpha : 1;
Eina_Bool alpha_sparse : 1;
};
@ -183,7 +190,6 @@ struct _Msg_Font_Glyphs_Request {
*/
struct _Msg_Font_Glyphs_Loaded {
Msg_Base base;
unsigned int ncaches;
};
struct _Msg_Stats {
@ -224,13 +230,14 @@ struct _Msg_Stats {
} images;
};
/*
/**
* @struct _Msg_Font_Debug
*
* Message from server containing all font cache info.
*
* Content of the message follows:
*
* * char fonts_index_path[64]
* * number of font entries;
* * each font entry:
* - unsigned int filelen
@ -241,15 +248,15 @@ struct _Msg_Stats {
* - unsigned int size;
* - unsigned int dpi;
* - unsigned int unused;
* - ncaches:
* - each cache:
* * usigned int shmnamelen;
* * const char shmname;
* * unsigned int size;
* * unsigned int usage;
* * unsigned int nglyphs;
* * each glyph:
* - const char glyph_data_shm[64];
* - const char glyph_mempool_shm[64];
* - unsigned int nglyphs;
* - each glyph: Glyph_Data struct
* - unsigned int id;
* - unsigned int refcount;
* - unsigned int index;
* - unsigned int shm_id; // shared string id
* - unsigned int buffer_id;
* - unsigned int offset;
* - unsigned int size;
* - unsigned int rows;
@ -260,6 +267,136 @@ struct _Msg_Stats {
*/
struct _Msg_Font_Debug {
Msg_Base base;
char fonts_index_path[64];
int nfonts;
};
/**
* @brief The Msg_Index_List struct
*
* Message sent from the server, without request from the client,
* to inform all clients of the shared index files. Contains the paths
* to the latest File, Image and Font index shm.
*
* The paths contain only the filename used in the call to shm_open.
* All strings must be null-terminated.
*/
struct _Msg_Index_List {
Msg_Base base;
int generation_id;
char strings_index_path[64];
char strings_entries_path[64];
char files_index_path[64];
char images_index_path[64];
char fonts_index_path[64];
};
typedef struct _Shm_Object Shm_Object;
typedef struct _Index_Entry Index_Entry;
typedef struct _File_Data File_Data;
typedef struct _Image_Data Image_Data;
typedef struct _Font_Data Font_Data;
typedef struct _Glyph_Data Glyph_Data;
typedef struct _Shared_Array_Header Shared_Array_Header;
typedef int string_t;
#define SHMOBJECT unsigned int id; unsigned int refcount
struct _Shared_Array_Header {
int32_t tag;
int32_t generation_id;
int32_t elemsize;
int32_t count;
int32_t emptyidx;
int32_t sortedidx;
int32_t _reserved1;
int32_t _reserved2;
};
struct _Shm_Object {
SHMOBJECT;
};
#define STRING_INDEX_ARRAY_TAG ('S' | 'T' << 8 | 'R' << 16 | 'N' << 24)
#define STRING_MEMPOOL_FAKETAG ('S' | 'T' << 8 | 'R' << 16 | 'M' << 24)
struct _Index_Entry {
SHMOBJECT;
// Block entry
int32_t length;
int32_t offset;
int32_t shmid;
};
#define FILE_DATA_ARRAY_TAG ('F' | 'I' << 8 | 'L' << 16 | 'E' << 24)
struct _File_Data {
SHMOBJECT;
// Hash entry elements (see Evas_Image_Load_Opts)
string_t path;
string_t key;
struct {
struct {
unsigned int x, y, w, h;
} region;
double dpi;
unsigned int w, h;
int scale_down_by;
Eina_Bool orientation;
} lo;
// Properties set after opening the file
string_t loader_data; // Can also be set during open (force this loader)
int w, h;
int frame_count;
int loop_count;
int loop_hint;
Eina_Bool alpha : 1;
Eina_Bool invalid : 1;
Eina_Bool valid : 1;
Eina_Bool animated : 1;
};
#define IMAGE_DATA_ARRAY_TAG ('I' | 'M' << 8 | 'A' << 16 | 'G' << 24)
struct _Image_Data {
SHMOBJECT;
uint32_t file_id;
string_t shm_id;
Evas_Image_Load_Opts opts;
uint32_t w, h;
Eina_Bool alpha : 1;
Eina_Bool alpha_sparse : 1;
Eina_Bool unused : 1;
Eina_Bool doload : 1;
Eina_Bool valid : 1;
};
#define FONT_DATA_ARRAY_TAG ('F' | 'O' << 8 | 'N' << 16 | 'T' << 24)
struct _Font_Data {
SHMOBJECT;
string_t name;
string_t file;
string_t glyph_index_shm;
string_t mempool_shm;
uint32_t rend_flags;
uint32_t size;
uint32_t dpi;
};
#define GLYPH_DATA_ARRAY_TAG ('G' | 'L' << 8 | 'P' << 16 | 'H' << 24)
struct _Glyph_Data {
// Index_Entry
SHMOBJECT;
int32_t length;
int32_t offset;
int32_t shmid;
// Glyph data stuff
uint32_t index;
string_t mempool_id; // TODO: Merge with shmid? (Internally impossible atm)
uint32_t buffer_id;
uint32_t size;
uint32_t rows;
uint32_t width;
uint32_t pitch;
uint32_t num_grays;
uint32_t pixel_mode;
uint32_t hint;
};
struct _Msg_Error {
@ -282,6 +419,7 @@ typedef struct _Msg_Font_Glyphs_Loaded Msg_Font_Glyphs_Loaded;
typedef struct _Msg_Stats Msg_Stats;
typedef struct _Msg_Font_Debug Msg_Font_Debug;
typedef struct _Msg_Error Msg_Error;
typedef struct _Msg_Index_List Msg_Index_List;
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -20,4 +20,13 @@ evas_cserve2_image_data_get(Image_Entry *ie)
return dentry->shm.data;
}
unsigned int
evas_cserve2_image_hit(Image_Entry *ie)
{
Data_Entry *dentry = ie->data2;
if (!dentry) return 0;
return ++dentry->hit_count;
}
#endif

View File

@ -2,12 +2,21 @@
#define EVAS_CS2_PRIVATE_H 1
#include "evas_common_private.h"
#include "evas_cs2.h"
struct _Data_Entry {
#define SHARED_BUFFER_PATH_MAX 64
typedef struct _Data_Entry Data_Entry;
typedef struct _Font_Entry Font_Entry;
typedef struct _Index_Table Index_Table;
typedef struct _Shared_Index Shared_Index;
typedef struct _Shared_Buffer Shared_Buffer;
struct _Data_Entry
{
unsigned int image_id;
unsigned int hit_count;
void (*preloaded_cb)(void *, Eina_Bool);
struct {
const char *path;
int mmap_offset;
int use_offset;
int mmap_size;
@ -17,8 +26,48 @@ struct _Data_Entry {
} shm;
};
typedef struct _Data_Entry Data_Entry;
typedef struct _Font_Entry Font_Entry;
struct _Shared_Index
{
char path[SHARED_BUFFER_PATH_MAX];
int generation_id;
Eina_File *f;
union
{
const Shared_Array_Header *header;
char *data;
};
union
{
const char *p; // Random access
const Index_Entry *index;
const Image_Data *idata;
const File_Data *filedata;
const Font_Data *fontdata;
const Glyph_Data *gldata;
} entries;
int count;
Eina_Hash *entries_by_hkey;
int last_entry_in_hash;
};
struct _Shared_Buffer
{
char path[SHARED_BUFFER_PATH_MAX];
Eina_File *f;
char *data;
int size;
EINA_REFCOUNT;
};
struct _Index_Table
{
int generation_id;
Shared_Buffer strings_entries;
Shared_Index strings_index;
Shared_Index files;
Shared_Index images;
Shared_Index fonts;
};
int evas_cserve2_init(void);
int evas_cserve2_shutdown(void);
@ -33,6 +82,7 @@ Eina_Bool evas_cserve2_image_preload(Image_Entry *ie, void (*preloaded_cb)(void
void evas_cserve2_dispatch(void);
void *evas_cserve2_image_data_get(Image_Entry *ie);
unsigned int evas_cserve2_image_hit(Image_Entry *ie);
Font_Entry *evas_cserve2_font_load(const char *source, const char *name, int size, int dpi, Font_Rend_Flags wanted_rend);
EAPI int evas_cserve2_font_load_wait(Font_Entry *fe);
@ -40,4 +90,5 @@ void evas_cserve2_font_free(Font_Entry *fe);
Eina_Bool evas_cserve2_font_glyph_request(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints);
Eina_Bool evas_cserve2_font_glyph_used(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints) EINA_WARN_UNUSED_RESULT;
RGBA_Font_Glyph_Out *evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints);
void evas_cserve2_font_glyph_ref(RGBA_Font_Glyph_Out *glyph, Eina_Bool incref);
#endif

View File

@ -56,6 +56,8 @@ fash_gl_free(Fash_Glyph2 *fash)
{
int i;
if (!fash) return;
for (i = 0; i < 256; i++)
if (fash->bucket[i]) _fash_gl2_free(fash, fash->bucket[i]);
free(fash);

View File

@ -1,5 +1,9 @@
#include "evas_gl_private.h"
#ifdef EVAS_CSERVE2
#include "evas_cs2_private.h"
#endif
void
evas_gl_common_image_alloc_ensure(Evas_GL_Image *im)
{
@ -16,7 +20,15 @@ evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc)
EINA_LIST_FOREACH(gc->shared->images, l, im)
{
if (im->im) evas_cache_image_unload_data(&im->im->cache_entry);
if (im->im)
{
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_unload_data(&im->im->cache_entry);
else
#endif
evas_cache_image_unload_data(&im->im->cache_entry);
}
if (im->tex)
{
if (!im->tex->pt->dyn.img)
@ -141,7 +153,12 @@ _evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_
im = calloc(1, sizeof(Evas_GL_Image));
if (!im)
{
evas_cache_image_drop(&(im_im->cache_entry));
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im_im->cache_entry))
evas_cache2_image_close(&(im_im->cache_entry));
else
#endif
evas_cache_image_drop(&(im_im->cache_entry));
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
return NULL;
}
@ -163,6 +180,26 @@ evas_gl_common_image_load(Evas_Engine_GL_Context *gc, const char *file, const ch
{
RGBA_Image *im_im;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
im_im = (RGBA_Image *) evas_cache2_image_open
(evas_common_image_cache2_get(), file, key, lo, error);
if (im_im)
{
*error = evas_cache2_image_open_wait(&im_im->cache_entry);
if ((*error != EVAS_LOAD_ERROR_NONE)
&& im_im->cache_entry.animated.animated)
{
evas_cache2_image_close(&im_im->cache_entry);
im_im = NULL;
}
else
return _evas_gl_common_image(gc, im_im, lo, error);
}
}
#endif
im_im = evas_common_load_image_from_file(file, key, lo, error);
if (!im_im) return NULL;
@ -174,6 +211,26 @@ evas_gl_common_image_mmap(Evas_Engine_GL_Context *gc, Eina_File *f, const char *
{
RGBA_Image *im_im;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get() && !eina_file_virtual(f))
{
im_im = (RGBA_Image *) evas_cache2_image_open
(evas_common_image_cache2_get(), eina_file_filename_get(f), key, lo, error);
if (im_im)
{
*error = evas_cache2_image_open_wait(&im_im->cache_entry);
if ((*error != EVAS_LOAD_ERROR_NONE)
&& im_im->cache_entry.animated.animated)
{
evas_cache2_image_close(&im_im->cache_entry);
im_im = NULL;
}
else
return _evas_gl_common_image(gc, im_im, lo, error);
}
}
#endif
im_im = evas_common_load_image_from_mmap(f, key, lo, error);
if (!im_im) return NULL;
@ -341,7 +398,12 @@ evas_gl_common_image_alpha_set(Evas_GL_Image *im, int alpha)
im->alpha = alpha;
if (!im->im) return im;
evas_gl_common_image_alloc_ensure(im);
evas_cache_image_load_data(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_load_data(&im->im->cache_entry);
else
#endif
evas_cache_image_load_data(&im->im->cache_entry);
im->im->cache_entry.flags.alpha = alpha ? 1 : 0;
if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE);
@ -376,7 +438,12 @@ evas_gl_common_image_native_enable(Evas_GL_Image *im)
}
if (im->im)
{
evas_cache_image_drop(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
im->im = NULL;
}
if (im->tex)
@ -395,7 +462,12 @@ evas_gl_common_image_native_disable(Evas_GL_Image *im)
{
if (im->im)
{
evas_cache_image_drop(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (!evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
im->im = NULL;
}
if (im->tex)
@ -451,7 +523,12 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint)
}
if (im->im)
{
evas_cache_image_drop(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
im->im = NULL;
}
if (im->tex)
@ -466,7 +543,12 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint)
{
if (im->im)
{
evas_cache_image_drop(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
im->im = NULL;
}
if (im->tex)
@ -510,7 +592,15 @@ evas_gl_common_image_free(Evas_GL_Image *im)
{
if (_evas_gl_image_cache_add(im)) return;
}
if (im->im) evas_cache_image_drop(&im->im->cache_entry);
if (im->im)
{
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
}
if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE);
free(im);
@ -549,7 +639,12 @@ evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, un
if (im->im)
{
evas_gl_common_image_alloc_ensure(im);
im->im = (RGBA_Image *)evas_cache_image_dirty(&im->im->cache_entry, x, y, w, h);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
im->im = (RGBA_Image *)evas_cache2_image_dirty(&im->im->cache_entry, x, y, w, h);
else
#endif
im->im = (RGBA_Image *)evas_cache_image_dirty(&im->im->cache_entry, x, y, w, h);
}
im->dirty = 1;
}
@ -588,16 +683,38 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
if ((im->tex) &&
((im->dirty) || (ie->animated.animated) || (ie->flags.updated_data)))
{
evas_cache_image_load_data(&im->im->cache_entry);
evas_gl_common_texture_update(im->tex, im->im);
evas_cache_image_unload_data(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
{
evas_cache2_image_load_data(&im->im->cache_entry);
evas_gl_common_texture_update(im->tex, im->im);
evas_cache2_image_unload_data(&im->im->cache_entry);
}
else
#endif
{
evas_cache_image_load_data(&im->im->cache_entry);
evas_gl_common_texture_update(im->tex, im->im);
evas_cache_image_unload_data(&im->im->cache_entry);
}
ie->flags.updated_data = 0;
}
if (!im->tex)
{
evas_cache_image_load_data(&im->im->cache_entry);
im->tex = evas_gl_common_texture_new(gc, im->im);
evas_cache_image_unload_data(&im->im->cache_entry);
#ifdef EVAS_CSERVE2
if (evas_cache2_image_cached(&im->im->cache_entry))
{
evas_cache2_image_load_data(&im->im->cache_entry);
im->tex = evas_gl_common_texture_new(gc, im->im);
evas_cache2_image_unload_data(&im->im->cache_entry);
}
else
#endif
{
evas_cache_image_load_data(&im->im->cache_entry);
im->tex = evas_gl_common_texture_new(gc, im->im);
evas_cache_image_unload_data(&im->im->cache_entry);
}
}
im->dirty = 0;
if (!im->tex) return;

View File

@ -949,10 +949,19 @@ eng_image_load(void *data EINA_UNUSED, const char *file, const char *key, int *e
ie = evas_cache2_image_open(evas_common_image_cache2_get(),
file, key, lo, error);
if (ie)
*error = evas_cache2_image_open_wait(ie);
{
*error = evas_cache2_image_open_wait(ie);
if ((*error != EVAS_LOAD_ERROR_NONE) && ie->animated.animated)
{
evas_cache2_image_close(ie);
goto use_local_cache;
}
}
return ie;
}
use_local_cache:
#endif
return evas_common_load_image_from_file(file, key, lo, error);
}
@ -962,16 +971,25 @@ eng_image_mmap(void *data EINA_UNUSED, Eina_File *f, const char *key, int *error
*error = EVAS_LOAD_ERROR_NONE;
#ifdef EVAS_CSERVE2
// FIXME: Need to pass fd to make that useful, so just get the filename for now.
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && !eina_file_virtual(f))
{
Image_Entry *ie;
ie = evas_cache2_image_open(evas_common_image_cache2_get(),
eina_file_filename_get(f), key, lo, error);
if (ie)
*error = evas_cache2_image_open_wait(ie);
{
*error = evas_cache2_image_open_wait(ie);
if ((*error != EVAS_LOAD_ERROR_NONE) && ie->animated.animated)
{
evas_cache2_image_close(ie);
goto use_local_cache;
}
}
return ie;
}
use_local_cache:
#endif
return evas_common_load_image_from_mmap(f, key, lo, error);
}
@ -1006,7 +1024,7 @@ static void
eng_image_free(void *data EINA_UNUSED, void *image)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(image))
{
evas_cache2_image_close(image);
return;
@ -1031,7 +1049,7 @@ eng_image_size_set(void *data EINA_UNUSED, void *image, int w, int h)
Image_Entry *im = image;
if (!im) return NULL;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(im))
return evas_cache2_image_size_set(im, w, h);
#endif
return evas_cache_image_size_set(im, w, h);
@ -1043,7 +1061,7 @@ eng_image_dirty_region(void *data EINA_UNUSED, void *image, int x, int y, int w,
Image_Entry *im = image;
if (!im) return NULL;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(im))
return evas_cache2_image_dirty(im, x, y, w, h);
#endif
return evas_cache_image_dirty(im, x, y, w, h);
@ -1063,7 +1081,7 @@ eng_image_data_get(void *data EINA_UNUSED, void *image, int to_write, DATA32 **i
im = image;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
{
error = evas_cache2_image_load_data(&im->cache_entry);
if (err) *err = error;
@ -1157,7 +1175,7 @@ eng_image_data_preload_request(void *data EINA_UNUSED, void *image, const Eo *ta
if (!im) return;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
{
evas_cache2_image_preload_data(&im->cache_entry, target);
return;
@ -1171,7 +1189,7 @@ eng_image_data_preload_cancel(void *data EINA_UNUSED, void *image, const Eo *tar
{
RGBA_Image *im = image;
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
return;
#endif
@ -1295,7 +1313,7 @@ eng_image_draw(void *data EINA_UNUSED, void *context, void *surface, void *image
if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
{
#if EVAS_CSERVE2
if (evas_cserve2_use_get())
if (evas_cserve2_use_get() && evas_cache2_image_cached(&im->cache_entry))
evas_cache2_image_load_data(&im->cache_entry);
else
#endif
@ -1334,52 +1352,14 @@ eng_image_draw(void *data EINA_UNUSED, void *context, void *surface, void *image
#endif
else
{
#if 0
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
evas_cache2_image_load_data(&im->cache_entry);
goto image_loaded;
}
#endif
if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
evas_cache_image_load_data(&im->cache_entry);
evas_common_image_colorspace_normalize(im);
image_loaded:
#endif
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
{
if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
evas_cache2_image_load_data(&im->cache_entry);
if (!im->cache_entry.flags.loaded) return EINA_FALSE;
evas_common_image_colorspace_normalize(im);
if (smooth)
evas_common_scale_rgba_in_to_out_clip_smooth
(im, surface, context,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h);
else
evas_common_scale_rgba_in_to_out_clip_sample
(im, surface, context,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h);
}
else
#endif
{
evas_common_rgba_image_scalecache_prepare
(&im->cache_entry, surface, context, smooth,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h);
evas_common_rgba_image_scalecache_do
(&im->cache_entry, surface, context, smooth,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h);
}
evas_common_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();
}