Font cache: Enforce mutually exclusive access to the font cache

This commit is contained in:
Gregory Nutt 2017-01-06 09:50:30 -06:00
parent 0b52e6f571
commit d7173f2eb5
2 changed files with 180 additions and 43 deletions

View File

@ -624,14 +624,14 @@ FCACHE nxf_cache_connect(enum nx_fontid_e fontid,
* font handler is invalid upon return in either case.
*
* Input Parameters:
* fcache - A font cache handler previously returned by nxf_cache_connect();
* fhandle - A font cache handler previously returned by nxf_cache_connect();
*
* Returned value:
* None
*
****************************************************************************/
void nxf_cache_disconnect(FCACHE fcache);
void nxf_cache_disconnect(FCACHE fhandle);
/****************************************************************************
* Name: nxf_cache_getfonthandle
@ -641,7 +641,7 @@ void nxf_cache_disconnect(FCACHE fcache);
* cache.
*
* Input Parameters:
* fcache - A font cache handle previously returned by nxf_cache_connect();
* fhandle - A font cache handle previously returned by nxf_cache_connect();
*
* Returned value:
* Zero (OK) is returned if the metrics were
@ -651,7 +651,7 @@ void nxf_cache_disconnect(FCACHE fcache);
*
****************************************************************************/
NXHANDLE nxf_cache_getfonthandle(FCACHE fcache);
NXHANDLE nxf_cache_getfonthandle(FCACHE fhandle);
/****************************************************************************
* Name: nxf_cache_getglyph
@ -667,7 +667,7 @@ NXHANDLE nxf_cache_getfonthandle(FCACHE fcache);
*
****************************************************************************/
FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fcache, uint8_t ch);
FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fhandle, uint8_t ch);
#undef EXTERN
#if defined(__cplusplus)

View File

