evas/cserve2: Store Glyph_Data in shared mempools

- Create one Glyph_Data array per Font_Entry
- Copy Font_Source descriptors in shared array
- Copy font entries in shared index
- Send font index path over socket
- Merge Font_Source and Font_Data in shared memory
- Send font index path on client connect
- Repack font index after free
- Pass font shm name to clients
This commit is contained in:
Jean-Philippe Andre 2013-08-19 12:22:19 +09:00
parent c7515f3300
commit 467b1b1739
7 changed files with 597 additions and 325 deletions

View File

@ -62,6 +62,8 @@ extern Eina_Prefix *_evas_cserve2_pfx;
typedef struct _Slave Slave; typedef struct _Slave Slave;
typedef struct _Slave_Thread_Data Slave_Thread_Data; typedef struct _Slave_Thread_Data Slave_Thread_Data;
typedef struct _Shm_Handle Shm_Handle; typedef struct _Shm_Handle Shm_Handle;
typedef struct _Shared_Array Shared_Array;
typedef struct _Shared_Mempool Shared_Mempool;
typedef enum { typedef enum {
FD_READ = 1, FD_READ = 1,
@ -172,14 +174,13 @@ struct _Slave_Msg_Font_Glyphs_Load {
unsigned int *glyphs; unsigned int *glyphs;
} glyphs; } glyphs;
struct { struct {
Shm_Handle *shm; Shared_Mempool *mempool;
unsigned int usage;
unsigned int nglyphs;
} cache; } cache;
}; };
struct _Slave_Msg_Glyph { struct _Slave_Msg_Glyph {
unsigned int index; unsigned int index;
unsigned int buffer_id;
unsigned int offset; unsigned int offset;
unsigned int size; unsigned int size;
unsigned int rows; unsigned int rows;
@ -191,21 +192,13 @@ struct _Slave_Msg_Glyph {
typedef struct _Slave_Msg_Glyph 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 { struct _Slave_Msg_Font_Glyphs_Loaded {
unsigned int ncaches; Shared_Mempool *mempool;
unsigned int gl_load_time; unsigned int gl_load_time;
unsigned int gl_render_time; unsigned int gl_render_time;
unsigned int gl_slave_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; typedef struct _Slave_Msg_Font_Load Slave_Msg_Font_Load;
@ -349,8 +342,6 @@ void cserve2_font_ft_free(void *fontinfo);
void cserve2_shared_index_init(void); void cserve2_shared_index_init(void);
void cserve2_shared_index_shutdown(void); void cserve2_shared_index_shutdown(void);
typedef struct _Shared_Array Shared_Array;
typedef struct _Shared_Mempool Shared_Mempool;
typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *sa, typedef Eina_Bool (* Shared_Array_Repack_Skip_Cb) (Shared_Array *sa,
const void *elem, const void *elem,
void *user_data); void *user_data);
@ -382,7 +373,9 @@ int cserve2_shared_mempool_buffer_new(Shared_Mempool *sm, int size);
int cserve2_shared_mempool_buffer_ref(Shared_Mempool *sm, int bufferid); 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_del(Shared_Mempool *sm, int bufferid);
void *cserve2_shared_mempool_buffer_get(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);
// Shared strings // Shared strings
const char *cserve2_shared_strings_table_name_get(); const char *cserve2_shared_strings_table_name_get();

View File

@ -26,7 +26,6 @@ typedef struct _File_Watch File_Watch;
typedef struct _Font_Source Font_Source; typedef struct _Font_Source Font_Source;
typedef struct _Font_Entry Font_Entry; typedef struct _Font_Entry Font_Entry;
typedef struct _Font_Cache Font_Cache;
typedef enum { typedef enum {
CSERVE2_IMAGE_FILE, CSERVE2_IMAGE_FILE,
@ -62,22 +61,23 @@ struct _Font_Source {
string_t key; string_t key;
string_t name; string_t name;
string_t file; string_t file;
int references; int refcount;
void *ft; void *ft; // Font_Source_Info
}; };
struct _Font_Entry { struct _Font_Entry {
Entry base; ENTRY;
unsigned int rend_flags; unsigned int rend_flags;
unsigned int size; unsigned int size;
unsigned int dpi; unsigned int dpi;
unsigned int font_data_id;
Font_Source *src; Font_Source *src;
void *ft; void *ft; // Font_Info
Fash_Glyph2 *glyphs; Fash_Glyph2 *glyph_entries; // Fast access to the Glyph_Entry objects
Shared_Array *glyph_datas; // Contains the Glyph_Data objects
unsigned int nglyphs; unsigned int nglyphs;
Eina_List *caches;
Font_Cache *last_cache;
Eina_Bool unused : 1; Eina_Bool unused : 1;
Shared_Mempool *mempool; // Contains the rendered glyphs
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
struct timeval rstart; // start of the glyphs load request struct timeval rstart; // start of the glyphs load request
struct timeval rfinish; // finish of the glyphs load request struct timeval rfinish; // finish of the glyphs load request
@ -89,19 +89,9 @@ struct _Font_Entry {
#endif #endif
}; };
struct _Font_Cache {
Font_Entry *fe;
Shm_Handle *shm;
unsigned int usage;
int inuse;
Shared_Array *glyphs; // Contains gldata_id only
unsigned int nglyphs;
};
struct _Glyph_Entry { struct _Glyph_Entry {
unsigned int gldata_id; unsigned int gldata_id;
Font_Entry *fe; Font_Entry *fe;
Font_Cache *fc;
}; };
struct _Glyphs_Request { struct _Glyphs_Request {
@ -119,13 +109,6 @@ struct _Glyphs_Request {
typedef struct _Glyphs_Request Glyphs_Request; typedef struct _Glyphs_Request Glyphs_Request;
struct _Glyphs_Group {
Font_Cache *fc;
Eina_List *glyphs;
};
typedef struct _Glyphs_Group Glyphs_Group;
struct _Reference { struct _Reference {
Client *client; Client *client;
Entry *entry; Entry *entry;
@ -140,12 +123,15 @@ struct _File_Watch {
static unsigned int _entry_id = 0; static unsigned int _entry_id = 0;
static unsigned int _glyph_id = 0; static unsigned int _glyph_id = 0;
static unsigned int _font_data_id = 0;
static unsigned int _freed_file_entry_count = 0; static unsigned int _freed_file_entry_count = 0;
static unsigned int _freed_image_entry_count = 0; static unsigned int _freed_image_entry_count = 0;
static unsigned int _freed_font_entry_count = 0;
static Eina_Bool _shutdown = EINA_FALSE;
static Shared_Array *_file_data_array = NULL; static Shared_Array *_file_data_array = NULL;
static Shared_Array *_image_data_array = NULL; static Shared_Array *_image_data_array = NULL;
static Shared_Array *_glyph_data_array = NULL; static Shared_Array *_font_data_array = NULL;
static Eina_Hash *file_ids = NULL; // maps path + key --> file_id static Eina_Hash *file_ids = NULL; // maps path + key --> file_id
static Eina_Hash *file_entries = NULL; // maps file_id --> entry static Eina_Hash *file_entries = NULL; // maps file_id --> entry
@ -296,12 +282,28 @@ _image_entry_find(unsigned int entry_id)
return (Image_Entry *) e; return (Image_Entry *) e;
} }
static Font_Data *
_font_data_find(unsigned int fs_id)
{
Font_Data *fdata;
fdata = cserve2_shared_array_item_data_find(_font_data_array,
&fs_id, _shm_object_id_cmp_cb);
if (!fdata)
{
ERR("Could not find font data %u", fs_id);
return NULL;
}
return fdata;
}
static Glyph_Data * static Glyph_Data *
_glyph_data_find(unsigned int glyph_id) _glyph_data_find(Shared_Array *sa, unsigned int glyph_id)
{ {
Glyph_Data *gldata; Glyph_Data *gldata;
gldata = cserve2_shared_array_item_data_find(_glyph_data_array, &glyph_id, gldata = cserve2_shared_array_item_data_find(sa, &glyph_id,
_shm_object_id_cmp_cb); _shm_object_id_cmp_cb);
if (!gldata) if (!gldata)
{ {
@ -327,6 +329,9 @@ _repack()
int count; int count;
Eina_Bool updated = EINA_FALSE; Eina_Bool updated = EINA_FALSE;
if (_shutdown)
return;
// Repack when we have 10% fragmentation over the whole shm buffer // Repack when we have 10% fragmentation over the whole shm buffer
count = cserve2_shared_array_size_get(_file_data_array); count = cserve2_shared_array_size_get(_file_data_array);
@ -341,7 +346,7 @@ _repack()
_shm_object_id_cmp_cb, NULL); _shm_object_id_cmp_cb, NULL);
if (!sa) if (!sa)
{ {
ERR("Failed to repack array. Keeping previous references!"); ERR("Failed to repack files array. Keeping previous references!");
goto skip_files; goto skip_files;
} }
@ -364,7 +369,7 @@ skip_files:
_shm_object_id_cmp_cb, NULL); _shm_object_id_cmp_cb, NULL);
if (!sa) if (!sa)
{ {
ERR("Failed to repack array. Keeping previous references!"); ERR("Failed to repack images array. Keeping previous references!");
goto skip_images; goto skip_images;
} }
@ -375,12 +380,35 @@ skip_files:
} }
skip_images: skip_images:
count = cserve2_shared_array_size_get(_font_data_array);
if ((count > 0) && (_freed_font_entry_count > 100 ||
((_freed_font_entry_count * 100) / count >= 10)))
{
DBG("Repacking font data array: %s",
cserve2_shared_array_name_get(_font_data_array));
sa = cserve2_shared_array_repack(_font_data_array,
_repack_skip_cb,
_shm_object_id_cmp_cb, NULL);
if (!sa)
{
ERR("Failed to repack fonts array. Keeping previous references!");
goto skip_fonts;
}
cserve2_shared_array_del(_font_data_array);
_freed_font_entry_count = 0;
_font_data_array = sa;
updated = EINA_TRUE;
}
skip_fonts:
if (updated) if (updated)
cserve2_index_list_send(cserve2_shared_strings_index_name_get(), cserve2_index_list_send(cserve2_shared_strings_index_name_get(),
cserve2_shared_strings_table_name_get(), cserve2_shared_strings_table_name_get(),
cserve2_shared_array_name_get(_file_data_array), cserve2_shared_array_name_get(_file_data_array),
cserve2_shared_array_name_get(_image_data_array), cserve2_shared_array_name_get(_image_data_array),
NULL, cserve2_shared_array_name_get(_font_data_array),
NULL); NULL);
} }
@ -1055,15 +1083,32 @@ _font_entry_key_hash(const Font_Entry *key, int key_length EINA_UNUSED)
static void static void
_font_entry_free(Font_Entry *fe) _font_entry_free(Font_Entry *fe)
{ {
fash_gl_free(fe->glyphs); Font_Data *fd;
fe->src->references--;
if (fe->ft) cserve2_font_ft_free(fe->ft); if (!fe) return;
if (fe->src->references <= 0)
fd = _font_data_find(fe->font_data_id);
if (fd)
{
fd->refcount = 0;
cserve2_shared_string_del(fd->glyph_index_shm);
cserve2_shared_string_del(fd->file);
cserve2_shared_string_del(fd->name);
}
fash_gl_free(fe->glyph_entries);
cserve2_shared_array_del(fe->glyph_datas);
cserve2_font_ft_free(fe->ft);
fe->src->refcount--;
if (fe->src->refcount <= 0)
{ {
const char *key = cserve2_shared_string_get(fe->src->key); const char *key = cserve2_shared_string_get(fe->src->key);
eina_hash_del_by_key(font_sources, key); eina_hash_del_by_key(font_sources, key);
} }
free(fe); free(fe);
_freed_font_entry_count++;
_repack();
} }
static void static void
@ -1072,24 +1117,31 @@ _glyph_free_cb(void *data)
Glyph_Entry *gl = data; Glyph_Entry *gl = data;
Glyph_Data *gldata; Glyph_Data *gldata;
if (!gl) return; if (!gl || !gl->fe) return;
gldata = _glyph_data_find(gl->gldata_id);
cserve2_shared_string_del(gldata->shm_id); gldata = _glyph_data_find(gl->fe->glyph_datas, gl->gldata_id);
gldata->refcount--; if (gldata)
{
cserve2_shared_string_del(gldata->shm_id);
gldata->refcount--;
}
free(gl); free(gl);
} }
static void static void
_font_source_free(Font_Source *fs) _font_source_free(Font_Source *fs)
{ {
if (!fs) return;
cserve2_shared_string_del(fs->key); cserve2_shared_string_del(fs->key);
cserve2_shared_string_del(fs->name); cserve2_shared_string_del(fs->name);
cserve2_shared_string_del(fs->file); cserve2_shared_string_del(fs->file);
if (fs->ft) cserve2_font_source_ft_free(fs->ft); cserve2_font_source_ft_free(fs->ft);
free(fs); free(fs);
} }
#if 0
static void static void
_font_shm_promote(Font_Cache *fc) _font_shm_promote(Font_Cache *fc)
{ {
@ -1161,6 +1213,7 @@ _font_shm_lru_flush(void)
l_next = eina_list_next(l); l_next = eina_list_next(l);
} }
} }
#endif
void void
cserve2_cache_init(void) cserve2_cache_init(void)
@ -1180,16 +1233,13 @@ cserve2_cache_init(void)
_file_data_array = cserve2_shared_array_new(1, sizeof(File_Data), 0); _file_data_array = cserve2_shared_array_new(1, sizeof(File_Data), 0);
_image_data_array = cserve2_shared_array_new(1, sizeof(Image_Data), 0); _image_data_array = cserve2_shared_array_new(1, sizeof(Image_Data), 0);
_glyph_data_array = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0); _font_data_array = cserve2_shared_array_new(1, sizeof(Font_Data), 0);
} }
void void
cserve2_cache_shutdown(void) cserve2_cache_shutdown(void)
{ {
Font_Cache *fc; _shutdown = EINA_TRUE;
EINA_LIST_FREE(font_shm_lru, fc)
_font_shm_free(fc);
eina_hash_free(image_entries); eina_hash_free(image_entries);
eina_hash_free(image_ids); eina_hash_free(image_ids);
@ -1202,7 +1252,7 @@ cserve2_cache_shutdown(void)
cserve2_shared_array_del(_file_data_array); cserve2_shared_array_del(_file_data_array);
cserve2_shared_array_del(_image_data_array); cserve2_shared_array_del(_image_data_array);
cserve2_shared_array_del(_glyph_data_array); cserve2_shared_array_del(_font_data_array);
} }
static Reference * static Reference *
@ -1304,7 +1354,7 @@ _entry_reference_del(Entry *entry, Reference *ref)
{ {
Font_Entry *fe = (Font_Entry *)entry; Font_Entry *fe = (Font_Entry *)entry;
fe->unused = EINA_TRUE; fe->unused = EINA_TRUE;
if (!fe->caches) if (!fe->mempool)
eina_hash_del_by_key(font_entries, fe); eina_hash_del_by_key(font_entries, fe);
} }
else else
@ -1372,7 +1422,7 @@ cserve2_cache_client_new(Client *client)
cserve2_shared_strings_table_name_get(), cserve2_shared_strings_table_name_get(),
cserve2_shared_array_name_get(_file_data_array), cserve2_shared_array_name_get(_file_data_array),
cserve2_shared_array_name_get(_image_data_array), cserve2_shared_array_name_get(_image_data_array),
NULL, cserve2_shared_array_name_get(_font_data_array),
client); client);
} }
@ -1647,7 +1697,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
for (i = req->current; i < req->nglyphs; i++) for (i = req->current; i < req->nglyphs; i++)
{ {
Glyph_Entry *ge; Glyph_Entry *ge;
ge = fash_gl_find(fe->glyphs, req->glyphs[i]); ge = fash_gl_find(fe->glyph_entries, req->glyphs[i]);
if (ge) if (ge)
{ {
req->answer[req->nanswer++] = ge; req->answer[req->nanswer++] = ge;
@ -1657,7 +1707,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
fe->gl_saved_time += fe->gl_saved_time +=
(fe->gl_load_time / fe->nglyphs); (fe->gl_load_time / fe->nglyphs);
#endif #endif
ge->fc->inuse++; //ge->fc->inuse++;
} }
else else
break; break;
@ -1669,6 +1719,7 @@ _glyphs_request_check(Glyphs_Request *req, Eina_Bool report_load)
return (req->nanswer == req->nglyphs); return (req->nanswer == req->nglyphs);
} }
#if 0
/* organize answer (cache1{gl1, gl2,}, cache2{gl3,gl4,gl5}, cache3{gl6}) /* organize answer (cache1{gl1, gl2,}, cache2{gl3,gl4,gl5}, cache3{gl6})
*/ */
static Eina_List * static Eina_List *
@ -1676,7 +1727,17 @@ _glyphs_group_create(Glyphs_Request *req)
{ {
Eina_List *groups = NULL; Eina_List *groups = NULL;
unsigned int i; unsigned int i;
Glyphs_Group *gg;
gg = calloc(1, sizeof(*gg));
groups = eina_list_append(groups, gg);
for (i = 0; i < req->nanswer; i++)
gg->glyphs = eina_list_append(gg->glyphs, req->answer[i]);
return groups;
/*
for (i = 0; i < req->nanswer; i++) for (i = 0; i < req->nanswer; i++)
{ {
Eina_List *l; Eina_List *l;
@ -1702,6 +1763,7 @@ _glyphs_group_create(Glyphs_Request *req)
} }
return groups; return groups;
*/
} }
static Msg_Font_Glyphs_Loaded * static Msg_Font_Glyphs_Loaded *
@ -1799,6 +1861,76 @@ _glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
return (Msg_Font_Glyphs_Loaded *)resp; return (Msg_Font_Glyphs_Loaded *)resp;
} }
#endif
static Msg_Font_Glyphs_Loaded *
_glyphs_loaded_msg_create(Glyphs_Request *req, int *resp_size)
{
Msg_Font_Glyphs_Loaded *msg;
unsigned int size;
const char *shmname;
unsigned int shmname_size;
unsigned int k;
char *response, *buf;
shmname = cserve2_shared_mempool_name_get(req->fe->mempool);
shmname_size = strlen(shmname) + 1;
size = sizeof(Msg_Font_Glyphs_Loaded);
size += sizeof(int) * 2;
size += shmname_size;
size += req->nanswer * 9 * sizeof(int);
response = malloc(size);
if (!response) return NULL;
msg = (Msg_Font_Glyphs_Loaded *) response;
buf = response + sizeof(Msg_Font_Glyphs_Loaded);
msg->base.type = CSERVE2_FONT_GLYPHS_LOADED;
memcpy(buf, &shmname_size, sizeof(int));
buf += sizeof(int);
memcpy(buf, shmname, shmname_size);
buf += shmname_size;
memcpy(buf, &req->nanswer, sizeof(int));
buf += sizeof(int);
for (k = 0; k < req->nanswer; k++)
{
Glyph_Entry *ge;
Glyph_Data *gldata;
ge = req->answer[k];
gldata = _glyph_data_find(ge->fe->glyph_datas, ge->gldata_id);
if (!gldata)
{
ERR("Glyph data not found for %d", ge->gldata_id);
continue;
}
memcpy(buf, &gldata->index, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->shm_id, sizeof(string_t));
buf += sizeof(string_t);
memcpy(buf, &gldata->offset, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->size, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->rows, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->width, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pitch, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->num_grays, sizeof(int));
buf += sizeof(int);
memcpy(buf, &gldata->pixel_mode, sizeof(int));
buf += sizeof(int);
}
*resp_size = size;
return msg;
}
static void static void
_glyphs_loaded_send(Glyphs_Request *req, unsigned int rid) _glyphs_loaded_send(Glyphs_Request *req, unsigned int rid)
@ -1846,7 +1978,10 @@ _file_path_join(const char *path, const char *end)
} }
static Glyphs_Request * static Glyphs_Request *
_glyphs_request_create(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs) _glyphs_request_create(Client *client, const char *source, const char *name,
unsigned int hint, unsigned int rend_flags,
unsigned int size, unsigned int dpi,
unsigned int *glyphs, unsigned int nglyphs)
{ {
char *fullname; char *fullname;
Glyphs_Request *req = calloc(1, sizeof(*req)); Glyphs_Request *req = calloc(1, sizeof(*req));
@ -1909,7 +2044,7 @@ _glyphs_load_request_prepare(Glyphs_Request *req)
for (i = req->current; i < req->nglyphs; i++) for (i = req->current; i < req->nglyphs; i++)
{ {
Glyph_Entry *ge; Glyph_Entry *ge;
ge = fash_gl_find(fe->glyphs, req->glyphs[i]); ge = fash_gl_find(fe->glyph_entries, req->glyphs[i]);
if (ge) if (ge)
{ {
req->answer[req->nanswer++] = ge; req->answer[req->nanswer++] = ge;
@ -1919,7 +2054,7 @@ _glyphs_load_request_prepare(Glyphs_Request *req)
fe->gl_saved_time += fe->gl_saved_time +=
(fe->gl_load_time / fe->nglyphs); (fe->gl_load_time / fe->nglyphs);
#endif #endif
ge->fc->inuse++; //ge->fc->inuse++;
} }
else else
req->render[req->nrender++] = req->glyphs[i]; req->render[req->nrender++] = req->glyphs[i];
@ -1932,7 +2067,6 @@ _glyphs_load_request_build(void *data, int *size EINA_UNUSED)
Glyphs_Request *req = data; Glyphs_Request *req = data;
Slave_Msg_Font_Glyphs_Load *msg = NULL; Slave_Msg_Font_Glyphs_Load *msg = NULL;
Font_Entry *fe = req->fe; Font_Entry *fe = req->fe;
Font_Cache *fc;
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
gettimeofday(&fe->rstart, NULL); gettimeofday(&fe->rstart, NULL);
@ -1947,15 +2081,7 @@ _glyphs_load_request_build(void *data, int *size EINA_UNUSED)
msg->font.rend_flags = fe->rend_flags; msg->font.rend_flags = fe->rend_flags;
msg->glyphs.nglyphs = req->nrender; msg->glyphs.nglyphs = req->nrender;
msg->glyphs.glyphs = req->render; msg->glyphs.glyphs = req->render;
msg->cache.mempool = fe->mempool;
// Trying to reuse last filled cache.
fc = fe->last_cache;
if (fc)
{
msg->cache.shm = fc->shm;
msg->cache.usage = fc->usage;
msg->cache.nglyphs = fc->nglyphs;
}
return msg; return msg;
} }
@ -1972,81 +2098,67 @@ _glyphs_load_request_response(Glyphs_Request *req,
Slave_Msg_Font_Glyphs_Loaded *msg, int *size) Slave_Msg_Font_Glyphs_Loaded *msg, int *size)
{ {
Font_Entry *fe = req->fe; Font_Entry *fe = req->fe;
Font_Cache *fc = NULL; Shared_Mempool *mempool = msg->mempool;
unsigned int i; unsigned int j;
string_t shm_id = 0;
if (fe->last_cache && fe->last_cache->shm == msg->caches[0]->shm) if (!msg->nglyphs)
fc = fe->last_cache; return _glyphs_loaded_msg_create(req, size);
for (i = 0; i < msg->ncaches; i++) if (!mempool)
mempool = cserve2_shared_mempool_new(0);
if (!fe->glyph_datas)
fe->glyph_datas = cserve2_shared_array_new(1, sizeof(Glyph_Data), 0);
shm_id = cserve2_shared_string_add(cserve2_shared_mempool_name_get(mempool));
for (j = 0; j < msg->nglyphs; j++)
{ {
unsigned int j; Glyph_Entry *gl;
Slave_Msg_Font_Cache *c = msg->caches[i];
string_t shm_id;
if (!fc) gl = fash_gl_find(fe->glyph_entries, msg->glyphs[j].index);
if (!gl)
{ {
fc = calloc(1, sizeof(*fc)); int glyph_id;
fe->caches = eina_list_append(fe->caches, fc); Glyph_Data *gldata;
fe->last_cache = fc;
fc->fe = fe;
fc->shm = c->shm;
fc->glyphs = cserve2_shared_array_new(1, sizeof(int), 0);
fc->nglyphs = 0;
fc->inuse = 0;
font_shm_lru = eina_list_append(font_shm_lru, fc);
font_mem_usage += _font_shm_size_get(fc);
}
fc->usage = c->usage;
shm_id = cserve2_shared_string_add(cserve2_shm_name_get(fc->shm));
for (j = 0; j < c->nglyphs; j++)
{
Glyph_Entry *gl;
gl = fash_gl_find(fe->glyphs, c->glyphs[j].index); glyph_id = cserve2_shared_array_item_new(fe->glyph_datas);
if (!gl) gldata = cserve2_shared_array_item_data_get(fe->glyph_datas,
glyph_id);
if (!gldata)
{ {
int glyph_id, idx, *gldata_id; ERR("Could not create new Glyph_Data!");
Glyph_Data *gldata; // TODO: Return error?
continue;
gl = calloc(1, sizeof(*gl));
gl->fe = fe;
gl->fc = fc;
gl->gldata_id = ++_glyph_id;
glyph_id = cserve2_shared_array_item_new(_glyph_data_array);
gldata = cserve2_shared_array_item_data_get(_glyph_data_array,
glyph_id);
gldata->refcount = 1;
gldata->id = gl->gldata_id;
gldata->index = c->glyphs[j].index;
gldata->shm_id = cserve2_shared_string_ref(shm_id);
gldata->offset = c->glyphs[j].offset;
gldata->size = c->glyphs[j].size;
gldata->rows = c->glyphs[j].rows;
gldata->width = c->glyphs[j].width;
gldata->pitch = c->glyphs[j].pitch;
gldata->num_grays = c->glyphs[j].num_grays;
gldata->pixel_mode = c->glyphs[j].pixel_mode;
font_mem_usage += sizeof(*gl) + sizeof(*gldata);
idx = cserve2_shared_array_item_new(fc->glyphs);
gldata_id = cserve2_shared_array_item_data_get(fc->glyphs, idx);
*gldata_id = gldata->id;
fc->nglyphs++;
fe->nglyphs++;
fash_gl_add(fe->glyphs, gldata->index, gl);
} }
req->answer[req->nanswer++] = gl;
gl->fc->inuse++;
}
cserve2_shared_string_del(shm_id); gl = calloc(1, sizeof(*gl));
free(c); // FIXME: We are freeing this here because we only do a gl->fe = fe;
// simple free on the response message. Later we need to gl->gldata_id = ++_glyph_id;
// setup a free callback for the slave response.
fc = NULL; gldata->refcount = 1;
gldata->id = gl->gldata_id;
gldata->index = msg->glyphs[j].index;
gldata->shm_id = cserve2_shared_string_ref(shm_id);
gldata->buffer_id = msg->glyphs[j].buffer_id;
gldata->offset = msg->glyphs[j].offset; // TODO: Remove?
gldata->size = msg->glyphs[j].size;
gldata->rows = msg->glyphs[j].rows;
gldata->width = msg->glyphs[j].width;
gldata->pitch = msg->glyphs[j].pitch;
gldata->num_grays = msg->glyphs[j].num_grays;
gldata->pixel_mode = msg->glyphs[j].pixel_mode;
fe->nglyphs++;
fash_gl_add(fe->glyph_entries, gldata->index, gl);
font_mem_usage += sizeof(*gl) + sizeof(*gldata);
}
req->answer[req->nanswer++] = gl;
} }
cserve2_shared_string_del(shm_id);
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
gettimeofday(&fe->rfinish, NULL); gettimeofday(&fe->rfinish, NULL);
fe->gl_request_time += _timeval_sub(&fe->rfinish, &fe->rstart); fe->gl_request_time += _timeval_sub(&fe->rfinish, &fe->rstart);
@ -2055,7 +2167,7 @@ _glyphs_load_request_response(Glyphs_Request *req,
fe->gl_slave_time += msg->gl_slave_time; fe->gl_slave_time += msg->gl_slave_time;
#endif #endif
_font_shm_lru_flush(); fe->mempool = mempool;
return _glyphs_loaded_msg_create(req, size); return _glyphs_loaded_msg_create(req, size);
} }
@ -2075,6 +2187,9 @@ static Slave_Request_Funcs _glyphs_load_funcs = {
static Eina_Bool static Eina_Bool
_font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata) _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
{ {
// FIXME TODO Must reimplement this
#if 0
Font_Entry *fe = data; Font_Entry *fe = data;
Msg_Stats *msg = fdata; Msg_Stats *msg = fdata;
Eina_List *iter; Eina_List *iter;
@ -2117,6 +2232,8 @@ _font_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
msg->fonts.glyphs_saved_time += fe->gl_saved_time; msg->fonts.glyphs_saved_time += fe->gl_saved_time;
msg->fonts.glyphs_request_time += fe->gl_request_time; msg->fonts.glyphs_request_time += fe->gl_request_time;
msg->fonts.glyphs_slave_time += fe->gl_slave_time; msg->fonts.glyphs_slave_time += fe->gl_slave_time;
#endif
#endif #endif
return EINA_TRUE; return EINA_TRUE;
@ -2207,8 +2324,6 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
struct _debug_info *di = fdata; struct _debug_info *di = fdata;
unsigned int size = di->size; unsigned int size = di->size;
Font_Entry *fe = data; Font_Entry *fe = data;
Font_Cache *fc;
Eina_List *iter;
const char *str; const char *str;
// filelen // filelen
@ -2240,20 +2355,7 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
// ncaches // ncaches
size += sizeof(int); size += sizeof(int);
EINA_LIST_FOREACH(fe->caches, iter, fc) size += cserve2_shared_mempool_size_get(fe->mempool);
{
// shmnamelen + shmname
size += sizeof(int);
size += strlen(cserve2_shm_name_get(fc->shm)) + 1;
// size + usage
size += 2 * sizeof(int);
// nglyphs
size += sizeof(int);
size += (4 + 3 + 2) * sizeof(int) * fc->nglyphs;
}
di->size = size; di->size = size;
di->nfonts++; di->nfonts++;
@ -2264,6 +2366,94 @@ _font_entry_debug_size_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EIN
static Eina_Bool static Eina_Bool
_font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata) _font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
{ {
char **pos = fdata;
char *buf = *pos;
Font_Entry *fe = data;
unsigned int len, k, nglyphs;
const char *str;
char *nglyphs_pos;
// file
str = cserve2_shared_string_get(fe->src->file);
len = str ? (strlen(str) + 1) : 0;
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
if (len)
{
memcpy(buf, str, len);
buf += len;
}
// name
str = cserve2_shared_string_get(fe->src->name);
len = str ? (strlen(str) + 1) : 0;
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
if (len)
{
memcpy(buf, str, len);
buf += len;
}
// rend_flags, size, dpi, unused
memcpy(buf, &fe->rend_flags, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fe->size, sizeof(int));
buf += sizeof(int);
memcpy(buf, &fe->dpi, sizeof(int));
buf += sizeof(int);
len = fe->unused;
memcpy(buf, &len, sizeof(int));
buf += sizeof(int);
// glyph shared index and mempool
if (fe->glyph_datas)
eina_strlcpy(buf, cserve2_shared_array_name_get(fe->glyph_datas), 64);
else
memset(buf, 0, 64);
buf += 64;
if (fe->mempool)
eina_strlcpy(buf, cserve2_shared_mempool_name_get(fe->mempool), 64);
else
memset(buf, 0, 64);
buf += 64;
// skip nglyphs for now...
nglyphs_pos = buf;
buf += sizeof(int);
nglyphs = 0;
for (k = 0; k < fe->nglyphs; k++)
{
Glyph_Data *gd = cserve2_shared_array_item_data_get(fe->glyph_datas, k);
if (!gd || !gd->id) break;
nglyphs++;
memcpy(buf, gd, sizeof(*gd));
buf += sizeof(*gd);
}
// write real value of nglyphs
memcpy(nglyphs_pos, &nglyphs, sizeof(int));
if (nglyphs != fe->nglyphs)
{
WRN("Found %u valid glyphs when the font advertised %u entries",
nglyphs, fe->nglyphs);
}
*pos = buf;
return EINA_TRUE;
}
// FIXME TODO Must reimplement this
#if 0
char **pos = fdata; char **pos = fdata;
char *buf = *pos; char *buf = *pos;
Font_Entry *fe = data; Font_Entry *fe = data;
@ -2376,6 +2566,7 @@ _font_entry_debug_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNU
*pos = buf; *pos = buf;
return EINA_TRUE; return EINA_TRUE;
#endif
} }
static void * static void *
@ -2852,12 +3043,16 @@ cserve2_cache_image_unload(Client *client, unsigned int client_image_id)
} }
int int
cserve2_cache_font_load(Client *client, const char *source, const char *name, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int rid) cserve2_cache_font_load(Client *client, const char *source, const char *name,
unsigned int rend_flags, unsigned int size,
unsigned int dpi, unsigned int rid)
{ {
Reference *ref; Reference *ref;
Font_Source *fs; Font_Source *fs;
Font_Data *fd;
Font_Entry *fe; Font_Entry *fe;
char *fullname; char *fullname;
int fd_index;
if (source && !*source) if (source && !*source)
source = NULL; source = NULL;
@ -2891,10 +3086,9 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name, un
fe->size = size; fe->size = size;
fe->dpi = dpi; fe->dpi = dpi;
fe->base.type = CSERVE2_FONT_ENTRY; fe->base.type = CSERVE2_FONT_ENTRY;
fe->glyphs = fash_gl_new(_glyph_free_cb); fe->glyph_entries = fash_gl_new(_glyph_free_cb);
ref = _entry_reference_add((Entry *)fe, client, 0); ref = _entry_reference_add((Entry *)fe, client, 0);
client->fonts.referencing = eina_list_append( client->fonts.referencing = eina_list_append(client->fonts.referencing, ref);
client->fonts.referencing, ref);
fe->unused = EINA_FALSE; fe->unused = EINA_FALSE;
fs = _cserve2_font_source_find(fullname); fs = _cserve2_font_source_find(fullname);
@ -2912,14 +3106,28 @@ cserve2_cache_font_load(Client *client, const char *source, const char *name, un
else else
{ {
fs->file = cserve2_shared_string_add(name); fs->file = cserve2_shared_string_add(name);
fs->name = 0;
fs->key = cserve2_shared_string_ref(fs->file); fs->key = cserve2_shared_string_ref(fs->file);
key = name; key = name;
} }
eina_hash_direct_add(font_sources, key, fs); eina_hash_add(font_sources, key, fs);
} }
// Copy descriptor to Shared Array
fd_index = cserve2_shared_array_item_new(_font_data_array);
fd = cserve2_shared_array_item_data_get(_font_data_array, fd_index);
fd->size = fe->size;
fd->rend_flags = fe->rend_flags;
fd->dpi = fe->dpi;
fd->id = ++_font_data_id;
fd->refcount = 1;
fd->name = cserve2_shared_string_ref(fs->name);
fd->file = cserve2_shared_string_ref(fs->file);
fd->glyph_index_shm = 0;
fe->src = fs; fe->src = fs;
fs->references++; fe->font_data_id = fd->id;
fs->refcount++;
DBG("adding FONT_LOAD '%s' request.", name); DBG("adding FONT_LOAD '%s' request.", name);
fe->base.request = cserve2_request_add(CSERVE2_REQ_FONT_LOAD, rid, client, fe->base.request = cserve2_request_add(CSERVE2_REQ_FONT_LOAD, rid, client,
NULL, &_font_load_funcs, fe); NULL, &_font_load_funcs, fe);
@ -2958,7 +3166,11 @@ cserve2_cache_font_unload(Client *client, const char *source, const char *name,
} }
int int
cserve2_cache_font_glyphs_load(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs, unsigned int rid) cserve2_cache_font_glyphs_load(Client *client, const char *source,
const char *name, unsigned int hint,
unsigned int rend_flags, unsigned int size,
unsigned int dpi, unsigned int *glyphs,
unsigned int nglyphs, unsigned int rid)
{ {
Glyphs_Request *req; Glyphs_Request *req;
@ -2985,8 +3197,17 @@ cserve2_cache_font_glyphs_load(Client *client, const char *source, const char *n
} }
int int
cserve2_cache_font_glyphs_used(Client *client, const char *source, const char *name, unsigned int hint, unsigned int rend_flags, unsigned int size, unsigned int dpi, unsigned int *glyphs, unsigned int nglyphs, unsigned int rid EINA_UNUSED) cserve2_cache_font_glyphs_used(Client *client, const char *source,
const char *name, unsigned int hint,
unsigned int rend_flags, unsigned int size,
unsigned int dpi, unsigned int *glyphs,
unsigned int nglyphs,
unsigned int rid EINA_UNUSED)
{ {
// FIXME TODO: Must reimplement this
return 0;
#if 0
Glyphs_Group *gg; Glyphs_Group *gg;
Eina_List *groups; Eina_List *groups;
Glyphs_Request *req; Glyphs_Request *req;
@ -3008,13 +3229,14 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source, const char *n
// glyphs which are not cached anymore, but are in use on the client. // glyphs which are not cached anymore, but are in use on the client.
EINA_LIST_FREE(groups, gg) EINA_LIST_FREE(groups, gg)
{ {
_font_shm_promote(gg->fc); //_font_shm_promote(gg->fc);
eina_list_free(gg->glyphs); eina_list_free(gg->glyphs);
free(gg); free(gg);
} }
_glyphs_request_free(req); _glyphs_request_free(req);
return 0; return 0;
#endif
} }
void void

View File

@ -47,7 +47,6 @@ struct _Font_Info
int dpi; int dpi;
int max_h; int max_h;
unsigned int runtime_rend; unsigned int runtime_rend;
int shmsize;
}; };
struct _Font_Source_Info struct _Font_Source_Info
@ -281,14 +280,6 @@ _font_slave_load(const void *cmddata, void *data EINA_UNUSED)
return response; 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. /* 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, * In order to use or render it, one should access it from the glyph slot,
* or get the glyph using FT_Get_Glyph(). * or get the glyph using FT_Get_Glyph().
@ -326,39 +317,48 @@ _font_slave_glyph_load(Font_Info *fi, unsigned int idx, unsigned int hint)
* given Font Cache. * given Font Cache.
*/ */
static Eina_Bool 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; Font_Source_Info *fsi = fi->fsi;
unsigned int glyphsize; unsigned int glyphsize;
char *cachedata = cserve2_shm_map(c->shm);
FT_Glyph glyph; FT_Glyph glyph;
FT_BitmapGlyph bglyph; FT_BitmapGlyph bglyph;
char *data;
int buffer_id = 0;
FT_Get_Glyph(fsi->face->glyph, &glyph); FT_Get_Glyph(fsi->face->glyph, &glyph);
FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1); FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
bglyph = (FT_BitmapGlyph)glyph; bglyph = (FT_BitmapGlyph)glyph;
glyphsize = bglyph->bitmap.pitch * bglyph->bitmap.rows; glyphsize = bglyph->bitmap.pitch * bglyph->bitmap.rows;
if (!glyphsize)
if (c->usage + glyphsize > cserve2_shm_size_get(c->shm))
{ {
FT_Done_Glyph(glyph); FT_Done_Glyph(glyph);
return EINA_FALSE; return EINA_FALSE;
} }
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);
return EINA_FALSE;
}
memcpy(data, bglyph->bitmap.buffer, glyphsize);
// TODO: Check if we have problems with alignment // TODO: Check if we have problems with alignment
c->glyphs[c->nglyphs].index = idx; response->glyphs[response->nglyphs].index = idx;
c->glyphs[c->nglyphs].offset = c->usage; response->glyphs[response->nglyphs].buffer_id = buffer_id;
c->glyphs[c->nglyphs].size = glyphsize; response->glyphs[response->nglyphs].offset =
c->glyphs[c->nglyphs].rows = bglyph->bitmap.rows; cserve2_shared_mempool_buffer_offset_get(response->mempool, buffer_id);
c->glyphs[c->nglyphs].width = bglyph->bitmap.width; response->glyphs[response->nglyphs].size = glyphsize;
c->glyphs[c->nglyphs].pitch = bglyph->bitmap.pitch; response->glyphs[response->nglyphs].rows = bglyph->bitmap.rows;
c->glyphs[c->nglyphs].num_grays = bglyph->bitmap.num_grays; response->glyphs[response->nglyphs].width = bglyph->bitmap.width;
c->glyphs[c->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode; response->glyphs[response->nglyphs].pitch = bglyph->bitmap.pitch;
c->usage += glyphsize; response->glyphs[response->nglyphs].num_grays = bglyph->bitmap.num_grays;
c->nglyphs++; response->glyphs[response->nglyphs].pixel_mode = bglyph->bitmap.pixel_mode;
response->nglyphs++;
FT_Done_Glyph(glyph); FT_Done_Glyph(glyph);
@ -465,15 +465,12 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
Slave_Msg_Font_Glyphs_Loaded *response; Slave_Msg_Font_Glyphs_Loaded *response;
Font_Info *fi; Font_Info *fi;
unsigned int i; unsigned int i;
unsigned int total_glyphs = 0;
#ifdef DEBUG_LOAD_TIME #ifdef DEBUG_LOAD_TIME
unsigned int gl_load_time = 0; unsigned int gl_load_time = 0;
unsigned int gl_render_time = 0; unsigned int gl_render_time = 0;
struct timeval tv_start, tv_end; struct timeval tv_start, tv_end;
struct timeval rstart, rfinish; struct timeval rstart, rfinish;
#endif #endif
Eina_List *caches = NULL;
Slave_Msg_Font_Cache *c = NULL;
fi = msg->font.ftdata2; fi = msg->font.ftdata2;
@ -483,41 +480,22 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
_font_slave_size_use(fi); _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) * unsigned shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
(msg->glyphs.nglyphs)); response->mempool = cserve2_shared_mempool_new(shmsize);
c->nglyphs = 0; if (!response->mempool) return NULL;
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;
} }
if (!fi->shmsize) for (i = 0; i < msg->glyphs.nglyphs; i++)
fi->shmsize = _font_slave_int_shm_calculate(fi, msg->font.hint);
i = 0;
while (i < msg->glyphs.nglyphs)
{ {
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 #ifdef DEBUG_LOAD_TIME
gettimeofday(&tv_start, NULL); gettimeofday(&tv_start, NULL);
#endif #endif
@ -530,32 +508,14 @@ _font_slave_glyphs_load(const void *cmddata, void *data EINA_UNUSED)
tv_start.tv_sec = tv_end.tv_sec; tv_start.tv_sec = tv_end.tv_sec;
tv_start.tv_usec = tv_end.tv_usec; tv_start.tv_usec = tv_end.tv_usec;
#endif #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 #ifdef DEBUG_LOAD_TIME
gettimeofday(&tv_end, NULL); gettimeofday(&tv_end, NULL);
gl_render_time += _timeval_sub(&tv_end, &tv_start); gl_render_time += _timeval_sub(&tv_end, &tv_start);
#endif #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 #ifdef DEBUG_LOAD_TIME
response->gl_load_time = gl_load_time; response->gl_load_time = gl_load_time;
response->gl_render_time = gl_render_time; response->gl_render_time = gl_render_time;
@ -630,6 +590,8 @@ cserve2_font_source_ft_free(void *fontsource)
{ {
Font_Source_Info *fsi = fontsource; Font_Source_Info *fsi = fontsource;
if (!fsi) return;
FT_Done_Face(fsi->face); FT_Done_Face(fsi->face);
free(fsi->data); free(fsi->data);
free(fsi); free(fsi);
@ -640,6 +602,8 @@ cserve2_font_ft_free(void *fontinfo)
{ {
Font_Info *fi = fontinfo; Font_Info *fi = fontinfo;
if (!fi) return;
FT_Done_Size(fi->size); FT_Done_Size(fi->size);
free(fi); free(fi);
} }

View File

@ -837,6 +837,20 @@ cserve2_shared_mempool_buffer_offset_get(Shared_Mempool *sm, int bufferid)
return ie->offset; return ie->offset;
} }
size_t
cserve2_shared_mempool_size_get(Shared_Mempool *sm)
{
if (!sm) return 0;
return cserve2_shm_map_size_get(sm->ds->shm);
}
const char *
cserve2_shared_mempool_name_get(Shared_Mempool *sm)
{
if (!sm) return NULL;
return cserve2_shm_name_get(sm->ds->shm);
}
// Shared strings // Shared strings

View File

@ -47,6 +47,9 @@ cserve2_index_list_send(const char *strings_index_path,
Msg_Index_List msg; Msg_Index_List msg;
const int size = sizeof(msg); const int size = sizeof(msg);
if (!client_list)
return;
INF("New shared index: strings: '%s':'%s' files: '%s' images: '%s', fonts: '%s'", INF("New shared index: strings: '%s':'%s' files: '%s' images: '%s', fonts: '%s'",
strings_index_path, strings_entries_path, strings_index_path, strings_entries_path,
files_index_path, images_index_path, fonts_index_path); files_index_path, images_index_path, fonts_index_path);
@ -339,6 +342,7 @@ static void
_clients_finish(void) _clients_finish(void)
{ {
eina_hash_free(client_list); eina_hash_free(client_list);
client_list = NULL;
} }
int int

View File

@ -184,7 +184,6 @@ struct _Msg_Font_Glyphs_Request {
*/ */
struct _Msg_Font_Glyphs_Loaded { struct _Msg_Font_Glyphs_Loaded {
Msg_Base base; Msg_Base base;
unsigned int ncaches;
}; };
struct _Msg_Stats { struct _Msg_Stats {
@ -287,6 +286,7 @@ typedef struct _Shm_Object Shm_Object;
typedef struct _Index_Entry Index_Entry; typedef struct _Index_Entry Index_Entry;
typedef struct _File_Data File_Data; typedef struct _File_Data File_Data;
typedef struct _Image_Data Image_Data; typedef struct _Image_Data Image_Data;
typedef struct _Font_Data Font_Data;
typedef struct _Glyph_Data Glyph_Data; typedef struct _Glyph_Data Glyph_Data;
typedef struct _Shared_Array_Header Shared_Array_Header; typedef struct _Shared_Array_Header Shared_Array_Header;
typedef int string_t; typedef int string_t;
@ -338,10 +338,21 @@ struct _Image_Data {
Eina_Bool doload : 1; Eina_Bool doload : 1;
}; };
struct _Font_Data {
SHMOBJECT;
string_t name;
string_t file;
string_t glyph_index_shm;
uint32_t rend_flags;
uint32_t size;
uint32_t dpi;
};
struct _Glyph_Data { struct _Glyph_Data {
SHMOBJECT; SHMOBJECT;
uint32_t index; uint32_t index;
string_t shm_id; string_t shm_id;
uint32_t buffer_id;
uint32_t offset; uint32_t offset;
uint32_t size; uint32_t size;
uint32_t rows; uint32_t rows;

View File

@ -1085,6 +1085,9 @@ struct _Font_Entry
unsigned int dpi; unsigned int dpi;
Font_Rend_Flags wanted_rend; Font_Rend_Flags wanted_rend;
char *hkey;
int font_data_id;
unsigned int rid; // open unsigned int rid; // open
Eina_Hash *glyphs_maps; Eina_Hash *glyphs_maps;
@ -1305,8 +1308,12 @@ _glyph_request_cb(void *data, const void *msg, int size)
const Msg_Font_Glyphs_Loaded *resp = msg; const Msg_Font_Glyphs_Loaded *resp = msg;
Glyph_Request_Data *grd = data; Glyph_Request_Data *grd = data;
Font_Entry *fe = grd->fe; Font_Entry *fe = grd->fe;
unsigned int ncaches;
const char *buf; const char *buf;
int i, nglyphs;
int namelen;
const char *name;
Glyph_Map *map;
int pos;
if (resp->base.type == CSERVE2_ERROR) if (resp->base.type == CSERVE2_ERROR)
goto end; goto end;
@ -1317,89 +1324,82 @@ _glyph_request_cb(void *data, const void *msg, int size)
if (size <= (int) sizeof(*resp)) goto end; if (size <= (int) sizeof(*resp)) goto end;
buf = (const char *)resp + sizeof(*resp); buf = (const char *)resp + sizeof(*resp);
for (ncaches = 0; ncaches < resp->ncaches; ncaches++) pos = buf - (const char*) resp;
pos += sizeof(int);
if (pos > size) goto end;
memcpy(&namelen, buf, sizeof(int));
buf += sizeof(int);
pos += namelen + sizeof(int);
if (pos > size) goto end;
name = eina_stringshare_add_length(buf, namelen);
buf += namelen;
memcpy(&nglyphs, buf, sizeof(int));
buf += sizeof(int);
map = eina_hash_find(fe->glyphs_maps, name);
if (!map)
{ {
int i, nglyphs; map = calloc(1, sizeof(*map));
int namelen; map->fe = fe;
const char *name; map->name = name;
Glyph_Map *map; map->map = eina_file_open(name, EINA_TRUE);
int pos = buf - (const char*) resp; map->data = eina_file_map_all(map->map, EINA_FILE_WILLNEED);
eina_clist_init(&map->glyphs);
eina_hash_direct_add(fe->glyphs_maps, &map->name, map);
}
else
eina_stringshare_del(name);
pos += sizeof(int); for (i = 0; i < nglyphs; i++)
{
string_t shm_id;
unsigned int idx, offset, glsize;
int rows, width, pitch, num_grays, pixel_mode;
CS_Glyph_Out *gl;
pos = buf - (const char*) resp;
pos += 8 * sizeof(int);
if (pos > size) goto end; if (pos > size) goto end;
memcpy(&namelen, buf, sizeof(int)); memcpy(&idx, buf, sizeof(int));
buf += sizeof(int);
memcpy(&shm_id, buf, sizeof(string_t));
buf += sizeof(string_t);
memcpy(&offset, buf, sizeof(int));
buf += sizeof(int);
memcpy(&glsize, buf, sizeof(int));
buf += sizeof(int);
memcpy(&rows, buf, sizeof(int));
buf += sizeof(int);
memcpy(&width, buf, sizeof(int));
buf += sizeof(int);
memcpy(&pitch, buf, sizeof(int));
buf += sizeof(int);
memcpy(&num_grays, buf, sizeof(int));
buf += sizeof(int);
memcpy(&pixel_mode, buf, sizeof(int));
buf += sizeof(int); buf += sizeof(int);
pos += namelen + sizeof(int); gl = fash_gl_find(fe->fash[grd->hints], idx);
if (pos > size) goto end; if (gl)
name = eina_stringshare_add_length(buf, namelen);
buf += namelen;
memcpy(&nglyphs, buf, sizeof(int));
buf += sizeof(int);
map = eina_hash_find(fe->glyphs_maps, name);
if (!map)
{ {
map = calloc(1, sizeof(*map)); gl->map = map;
map->fe = fe; gl->offset = offset;
map->name = name; gl->size = glsize;
map->map = eina_file_open(name, EINA_TRUE); gl->base.bitmap.rows = rows;
map->data = eina_file_map_all(map->map, EINA_FILE_WILLNEED); gl->base.bitmap.width = width;
eina_clist_init(&map->glyphs); gl->base.bitmap.pitch = pitch;
eina_hash_direct_add(fe->glyphs_maps, &map->name, map); gl->base.bitmap.buffer = map->data + gl->offset;
} gl->base.bitmap.num_grays = num_grays;
else gl->base.bitmap.pixel_mode = pixel_mode;
eina_stringshare_del(name); gl->rid = 0;
for (i = 0; i < nglyphs; i++) eina_clist_add_head(&map->glyphs, &gl->map_entry);
{
string_t shm_id;
unsigned int idx, offset, glsize;
int rows, width, pitch, num_grays, pixel_mode;
CS_Glyph_Out *gl;
pos = buf - (const char*) resp;
pos += 8 * sizeof(int);
if (pos > size) goto end;
memcpy(&idx, buf, sizeof(int));
buf += sizeof(int);
memcpy(&shm_id, buf, sizeof(string_t));
buf += sizeof(string_t);
memcpy(&offset, buf, sizeof(int));
buf += sizeof(int);
memcpy(&glsize, buf, sizeof(int));
buf += sizeof(int);
memcpy(&rows, buf, sizeof(int));
buf += sizeof(int);
memcpy(&width, buf, sizeof(int));
buf += sizeof(int);
memcpy(&pitch, buf, sizeof(int));
buf += sizeof(int);
memcpy(&num_grays, buf, sizeof(int));
buf += sizeof(int);
memcpy(&pixel_mode, buf, sizeof(int));
buf += sizeof(int);
gl = fash_gl_find(fe->fash[grd->hints], idx);
if (gl)
{
gl->map = map;
gl->offset = offset;
gl->size = glsize;
gl->base.bitmap.rows = rows;
gl->base.bitmap.width = width;
gl->base.bitmap.pitch = pitch;
gl->base.bitmap.buffer = map->data + gl->offset;
gl->base.bitmap.num_grays = num_grays;
gl->base.bitmap.pixel_mode = pixel_mode;
gl->rid = 0;
eina_clist_add_head(&map->glyphs, &gl->map_entry);
}
} }
} }
@ -1858,7 +1858,8 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
file = _shared_string_get(fd->path); file = _shared_string_get(fd->path);
if (!file) if (!file)
{ {
ERR("Could not find filename for file %d", fd->id); ERR("Could not find filename for file %d: path id: %d",
fd->id, fd->path);
add_to_hash = EINA_FALSE; add_to_hash = EINA_FALSE;
continue; continue;
} }
@ -2191,5 +2192,68 @@ found:
return idata; return idata;
} }
static const Font_Data *
_shared_font_entry_data_get_by_id(int id)
{
return (Font_Data *)
_shared_index_item_get_by_id(&_index.fonts, sizeof(Font_Data), id);
}
static const Font_Data *
_shared_font_entry_data_find(Font_Entry *fe)
{
const Font_Data *fd = NULL;
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
char hkey[PATH_MAX];
int k;
if (!_index.strings_entries.data || !_index.strings_index.data)
return NULL;
if (!fe || !fe->hkey)
return NULL;
if (fe->font_data_id)
{
fd = _shared_font_entry_data_get_by_id(fe->font_data_id);
if (fd) return fd;
fe->font_data_id = 0;
}
// Find in hash
fd = eina_hash_find(_index.fonts.entries_by_hkey, fe->hkey);
if (fd) return fd;
// Find in shared index
for (k = _index.fonts.last_entry_in_hash;
k < _index.fonts.count && k < _index.fonts.header->emptyidx; k++)
{
const Font_Data *cur;
const char *name, *source;
cur = &(_index.fonts.entries.fontdata[k]);
if (!cur->id) return NULL;
if (!cur->refcount) continue;
name = _shared_string_get(cur->name);
source = _shared_string_get(cur->file);
snprintf(hkey, PATH_MAX, "%s:%s/%u:%u:%u", source, name,
cur->size, cur->dpi, cur->rend_flags);
if (add_to_hash)
{
eina_hash_add(_index.fonts.entries_by_hkey, hkey, cur);
_index.fonts.last_entry_in_hash++;
}
if (!strcmp(hkey, fe->hkey))
{
fe->font_data_id = cur->id;
return cur;
}
}
return fd;
}
#endif #endif