summaryrefslogtreecommitdiff
path: root/src/lib/evas/cserve2
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2013-10-07 15:59:13 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2013-10-28 15:47:16 +0900
commit6b6e33e262387380af4507e94a123a352ac6ee1c (patch)
treeca5239ef78104d012135dc977135a2a54dd14de5 /src/lib/evas/cserve2
parente74cac57e412bcd71f2cc58ba46d326aef0996c4 (diff)
evas/cserve2: Fix refcount for glyphs & glyph buffers
Maybe a little overkill on the iterations (ref/unref), but at least we can really track down which glyphs are currently being used.
Diffstat (limited to 'src/lib/evas/cserve2')
-rw-r--r--src/lib/evas/cserve2/evas_cs2_client.c198
-rw-r--r--src/lib/evas/cserve2/evas_cs2_private.h2
2 files changed, 145 insertions, 55 deletions
diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c
index a1ca4d3135..64e335afdf 100644
--- a/src/lib/evas/cserve2/evas_cs2_client.c
+++ b/src/lib/evas/cserve2/evas_cs2_client.c
@@ -262,6 +262,7 @@ _request_resend(unsigned int rid)
262 Client_Request *cr; 262 Client_Request *cr;
263 Eina_Bool found = EINA_FALSE; 263 Eina_Bool found = EINA_FALSE;
264 264
265 DBG("Re-sending %d requests...", eina_list_count(_requests));
265 EINA_LIST_FOREACH(_requests, l, cr) 266 EINA_LIST_FOREACH(_requests, l, cr)
266 { 267 {
267 if (rid) 268 if (rid)
@@ -337,9 +338,13 @@ _server_reconnect()
337 if (!_server_dispatch_until(SPECIAL_RID_INDEX_LIST)) 338 if (!_server_dispatch_until(SPECIAL_RID_INDEX_LIST))
338 goto on_error; 339 goto on_error;
339 340
340#warning TODO: Reopen all files, images, fonts... 341 /* NOTE: (TODO?)
342 * Either we reopen all images & fonts now
343 * Or we wait until new data is required again to request cserve2 to load
344 * it for us. Not sure which approch is the best now.
345 * So, for the moment, we'll just wait until the client needs new data.
346 */
341 347
342 DBG("Re-sending %d requests...", eina_list_count(_requests));
343 if (!_request_resend(0)) 348 if (!_request_resend(0))
344 goto on_error; 349 goto on_error;
345 350
@@ -768,7 +773,7 @@ _image_loaded_cb(void *data, const void *msg_received, int size)
768 773
769 if (msg_error->error == CSERVE2_NOT_LOADED) 774 if (msg_error->error == CSERVE2_NOT_LOADED)
770 { 775 {
771#warning Code path to check 776#warning Code path to check: cserve2 restart
772 DBG("Trying to reopen the image"); 777 DBG("Trying to reopen the image");
773 ie->open_rid = _image_open_server_send(ie); 778 ie->open_rid = _image_open_server_send(ie);
774 if (_server_dispatch_until(ie->open_rid)) 779 if (_server_dispatch_until(ie->open_rid))
@@ -1399,6 +1404,7 @@ struct _Glyph_Map
1399 Shared_Index index; 1404 Shared_Index index;
1400 Shared_Buffer mempool; 1405 Shared_Buffer mempool;
1401 Eina_Clist glyphs; 1406 Eina_Clist glyphs;
1407 Eina_List *mempool_lru;
1402}; 1408};
1403 1409
1404struct _CS_Glyph_Out 1410struct _CS_Glyph_Out
@@ -1409,15 +1415,27 @@ struct _CS_Glyph_Out
1409 unsigned int idx; 1415 unsigned int idx;
1410 unsigned int rid; 1416 unsigned int rid;
1411 Glyph_Map *map; 1417 Glyph_Map *map;
1418 Shared_Buffer *sb;
1412 unsigned int offset; 1419 unsigned int offset;
1413 unsigned int size; 1420 unsigned int size;
1414 Eina_Bool used; 1421 Eina_Bool used;
1422 int refcount;
1423 int pending_ref;
1415}; 1424};
1416 1425
1417static void 1426static void
1418_glyphs_map_free(Glyph_Map *map) 1427_glyphs_map_free(Glyph_Map *map)
1419{ 1428{
1429 Shared_Buffer *mempool;
1430
1420 if (!map) return; 1431 if (!map) return;
1432
1433 EINA_LIST_FREE(map->mempool_lru, mempool)
1434 {
1435 eina_file_map_free(mempool->f, mempool->data);
1436 eina_file_close(mempool->f);
1437 free(mempool);
1438 }
1421 eina_file_map_free(map->mempool.f, map->mempool.data); 1439 eina_file_map_free(map->mempool.f, map->mempool.data);
1422 eina_file_close(map->mempool.f); 1440 eina_file_close(map->mempool.f);
1423 eina_file_map_free(map->index.f, map->index.data); 1441 eina_file_map_free(map->index.f, map->index.data);
@@ -1643,48 +1661,52 @@ _glyph_map_remap_check(Glyph_Map *map)
1643{ 1661{
1644 Eina_Bool changed = EINA_FALSE; 1662 Eina_Bool changed = EINA_FALSE;
1645 int oldcount; 1663 int oldcount;
1646 const void *oldmap = map->mempool.data;
1647
1648 if (!map->mempool.f)
1649 {
1650 WRN("The glyph mempool has been closed.");
1651 if (!map->mempool.path)
1652 return EINA_FALSE;
1653
1654 DBG("Remapping from %s", map->mempool.path);
1655 map->mempool.f = eina_file_open(map->mempool.path, EINA_TRUE);
1656 if (!map->mempool.f)
1657 {
1658 ERR("Could not open shm file: %d %m", errno);
1659 return EINA_FALSE;
1660 }
1661 map->mempool.size = 0;
1662 }
1663 1664
1664 if (eina_file_refresh(map->mempool.f) 1665 if (eina_file_refresh(map->mempool.f)
1665 || (eina_file_size_get(map->mempool.f) != (size_t) map->mempool.size)) 1666 || (eina_file_size_get(map->mempool.f) != (size_t) map->mempool.size))
1666 { 1667 {
1667 CS_Glyph_Out *gl; 1668 CS_Glyph_Out *gl;
1669 Shared_Buffer *oldbuf = NULL;
1668 1670
1669 WRN("Glyph pool has been resized."); 1671 WRN("Glyph pool has been resized.");
1670 eina_file_map_free(map->mempool.f, map->mempool.data); 1672
1671 map->mempool.data = eina_file_map_all(map->mempool.f, EINA_FILE_RANDOM); 1673 // Queue old mempool into mempool_lru unless refcount == 0
1672 if (map->mempool.data) 1674 // We want to keep the old glyph bitmap data in memory because of
1673 map->mempool.size = eina_file_size_get(map->mempool.f); 1675 // asynchronous rendering and also because remap could happen
1676 // after some glyphs have been requested but not all for the current
1677 // draw.
1678
1679 if (map->mempool.refcount > 0)
1680 {
1681 oldbuf = calloc(1, sizeof(Glyph_Map));
1682 oldbuf->f = eina_file_dup(map->mempool.f);
1683 oldbuf->data = map->mempool.data;
1684 oldbuf->size = map->mempool.size;
1685 oldbuf->refcount = map->mempool.refcount;
1686 eina_strlcpy(oldbuf->path, map->mempool.path, SHARED_BUFFER_PATH_MAX);
1687 map->mempool_lru = eina_list_append(map->mempool_lru, oldbuf);
1688 }
1674 else 1689 else
1675 map->mempool.size = 0; 1690 {
1691 eina_file_map_free(map->mempool.f, map->mempool.data);
1692 }
1693 map->mempool.data = eina_file_map_all(map->mempool.f, EINA_FILE_RANDOM);
1694 map->mempool.size = eina_file_size_get(map->mempool.f);
1695 map->mempool.refcount = 0;
1676 changed = EINA_TRUE; 1696 changed = EINA_TRUE;
1677 1697
1678 // Remap loaded glyphs 1698 // Remap unused but loaded glyphs
1679#warning Infinite loop again here. FONT RELOAD IS STILL BROKEN.
1680 EINA_CLIST_FOR_EACH_ENTRY(gl, &map->fe->map->glyphs, 1699 EINA_CLIST_FOR_EACH_ENTRY(gl, &map->fe->map->glyphs,
1681 CS_Glyph_Out, map_entry) 1700 CS_Glyph_Out, map_entry)
1682 { 1701 {
1683 if (map->mempool.data) 1702 if (!gl->refcount)
1684 gl->base.bitmap.buffer = (unsigned char *) 1703 {
1685 map->mempool.data + gl->offset; 1704 gl->sb = &map->mempool;
1686 else 1705 gl->base.bitmap.buffer = (unsigned char *) gl->sb->data + gl->offset;
1687 gl->base.bitmap.buffer = NULL; 1706 }
1707 else if (oldbuf)
1708 gl->sb = oldbuf;
1709 else CRIT("Invalid refcount state");
1688 } 1710 }
1689 } 1711 }
1690 1712
@@ -1692,7 +1714,6 @@ _glyph_map_remap_check(Glyph_Map *map)
1692 oldcount = map->index.count; 1714 oldcount = map->index.count;
1693 _shared_index_remap_check(&map->index, sizeof(Glyph_Data)); 1715 _shared_index_remap_check(&map->index, sizeof(Glyph_Data));
1694 changed |= (oldcount != map->index.count); 1716 changed |= (oldcount != map->index.count);
1695 changed |= (oldmap != map->mempool.data);
1696 1717
1697 return changed; 1718 return changed;
1698} 1719}
@@ -1744,6 +1765,7 @@ _font_entry_glyph_map_rebuild_check(Font_Entry *fe, Font_Hint_Flags hints)
1744 eina_clist_element_init(&gl->map_entry); 1765 eina_clist_element_init(&gl->map_entry);
1745 } 1766 }
1746 gl->map = fe->map; 1767 gl->map = fe->map;
1768 gl->sb = &fe->map->mempool;
1747 gl->offset = gd->offset; 1769 gl->offset = gd->offset;
1748 gl->size = gd->size; 1770 gl->size = gd->size;
1749 gl->base.bitmap.rows = gd->rows; 1771 gl->base.bitmap.rows = gd->rows;
@@ -1790,20 +1812,9 @@ _glyph_request_cb(void *data, const void *msg, int size)
1790 1812
1791 if (err->error == CSERVE2_NOT_LOADED) 1813 if (err->error == CSERVE2_NOT_LOADED)
1792 { 1814 {
1815 // This can happen in case cserve2 restarted.
1793 DBG("Reloading the font: %s from %s", fe->name, fe->source); 1816 DBG("Reloading the font: %s from %s", fe->name, fe->source);
1794 1817
1795 // This will crash for sure.
1796 /*
1797 for (i = 0; i < 3; i++)
1798 {
1799 if (fe->fash[i])
1800 fash_gl_free(fe->fash[i]);
1801 fe->fash[i] = NULL;
1802 }
1803 _glyphs_map_free(fe->map);
1804 fe->map = NULL;
1805 */
1806
1807 if (!(fe->rid = _font_load_server_send(fe, CSERVE2_FONT_LOAD))) 1818 if (!(fe->rid = _font_load_server_send(fe, CSERVE2_FONT_LOAD)))
1808 { 1819 {
1809 ERR("Failed to send font load message"); 1820 ERR("Failed to send font load message");
@@ -1811,7 +1822,7 @@ _glyph_request_cb(void *data, const void *msg, int size)
1811 return EINA_TRUE; 1822 return EINA_TRUE;
1812 } 1823 }
1813 1824
1814#warning Code path to check 1825#warning Code path to check: cserve2 restart
1815 1826
1816 if (fe->glyphs_queue_count) 1827 if (fe->glyphs_queue_count)
1817 _glyph_request_server_send(fe, grd->hints, EINA_FALSE); 1828 _glyph_request_server_send(fe, grd->hints, EINA_FALSE);
@@ -1910,13 +1921,14 @@ _glyph_request_cb(void *data, const void *msg, int size)
1910 if (gl) 1921 if (gl)
1911 { 1922 {
1912 gl->map = fe->map; 1923 gl->map = fe->map;
1924 gl->sb = &fe->map->mempool;
1913 gl->offset = offset; 1925 gl->offset = offset;
1914 gl->size = glsize; 1926 gl->size = glsize;
1915 gl->base.bitmap.rows = rows; 1927 gl->base.bitmap.rows = rows;
1916 gl->base.bitmap.width = width; 1928 gl->base.bitmap.width = width;
1917 gl->base.bitmap.pitch = pitch; 1929 gl->base.bitmap.pitch = pitch;
1918 gl->base.bitmap.buffer = (unsigned char *) 1930 gl->base.bitmap.buffer =
1919 fe->map->mempool.data + gl->offset; 1931 (unsigned char *) gl->map->mempool.data + gl->offset;
1920 gl->base.bitmap.num_grays = num_grays; 1932 gl->base.bitmap.num_grays = num_grays;
1921 gl->base.bitmap.pixel_mode = pixel_mode; 1933 gl->base.bitmap.pixel_mode = pixel_mode;
1922 gl->rid = 0; 1934 gl->rid = 0;
@@ -1926,7 +1938,13 @@ _glyph_request_cb(void *data, const void *msg, int size)
1926 WRN("Glyph offset out of the buffer. Refreshing map."); 1938 WRN("Glyph offset out of the buffer. Refreshing map.");
1927 if (!_glyph_map_remap_check(fe->map)) 1939 if (!_glyph_map_remap_check(fe->map))
1928 { 1940 {
1929 ERR("Failed to remap glyph mempool!"); 1941 // This is very problematic. Evas expects the glyph to
1942 // be valid after this point.
1943 // We could set rows & width to 0 to avoid crashes but
1944 // then display might be b0rken.
1945 // Also, all the previous glyphs might be out of the
1946 // memory range now, so we're in a pretty bad situation.
1947 CRIT("Failed to remap glyph mempool!");
1930 gl->base.bitmap.buffer = NULL; 1948 gl->base.bitmap.buffer = NULL;
1931 //gl->base.bitmap.rows = 0; 1949 //gl->base.bitmap.rows = 0;
1932 //gl->base.bitmap.width = 0; 1950 //gl->base.bitmap.width = 0;
@@ -2067,16 +2085,15 @@ evas_cserve2_font_glyph_request(Font_Entry *fe, unsigned int idx, Font_Hint_Flag
2067 if (!glyph) 2085 if (!glyph)
2068 { 2086 {
2069 glyph = calloc(1, sizeof(*glyph)); 2087 glyph = calloc(1, sizeof(*glyph));
2070
2071 glyph->idx = idx; 2088 glyph->idx = idx;
2072
2073 fash_gl_add(fash, idx, glyph); 2089 fash_gl_add(fash, idx, glyph);
2074
2075 eina_clist_add_head(&fe->glyphs_queue, &glyph->map_entry); 2090 eina_clist_add_head(&fe->glyphs_queue, &glyph->map_entry);
2076 fe->glyphs_queue_count++; 2091 fe->glyphs_queue_count++;
2077 } 2092 }
2078 else if (!glyph->used) 2093 else if (!glyph->used)
2079 { 2094 {
2095 // FIXME: This code path seems unused (not logical)
2096 CRIT("Is this code path even valid?");
2080 eina_clist_add_head(&fe->glyphs_used, &glyph->used_list); 2097 eina_clist_add_head(&fe->glyphs_used, &glyph->used_list);
2081 fe->glyphs_used_count++; 2098 fe->glyphs_used_count++;
2082 glyph->used = EINA_TRUE; 2099 glyph->used = EINA_TRUE;
@@ -2114,6 +2131,7 @@ evas_cserve2_font_glyph_used(Font_Entry *fe, unsigned int idx, Font_Hint_Flags h
2114 if (!glyph) 2131 if (!glyph)
2115 return EINA_FALSE; 2132 return EINA_FALSE;
2116 2133
2134 // Glyph was requested but the bitmap data was not loaded yet.
2117 if (!glyph->map) 2135 if (!glyph->map)
2118 return EINA_TRUE; 2136 return EINA_TRUE;
2119 2137
@@ -2162,7 +2180,8 @@ evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx,
2162 } 2180 }
2163 2181
2164#if USE_SHARED_INDEX 2182#if USE_SHARED_INDEX
2165 _font_entry_glyph_map_rebuild_check(fe, hints); 2183#warning TODO MUST REIMPLEMENT THIS FUNCTION
2184 //_font_entry_glyph_map_rebuild_check(fe, hints);
2166#endif 2185#endif
2167 2186
2168 if (out->rid) 2187 if (out->rid)
@@ -2174,10 +2193,79 @@ evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx,
2174 } 2193 }
2175 2194
2176 // promote shm and font entry in lru or something 2195 // promote shm and font entry in lru or something
2177
2178 return &(out->base); 2196 return &(out->base);
2179} 2197}
2180 2198
2199void
2200evas_cserve2_font_glyph_ref(RGBA_Font_Glyph_Out *glyph, Eina_Bool incref)
2201{
2202 CS_Glyph_Out *glout;
2203
2204 EINA_SAFETY_ON_FALSE_RETURN(evas_cserve2_use_get());
2205
2206 // For debugging only.
2207 static int inc = 0, dec = 0;
2208 if (incref) inc++; else dec++;
2209
2210 // glout = (CS_Glyph_Out *) glyph;
2211 glout = (CS_Glyph_Out *) (((char *) glyph) - offsetof(CS_Glyph_Out, base));
2212
2213 if (incref)
2214 {
2215 if (!glout->sb)
2216 {
2217 // This can happen when cserve2 restarted.
2218 glout->pending_ref++;
2219 return;
2220 }
2221 else if (!glout->refcount)
2222 glout->sb->refcount++;
2223 if (glout->pending_ref)
2224 {
2225 glout->refcount += glout->pending_ref;
2226 glout->pending_ref = 0;
2227 }
2228 glout->refcount++;
2229 return;
2230 }
2231
2232 EINA_SAFETY_ON_FALSE_RETURN(glout->refcount > 0);
2233 EINA_SAFETY_ON_NULL_RETURN(glout->sb);
2234 if (glout->pending_ref)
2235 {
2236 glout->refcount += glout->pending_ref;
2237 glout->pending_ref = 0;
2238 glout->sb->refcount++;
2239 }
2240
2241 glout->refcount--;
2242 if (!glout->refcount)
2243 {
2244 EINA_SAFETY_ON_FALSE_RETURN(glout->sb->refcount > 0);
2245 glout->sb->refcount--;
2246
2247 if (!glout->sb->refcount)
2248 DBG("Shared buffer %p reached refcount ZERO. %d/%d", glout->sb, dec, inc);
2249
2250 //if (glout->sb->data != glout->map->mempool.data)
2251 if (glout->sb != &glout->map->mempool)
2252 {
2253 if (!glout->sb->refcount)
2254 {
2255 DBG("Glyph shared buffer reached refcount 0. Unmapping.");
2256 glout->map->mempool_lru =
2257 eina_list_remove(glout->map->mempool_lru, glout->sb);
2258 eina_file_map_free(glout->sb->f, glout->sb->data);
2259 eina_file_close(glout->sb->f);
2260 free(glout->sb);
2261 }
2262 glout->sb = &glout->map->mempool;
2263 glout->base.bitmap.buffer =
2264 (unsigned char *) glout->sb->data + glout->offset;
2265 }
2266 }
2267}
2268
2181 2269
2182 2270
2183// Fast access to shared index tables 2271// Fast access to shared index tables
@@ -2720,7 +2808,7 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
2720 const File_Data *fdata = _shared_image_entry_file_data_find(ie); 2808 const File_Data *fdata = _shared_image_entry_file_data_find(ie);
2721 if (!fdata) 2809 if (!fdata)
2722 { 2810 {
2723 ERR("File is not opened by cserve2"); 2811 DBG("File is not opened by cserve2");
2724 return NULL; 2812 return NULL;
2725 } 2813 }
2726 file_id = fdata->id; 2814 file_id = fdata->id;
diff --git a/src/lib/evas/cserve2/evas_cs2_private.h b/src/lib/evas/cserve2/evas_cs2_private.h
index 39cc829ca9..253c7e303c 100644
--- a/src/lib/evas/cserve2/evas_cs2_private.h
+++ b/src/lib/evas/cserve2/evas_cs2_private.h
@@ -56,6 +56,7 @@ struct _Shared_Buffer
56 Eina_File *f; 56 Eina_File *f;
57 char *data; 57 char *data;
58 int size; 58 int size;
59 int refcount;
59}; 60};
60 61
61struct _Index_Table 62struct _Index_Table
@@ -89,4 +90,5 @@ void evas_cserve2_font_free(Font_Entry *fe);
89Eina_Bool evas_cserve2_font_glyph_request(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints); 90Eina_Bool evas_cserve2_font_glyph_request(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints);
90Eina_Bool evas_cserve2_font_glyph_used(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints) EINA_WARN_UNUSED_RESULT; 91Eina_Bool evas_cserve2_font_glyph_used(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints) EINA_WARN_UNUSED_RESULT;
91RGBA_Font_Glyph_Out *evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints); 92RGBA_Font_Glyph_Out *evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints);
93void evas_cserve2_font_glyph_ref(RGBA_Font_Glyph_Out *glyph, Eina_Bool incref);
92#endif 94#endif