@ -88,11 +88,93 @@ struct nxfonts_fcache_s
/* Head of a list of font caches */
static FAR struct nxfonts_fcache_s *g_fcaches;
static sem_t g_cachesem = SEM_INITIALIZER(1);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nxf_list_lock and nxf_list_unlock
*
* Description:
* Get/relinquish exclusive access to the font cache list
*
****************************************************************************/
static void nxf_list_lock(void)
{
int ret;
/* Get exclusive access to the font cache */
while ((ret = sem_wait(&g_cachesem)) < 0)
{
int errorcode = errno;
DEBUGASSERT(errorcode == EINTR || errorcode == ECANCELED);
UNUSED(errorcode);
}
}
#define nxf_list_unlock() (sem_post(&g_cachesem))
/****************************************************************************
* Name: nxf_removecache
*
* Description:
* Removes the entry 'glyph' from the font cache.
*
* Assumptions:
* The caller holds the font cache list semaphore.
*
****************************************************************************/
static inline void nxf_removecache(FAR struct nxfonts_fcache_s *fcache,
FAR struct nxfonts_fcache_s *prev)
{
/* Remove the cache for the list. First check for removal from the head */
if (prev == NULL)
{
/* Replace the head with the node following glyph */
g_fcaches = fcache->flink;
}
/* No.. Remove from the head or from mid-list */
else
{
prev->flink = fcache->flink;
}
fcache->flink = NULL;
}
/****************************************************************************
* Name: nxf_cache_lock and nxf_cache_unlock
*
* Description:
* Get/relinquish exclusive access to the font cache
*
****************************************************************************/
static void nxf_cache_lock(FAR struct nxfonts_fcache_s *priv)
{
int ret;
/* Get exclusive access to the font cache */
while ((ret = sem_wait(&priv->fsem)) < 0)
{
int errorcode = errno;
DEBUGASSERT(errorcode == EINTR || errorcode == ECANCELED);
UNUSED(errorcode);
}
}
#define nxf_cache_unlock(p) (sem_post(&priv->fsem))
/****************************************************************************
* Name: nxf_removeglyph
*
@ -131,7 +213,7 @@ static inline void nxf_removeglyph(FAR struct nxfonts_fcache_s *priv,
prev->flink = NULL;
}
/* No.. removae from mid-list */
/* No.. remove from mid-list */
else
{
@ -191,6 +273,9 @@ static inline void nxf_addglyph(FAR struct nxfonts_fcache_s *priv,
* glyphs since it is now the most recently used (leaving the least
* recently used glyph at the tail of the list).
*
* Assumptions:
* The caller has exclusive access to the font cache.
*
****************************************************************************/
static FAR struct nxfonts_glyph_s *
@ -340,8 +425,26 @@ static inline void nxf_fillglyph(FAR struct nxfonts_fcache_s *priv,
#ifndef CONFIG_NX_DISABLE_24BPP
if (priv->bpp == 24)
{
gerr("ERROR: Additional logic is needed to support 24-bit color\n");
goto errout_with_glyph;
FAR uint32_t *ptr = (FAR uint32_t *)glyph->bitmap;
FAR uint32_t pixel[3];
/* Get two 32-bit values for alternating 32 representations */
pixel[0] = (uint32_t)priv->bgcolor << 8 | (uint32_t)priv->bgcolor >> 16;
pixel[1] = (uint32_t)priv->bgcolor << 16 | (uint32_t)priv->bgcolor >> 8;
pixel[1] = (uint32_t)priv->bgcolor << 24 | (uint32_t)priv->bgcolor;
for (row = 0; row < glyph->height; row++)
{
/* Just copy the color value into the glyph memory */
for (col = 0; col < glyph->width; col += 3)
{
*ptr++ = pixel[0];
*ptr++ = pixel[1];
*ptr++ = pixel[2];
}
}
}
else
#endif
@ -370,6 +473,14 @@ static inline void nxf_fillglyph(FAR struct nxfonts_fcache_s *priv,
/****************************************************************************
* Name: nxf_renderglyph
*
* Description:
* Allocate memory for a new glyph and render the bitmap font into the
* allocated glyph memory.
*
* Assumptions:
* The caller holds the font cache semaphore.
*
****************************************************************************/
static inline FAR struct nxfonts_glyph_s *
@ -434,6 +545,13 @@ nxf_renderglyph(FAR struct nxfonts_fcache_s *priv,
/****************************************************************************
* Name: nxf_findcache
*
* Description:
* Find a font cache tht matches the font charcteristics.
*
* Assumptions:
* The caller holds the font cache list semaphore.
*
****************************************************************************/
static FAR struct nxfonts_fcache_s *
@ -442,9 +560,6 @@ nxf_findcache(enum nx_fontid_e fontid, nxgl_mxpixel_t fgcolor,
{
FAR struct nxfonts_fcache_s *fcache;
/* Get exclusive access to the font cache list */
#warning Missing logic
/* Search for a cache for this font characteristics */
for (fcache = g_fcaches; fcache != NULL; fcache = fcache->flink)
@ -499,6 +614,10 @@ FCACHE nxf_cache_connect(enum nx_fontid_e fontid,
FAR struct nxfonts_fcache_s *priv;
int errcode;
/* Get exclusive access to the font cache list */
nxf_list_lock();
/* Find a font cache with the matching font characteristics */
priv = nxf_findcache(fontid, fgcolor, bgcolor, bpp);
@ -516,7 +635,7 @@ FCACHE nxf_cache_connect(enum nx_fontid_e fontid,
if (priv == NULL)
{
errcode = ENOMEM;
goto errout;
goto errout_with_lock;
}
/* Initialize the font cache */
@ -598,6 +717,11 @@ FCACHE nxf_cache_connect(enum nx_fontid_e fontid,
gerr("ERROR: Failed to get font ID %d: %d\n", fontid, errcode);
goto errout_with_fcache;
}
/* Add the new font cache to the list of font caches */
priv->flink = g_fcaches;
g_fcaches = priv;
}
else
{
@ -611,11 +735,13 @@ FCACHE nxf_cache_connect(enum nx_fontid_e fontid,
}
}
nxf_list_unlock();
return (FCACHE)priv;
errout_with_fcache:
lib_free(priv);
errout:
errout_with_lock:
nxf_list_unlock();
set_errno(errcode);
return NULL;
}
@ -629,36 +755,46 @@ errout:
* font handle is invalid upon return in either case.
*
* Input Parameters:
* fcache - A font cache handle previously returned by nxf_cache_connect();
* fhandle - A font cache handle previously returned by nxf_cache_connect();
*
* Returned value:
* None
*
****************************************************************************/
void nxf_cache_disconnect(FCACHE fcache)
void nxf_cache_disconnect(FCACHE fhandle)
{
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fcache;
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle;
FAR struct nxfonts_fcache_s *fcache;
FAR struct nxfonts_fcache_s *prev;
FAR struct nxfonts_glyph_s *glyph;
FAR struct nxfonts_glyph_s *next;
int ret;
DEBUGASSERT(priv != NULL && priv->fclients > 0);
/* Get exclusive access to the font cache */
while ((ret = sem_wait(&priv->fsem)) < 0)
{
int errorcode = errno;
DEBUGASSERT(errorcode == EINTR || errorcode == ECANCELED);
UNUSED(errorcode);
}
nxf_cache_lock(priv);
/* Is this the last client of the font cache? */
if (priv->fclients <= 1)
{
/* Yes.. destroy the font cache */
/* Get exclusive access to the font cache list */
nxf_list_lock();
/* Remove the font cache from the list of caches. This is a singly
* linked list, so we must do this the hard way.
*/
for (prev = NULL, fcache = g_fcaches;
fcache != priv && fcache != NULL;
fcache = fcache->flink);
ASSERT(fcache == priv);
nxf_removecache(fcache, prev);
nxf_list_unlock();
/* Free all allocated glyph memory */
@ -683,7 +819,7 @@ void nxf_cache_disconnect(FCACHE fcache)
*/
priv->fclients--;
sem_post(&priv->fsem);
nxf_cache_unlock(priv);
}
}
@ -695,7 +831,7 @@ void nxf_cache_disconnect(FCACHE fcache)
* cache.
*
* Input Parameters:
* fcache - A font cache handle previously returned by nxf_cache_connect();
* fhandle - A font cache handle previously returned by nxf_cache_connect();
*
* Returned value:
* Zero (OK) is returned if the metrics were
@ -705,9 +841,9 @@ void nxf_cache_disconnect(FCACHE fcache)
*
****************************************************************************/
NXHANDLE nxf_cache_getfonthandle(FCACHE fcache)
NXHANDLE nxf_cache_getfonthandle(FCACHE fhandle)
{
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fcache;
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle;
DEBUGASSERT(priv != NULL && priv->font != NULL);
return priv->font;
@ -727,31 +863,32 @@ NXHANDLE nxf_cache_getfonthandle(FCACHE fcache)
*
****************************************************************************/
FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fcache, uint8_t ch)
FAR const struct nxfonts_glyph_s *nxf_cache_getglyph(FCACHE fhandle, uint8_t ch)
{
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fcache;
FAR struct nxfonts_fcache_s *priv = (FAR struct nxfonts_fcache_s *)fhandle;
FAR struct nxfonts_glyph_s *glyph;
FAR const struct nx_fontbitmap_s *fbm;
/* Get exclusive access to the font cache */
nxf_cache_lock(priv);
/* First, try to find the glyph in the cache of pre-rendered glyphs */
glyph = nxf_findglyph(priv, ch);
if (glyph != NULL)
if (glyph == NULL)
{
/* We found it in the cache .. return the cached glyph */
/* No, it is not cached... Does the code map to a font? */
return glyph;
}
/* No, it is not cached... Does the code map to a font? */
fbm = nxf_getbitmap(priv->font, ch);
if (fbm)
{
/* Yes.. render the glyph */
glyph = nxf_renderglyph(priv, fbm, ch);
fbm = nxf_getbitmap(priv->font, ch);
if (fbm)
{
/* Yes.. render the glyph */
glyph = nxf_renderglyph(priv, fbm, ch);
}
}
nxf_cache_unlock(priv);
return glyph;
}