]> O.S.I.I.S - jp/vkvg.git/commitdiff
font cache mutex, func renames
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 1 Feb 2022 11:34:20 +0000 (12:34 +0100)
committerj-p <jp_bruyere@hotmail.com>
Fri, 18 Feb 2022 20:09:23 +0000 (21:09 +0100)
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
src/vkvg_device.c
src/vkvg_fonts.c
src/vkvg_fonts.h

index 8feab5c68256526476e7586f1a5603038efcead5..dca954e8e23acc53277c23037bb9a3f36ce33777 100644 (file)
@@ -277,7 +277,10 @@ void vkvg_destroy (VkvgContext ctx)
        _clear_context (ctx);
 
 #if VKVG_DBG_STATS
-       vkvg_debug_stats_t* dbgstats = &ctx->pSurf->dev->debug_stats;
+       if (ctx->dev->threadAware)
+               mtx_lock (&ctx->dev->mutex);
+       
+       vkvg_debug_stats_t* dbgstats = &ctx->dev->debug_stats;
        if (dbgstats->sizePoints < ctx->sizePoints)
                dbgstats->sizePoints = ctx->sizePoints;
        if (dbgstats->sizePathes < ctx->sizePathes)
@@ -291,6 +294,8 @@ void vkvg_destroy (VkvgContext ctx)
        if (dbgstats->sizeIBO < ctx->sizeIBO)
                dbgstats->sizeIBO = ctx->sizeIBO;
 
+       if (ctx->dev->threadAware)
+               mtx_unlock (&ctx->dev->mutex);
 #endif
 
        if (!ctx->status && ctx->dev->cachedContextCount < VKVG_MAX_CACHED_CONTEXT_COUNT) {
@@ -1108,7 +1113,7 @@ void vkvg_load_font_from_path (VkvgContext ctx, const char* path, const char* na
        if (ctx->status)
                return;
        RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
-       _add_new_font_identity(ctx, path, name);
+       _font_cache_add_font_identity(ctx, path, name);
        _select_font_face (ctx, name);
 }
 void vkvg_set_font_size (VkvgContext ctx, uint32_t size){
@@ -1137,7 +1142,7 @@ void vkvg_show_text (VkvgContext ctx, const char* text){
        RECORD(ctx, VKVG_CMD_SHOW_TEXT, text);
        LOG(VKVG_LOG_INFO_CMD, "CMD: show_text:\n");
        //_ensure_renderpass_is_started(ctx);
-       _show_text (ctx, text);
+       _font_cache_show_text (ctx, text);
        //_flush_undrawn_vertices (ctx);
 }
 
@@ -1145,17 +1150,17 @@ VkvgText vkvg_text_run_create (VkvgContext ctx, const char* text) {
        if (ctx->status)
                return NULL;
        VkvgText tr = (vkvg_text_run_t*)calloc(1, sizeof(vkvg_text_run_t));
-       _create_text_run(ctx, text, tr);
+       _font_cache_create_text_run(ctx, text, tr);
        return tr;
 }
 void vkvg_text_run_destroy (VkvgText textRun) {
-       _destroy_text_run (textRun);
+       _font_cache_destroy_text_run (textRun);
        free (textRun);
 }
 void vkvg_show_text_run (VkvgContext ctx, VkvgText textRun) {
        if (ctx->status)
                return;
-       _show_text_run(ctx, textRun);
+       _font_cache_show_text_run(ctx, textRun);
 }
 void vkvg_text_run_get_extents (VkvgText textRun, vkvg_text_extents_t* extents) {
        extents = &textRun->extents;
@@ -1164,12 +1169,12 @@ void vkvg_text_run_get_extents (VkvgText textRun, vkvg_text_extents_t* extents)
 void vkvg_text_extents (VkvgContext ctx, const char* text, vkvg_text_extents_t* extents) {
        if (ctx->status)
                return;
-       _text_extents(ctx, text, extents);
+       _font_cache_text_extents(ctx, text, extents);
 }
 void vkvg_font_extents (VkvgContext ctx, vkvg_font_extents_t* extents) {
        if (ctx->status)
                return;
-       _font_extents(ctx, extents);
+       _font_cache_font_extents(ctx, extents);
 }
 
 void vkvg_save (VkvgContext ctx){
index 0a0d2b6ead21bf77df5dddd96e1509d0aef40aa1..42a35c63b1788bd056cee3329a7a5a97cc9f80bc 100644 (file)
@@ -1928,3 +1928,11 @@ void _draw_full_screen_quad (VkvgContext ctx, bool useScissor) {
        vkh_cmd_label_end (ctx->cmd);
 #endif
 }
+
+void _select_font_face (VkvgContext ctx, const char* name){
+       if (strcmp(ctx->selectedFontName, name) == 0)
+               return;
+       strcpy (ctx->selectedFontName, name);
+       ctx->currentFont = NULL;
+       ctx->currentFontSize = NULL;
+}
index bbce0e84e63d50b175d050ab9c41a401e0c8edfb..cf01d589e1c6e3f9cd7b66d6997625858b0b9522 100644 (file)
@@ -327,5 +327,8 @@ void _bezier (VkvgContext ctx,
                          float x1, float y1, float x2, float y2,
                          float x3, float y3, float x4, float y4);
 void _line_to          (VkvgContext ctx, float x, float y);
-void _elliptic_arc     (VkvgContext ctx, float x1, float y1, float x2, float y2, bool largeArc, bool counterClockWise, float _rx, float _ry, float phi);
+void _elliptic_arc     (VkvgContext ctx, float x1, float y1, float x2, float y2,
+                                        bool largeArc, bool counterClockWise, float _rx, float _ry, float phi);
+
+void _select_font_face                 (VkvgContext ctx, const char* name);
 #endif
index ddb2129c3ae18b60d7d8b16a2be11c7192ee0b58..6beb912151cbf12e7ba29dd6b7da23769d58317f 100644 (file)
@@ -74,7 +74,7 @@ void _device_init (VkvgDevice dev, VkInstance inst, VkPhysicalDevice phy, VkDevi
        dev->fence      = vkh_fence_create_signaled ((VkhDevice)dev);
 
        _device_create_pipeline_cache           (dev);
-       _init_fonts_cache                       (dev);
+       _fonts_cache_create                     (dev);
        if (dev->deferredResolve || dev->samples == VK_SAMPLE_COUNT_1_BIT){
                dev->renderPass = _device_createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD);
                dev->renderPass_ClearStencil = _device_createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR);
@@ -308,7 +308,7 @@ void vkvg_device_destroy (VkvgDevice dev)
 
        vkh_queue_destroy(dev->gQueue);
 
-       _destroy_font_cache(dev);
+       _font_cache_destroy(dev);
 
        vmaDestroyAllocator (dev->allocator);
 
@@ -351,9 +351,11 @@ void vkvg_device_set_thread_aware (VkvgDevice dev, uint32_t thread_aware) {
                if (dev->threadAware)
                        return;
                mtx_init (&dev->mutex, mtx_plain);
+               mtx_init (&dev->fontCache->mutex, mtx_plain);
                dev->threadAware = true;
        } else if (dev->threadAware) {
                mtx_destroy (&dev->mutex);
+               mtx_destroy (&dev->fontCache->mutex);
                dev->threadAware = false;
        }
 }
index 90f776622a528f02348598e9533d0cb64b86e8c0..61fd138915eaa0b795a016bd8ea6cdc51600b2af 100644 (file)
 
 static int defaultFontCharSize = 12<<6;
 
-void _init_fonts_cache (VkvgDevice dev){
+void _fonts_cache_create (VkvgDevice dev){
        _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t));
 
+       if (dev->threadAware)
+               mtx_init (&cache->mutex, mtx_plain);
+
 #ifdef VKVG_USE_FONTCONFIG
        cache->config = FcInitLoadConfigAndFonts();
        if (!cache->config) {
@@ -157,6 +160,55 @@ void _increase_font_tex_array (VkvgDevice dev){
        }*/
        _device_wait_idle(dev);
 }
+//flush font stagging buffer to cache texture array
+//Trigger stagging buffer to be uploaded in font cache. Groupping upload improve performances.
+void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
+       
+       LOCK_FONTCACHE (dev)
+
+       _font_cache_t* cache = dev->fontCache;
+       if (cache->stagingX == 0) {//no char in stagging buff to flush
+               UNLOCK_FONTCACHE (dev)
+               return;
+       }
+
+       LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n",f->curLine.penX, f->curLine.penY);
+       vkWaitForFences         (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
+       _device_reset_fence (dev, cache->uploadFence);
+       vkResetCommandBuffer(cache->cmd,0);
+
+       memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
+
+       vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+
+       VkImageSubresourceRange subres          = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,f->curLine.pageIdx,1};
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+       VkBufferImageCopy bufferCopyRegion = { .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,f->curLine.pageIdx,1},
+                                                                                  .bufferRowLength = FONT_PAGE_SIZE,
+                                                                                  .bufferImageHeight = f->curLine.height,
+                                                                                  .imageOffset = {f->curLine.penX,f->curLine.penY,0},
+                                                                                  .imageExtent = {FONT_PAGE_SIZE-f->curLine.penX,f->curLine.height,1}};
+
+       vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer,
+                                                  vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
+
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+
+       VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+
+       _device_submit_cmd (dev, &cache->cmd, cache->uploadFence);
+
+       f->curLine.penX += cache->stagingX;
+       cache->stagingX = 0;
+       memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
+
+       UNLOCK_FONTCACHE (dev)
+}
 ///Start a new line in font cache, increase texture layer count if needed.
 void _init_next_line_in_tex_cache (VkvgDevice dev, _vkvg_font_t* f){
        _font_cache_t* cache = dev->fontCache;
@@ -174,7 +226,7 @@ void _init_next_line_in_tex_cache (VkvgDevice dev, _vkvg_font_t* f){
        _increase_font_tex_array        (dev);
        _init_next_line_in_tex_cache(dev, f);
 }
-void _destroy_font_cache (VkvgDevice dev){
+void _font_cache_destroy (VkvgDevice dev){
        _font_cache_t* cache = (_font_cache_t*)dev->fontCache;
 
        free (cache->hostBuff);
@@ -216,7 +268,6 @@ void _destroy_font_cache (VkvgDevice dev){
        free(cache->fonts);
        free(cache->pensY);
 
-
        vkvg_buffer_destroy (&cache->buff);
        vkh_image_destroy       (cache->texture);
        //vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
@@ -229,52 +280,13 @@ void _destroy_font_cache (VkvgDevice dev){
        FcFini();
 #endif
 
+       if (dev->threadAware)
+               mtx_destroy (&cache->mutex);
+
        free (dev->fontCache);
 
 }
 
-
-//flush font stagging buffer to cache texture array
-void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
-       _font_cache_t* cache = dev->fontCache;
-       if (cache->stagingX == 0)//no char in stagging buff to flush
-               return;
-
-       LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n",f->curLine.penX, f->curLine.penY);
-       vkWaitForFences         (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
-       _device_reset_fence (dev, cache->uploadFence);
-       vkResetCommandBuffer(cache->cmd,0);
-
-       memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
-
-       vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
-
-       VkImageSubresourceRange subres          = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,f->curLine.pageIdx,1};
-       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-
-       VkBufferImageCopy bufferCopyRegion = { .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,f->curLine.pageIdx,1},
-                                                                                  .bufferRowLength = FONT_PAGE_SIZE,
-                                                                                  .bufferImageHeight = f->curLine.height,
-                                                                                  .imageOffset = {f->curLine.penX,f->curLine.penY,0},
-                                                                                  .imageExtent = {FONT_PAGE_SIZE-f->curLine.penX,f->curLine.height,1}};
-
-       vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer,
-                                                  vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
-
-       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                                               VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
-
-       VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
-
-       _device_submit_cmd (dev, &cache->cmd, cache->uploadFence);
-
-       f->curLine.penX += cache->stagingX;
-       cache->stagingX = 0;
-       memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
-}
 //create a new char entry and put glyph in stagging buffer, ready for upload.
 _char_ref* _prepare_char (VkvgDevice dev, VkvgText tr, uint32_t gindex){
        _vkvg_font_t* f = tr->font;
@@ -286,12 +298,12 @@ _char_ref* _prepare_char (VkvgDevice dev, VkvgText tr, uint32_t gindex){
                FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_RENDER));
        #endif
 
-       FT_GlyphSlot    slot    = f->face->glyph;
-       FT_Bitmap               bmp             = slot->bitmap;
+       FT_GlyphSlot    slot                    = f->face->glyph;
+       FT_Bitmap               bmp                             = slot->bitmap;
        uint32_t                bmpByteWidth    = bmp.width;
        uint32_t                bmpPixelWidth   = bmp.width;
-       uint32_t                bmpRows = bmp.rows;
-       unsigned char*  buffer = bmp.buffer;
+       uint32_t                bmpRows                 = bmp.rows;
+       unsigned char*  buffer                  = bmp.buffer;
 
 #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
        bmpPixelWidth /= 3;
@@ -364,7 +376,7 @@ void _font_add_name (_vkvg_font_identity_t* font, const char* name, int nameLeng
        font->names[font->namesCount-1] = (char*)calloc(nameLength, sizeof (char));
        strcpy (font->names[font->namesCount-1], name);
 }
-void _add_new_font_identity (VkvgContext ctx, const char* fontFile, const char* name){
+void _font_cache_add_font_identity (VkvgContext ctx, const char* fontFile, const char* name){
        _font_cache_t*  cache = (_font_cache_t*)ctx->dev->fontCache;
        if (++cache->fontsCount == 1)
                cache->fonts = (_vkvg_font_identity_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_identity_t));
@@ -380,13 +392,6 @@ void _add_new_font_identity (VkvgContext ctx, const char* fontFile, const char*
        cache->fonts[cache->fontsCount-1] = nf;
 }
 //select current font for context
-void _select_font_face (VkvgContext ctx, const char* name){
-       if (strcmp(ctx->selectedFontName, name) == 0)
-               return;
-       strcpy (ctx->selectedFontName, name);
-       ctx->currentFont = NULL;
-       ctx->currentFontSize = NULL;
-}
 _vkvg_font_t* _find_or_create_font_size (VkvgContext ctx) {
        _vkvg_font_identity_t* font = ctx->currentFont;
 #ifndef VKVG_USE_FREETYPE
@@ -448,7 +453,7 @@ _vkvg_font_t* _find_or_create_font_size (VkvgContext ctx) {
 
 //try find font already resolved with fontconfig by font name
 bool _tryFindFontByName (VkvgContext ctx, _vkvg_font_identity_t** font){
-       _font_cache_t*  cache = (_font_cache_t*)ctx->dev->fontCache;
+       _font_cache_t*  cache = ctx->dev->fontCache;
        for (int i = 0; i < cache->fontsCount; ++i) {
                for (uint32_t j = 0; j < cache->fonts[i].namesCount; j++) {
                        if (strcmp (cache->fonts[i].names[j], ctx->selectedFontName) == 0) {
@@ -460,6 +465,9 @@ bool _tryFindFontByName (VkvgContext ctx, _vkvg_font_identity_t** font){
        return false;
 }
 bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t** resolvedFont) {
+
+       LOCK_FONTCACHE(ctx->dev)
+
        _font_cache_t*  cache = (_font_cache_t*)ctx->dev->fontCache;
        char* fontFile = NULL;
 
@@ -485,7 +493,7 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
                }
                if (!*resolvedFont) {
                        //if not found, create a new vkvg_font
-                       _add_new_font_identity(ctx, fontFile, ctx->selectedFontName);
+                       _font_cache_add_font_identity(ctx, fontFile, ctx->selectedFontName);
                        *resolvedFont = &cache->fonts[cache->fontsCount-1];
                }
        }
@@ -494,6 +502,9 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
        FcPatternDestroy(pat);
        FcPatternDestroy(font);
 #endif
+
+       UNLOCK_FONTCACHE(ctx->dev)
+
        return (fontFile != NULL);
 }
 
@@ -501,6 +512,7 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
 //try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
 void _update_current_font (VkvgContext ctx) {
        if (ctx->currentFont == NULL){
+               LOCK_FONTCACHE(ctx->dev)
                if (ctx->selectedFontName[0] == 0)
                        _select_font_face (ctx, "sans");
 
@@ -508,6 +520,7 @@ void _update_current_font (VkvgContext ctx) {
                        _tryResolveFontNameWithFontConfig (ctx, &ctx->currentFont);
 
                ctx->currentFontSize = _find_or_create_font_size (ctx);
+               UNLOCK_FONTCACHE(ctx->dev)
        }       
 }
 
@@ -533,7 +546,7 @@ hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text) {
 #endif
 
 //retrieve global font extends of context's current font as defined by FreeType
-void _font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
+void _font_cache_font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
        _update_current_font (ctx);
 
        if (ctx->status)
@@ -542,41 +555,40 @@ void _font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
        //TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
        _vkvg_font_t* font = ctx->currentFontSize;
 #ifdef VKVG_USE_FREETYPE
-       FT_BBox* bbox = &font->face->bbox;
-       FT_Size_Metrics* metrics = &font->face->size->metrics;
-       extents->ascent = (float)(FT_MulFix(font->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
-       extents->descent= -(float)(FT_MulFix(font->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
-       extents->height = (float)(FT_MulFix(font->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
-       extents->max_x_advance = (float)(bbox->xMax >> 6);
-       extents->max_y_advance = (float)(bbox->yMax >> 6);
+       FT_BBox*                        bbox    = &font->face->bbox;
+       FT_Size_Metrics*        metrics = &font->face->size->metrics;
+
+       extents->ascent                 = (float)(FT_MulFix(font->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
+       extents->descent                =-(float)(FT_MulFix(font->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
+       extents->height                 = (float)(FT_MulFix(font->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
+       extents->max_x_advance  = (float)(bbox->xMax >> 6);
+       extents->max_y_advance  = (float)(bbox->yMax >> 6);
 #else
-       extents->ascent = roundf (font->scale * ctx->currentFont->ascent);
-       extents->descent-roundf (font->scale * ctx->currentFont->descent);
-       extents->height = roundf (font->scale * (ctx->currentFont->ascent - ctx->currentFont->descent + ctx->currentFont->lineGap));
-       extents->max_x_advance = 0;//TODO
-       extents->max_y_advance = 0;
+       extents->ascent                 = roundf (font->scale * ctx->currentFont->ascent);
+       extents->descent                =-roundf (font->scale * ctx->currentFont->descent);
+       extents->height                 = roundf (font->scale * (ctx->currentFont->ascent - ctx->currentFont->descent + ctx->currentFont->lineGap));
+       extents->max_x_advance  = 0;//TODO
+       extents->max_y_advance  = 0;
 #endif
 }
 //compute text extends for provided string.
-void _text_extents (VkvgContext ctx, const char* text, vkvg_text_extents_t *extents) {
+void _font_cache_text_extents (VkvgContext ctx, const char* text, vkvg_text_extents_t *extents) {
        if (text == NULL) {
                memset(extents, 0, sizeof(vkvg_text_extents_t));
                return;
        }
 
-       _update_current_font (ctx);
+       vkvg_text_run_t tr = {0};
+       _font_cache_create_text_run (ctx, text, &tr);
 
        if (ctx->status)
                return;
 
-       vkvg_text_run_t tr = {0};
-       _create_text_run (ctx, text, &tr);
-
        *extents = tr.extents;
 
-       _destroy_text_run (&tr);
+       _font_cache_destroy_text_run (&tr);
 }
-void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
+void _font_cache_create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
 
        _update_current_font (ctx);
 
@@ -587,6 +599,8 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
        textRun->font = ctx->currentFontSize;
        textRun->dev = ctx->dev;
 
+       LOCK_FONTCACHE (ctx->dev)
+
 #ifdef VKVG_USE_HARFBUZZ
        textRun->hbBuf = _get_hb_buffer (ctx->currentFontSize, text);
        textRun->glyphs = hb_buffer_get_glyph_positions  (textRun->hbBuf, &textRun->glyph_count);
@@ -600,13 +614,13 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
                textRun->glyphs = (vkvg_glyph_info_t*)malloc(textRun->glyph_count * sizeof (vkvg_glyph_info_t));
                for (unsigned int i=0; i<textRun->glyph_count; i++) {
 #ifdef VKVG_USE_FREETYPE
-                       uint32_t gindex = FT_Get_Char_IndextextRun->font->face, tmp[i]);
+                       uint32_t gindex = FT_Get_Char_Index (textRun->font->face, tmp[i]);
 #else
-                       uint32_t gindex = stbtt_FindGlyphIndex(&textRun->fontId->stbInfo, tmp[i]);
+                       uint32_t gindex = stbtt_FindGlyphIndex (&textRun->fontId->stbInfo, tmp[i]);
 #endif
                        _char_ref* cr = textRun->font->charLookup[gindex];
                        if (cr==NULL)
-                               cr = _prepare_char(textRun->dev, textRun, gindex);
+                               cr = _prepare_char (textRun->dev, textRun, gindex);
                        textRun->glyphs[i].codepoint = gindex;
                        textRun->glyphs[i].x_advance = cr->advance.x;
                        textRun->glyphs[i].y_advance = cr->advance.y;
@@ -618,6 +632,8 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
                free (tmp);
        }
 #endif
+       
+       UNLOCK_FONTCACHE (ctx->dev)
 
        unsigned int string_width_in_pixels = 0;
        for (uint32_t i=0; i < textRun->glyph_count; ++i)
@@ -637,7 +653,7 @@ void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
 
        textRun->extents.width  = textRun->extents.x_advance;
 }
-void _destroy_text_run (VkvgText textRun) {
+void _font_cache_destroy_text_run (VkvgText textRun) {
 #ifdef VKVG_USE_HARFBUZZ
        hb_buffer_destroy (textRun->hbBuf);
 #else
@@ -664,7 +680,7 @@ void _show_texture (vkvg_context* ctx){
        _add_tri_indices_for_rect(ctx, firstIdx);
 }
 #endif
-void _show_text_run (VkvgContext ctx, VkvgText tr) {
+void _font_cache_show_text_run (VkvgContext ctx, VkvgText tr) {
        unsigned int glyph_count;
 #ifdef VKVG_USE_HARFBUZZ
        hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos (tr->hbBuf, &glyph_count);
@@ -727,18 +743,17 @@ void _show_text_run (VkvgContext ctx, VkvgText tr) {
        _flush_chars_to_tex(tr->dev, tr->font);
 }
 
-
-void _show_text (VkvgContext ctx, const char* text){
+void _font_cache_show_text (VkvgContext ctx, const char* text){
 
        vkvg_text_run_t tr = {0};
-       _create_text_run (ctx, text, &tr);
+       _font_cache_create_text_run (ctx, text, &tr);
 
        if (ctx->status)
                return;
 
-       _show_text_run (ctx, &tr);
+       _font_cache_show_text_run (ctx, &tr);
 
-       _destroy_text_run (&tr);
+       _font_cache_destroy_text_run (&tr);
 
        //_show_texture(ctx); return;
 }
index 3a2be102d1f5878ed8e13f03dd78d8273d7fb658..d7d656ad4337d88d60af24cac39451b5e50ed675 100644 (file)
@@ -77,6 +77,7 @@ typedef struct {
        vec2            advance;
 #endif
 }_char_ref;
+
 // Current location in font cache texture array for new character addition. Each font holds such structure to locate
 // where to upload new chars.
 typedef struct {
@@ -85,11 +86,12 @@ typedef struct {
        int                     penY;                           /* Current Y in cache for next char addition */
        int                     height;                         /* Height of current line pointed by this structure */
 }_tex_ref_t;
+
 // Loaded font structure, one per size, holds informations for glyphes upload in cache and the lookup table of characters.
 typedef struct {
 #ifdef VKVG_USE_FREETYPE
-       FT_F26Dot6      charSize;                       /* Font size*/
-       FT_Face         face;                           /* FreeType face*/
+       FT_F26Dot6              charSize;               /* Font size*/
+       FT_Face                 face;                   /* FreeType face*/
 #else
        uint32_t                charSize;               /* Font size in pixel */
        float                   scale;                  /* scale factor for the given size */
@@ -99,11 +101,11 @@ typedef struct {
 #endif
 
 #ifdef VKVG_USE_HARFBUZZ
-       hb_font_t*      hb_font;                        /* HarfBuzz font instance*/
+       hb_font_t*              hb_font;                /* HarfBuzz font instance*/
 #endif
-       _char_ref** charLookup;                 /* Lookup table of characteres in cache, if not found, upload is queued*/
+       _char_ref**             charLookup;             /* Lookup table of characteres in cache, if not found, upload is queued*/
 
-       _tex_ref_t      curLine;                        /* tex coord where to add new char bmp's */
+       _tex_ref_t              curLine;                /* tex coord where to add new char bmp's */
 }_vkvg_font_t;
 
 /* Font identification structure */
@@ -143,10 +145,19 @@ typedef struct {
        uint8_t                 texLength;              /* layer count of 2d array texture, starts with FONT_CACHE_INIT_LAYERS count and increased when needed */
        int*                    pensY;                  /* array of current y pen positions for each texture in cache 2d array */
        VkFence                 uploadFence;    /* Signaled when upload is finished */
+       mtx_t                   mutex;                  /* font cache global mutex, used only if device is in thread aware mode (see: vkvg_device_set_thread_aware) */
 
        _vkvg_font_identity_t*  fonts;  /* Loaded fonts structure array */
        int32_t                 fontsCount;             /* Loaded fonts array count*/
 }_font_cache_t;
+
+#define LOCK_FONTCACHE(dev) \
+       if (dev->threadAware)\
+               mtx_lock (&dev->fontCache->mutex);
+#define UNLOCK_FONTCACHE(dev) \
+       if (dev->threadAware)\
+               mtx_unlock (&dev->fontCache->mutex);
+
 #ifndef VKVG_USE_HARFBUZZ
 typedef struct _glyph_info_t {
   int32_t  x_advance;
@@ -156,40 +167,38 @@ typedef struct _glyph_info_t {
   uint32_t codepoint;//should be named glyphIndex, but for harfbuzz compatibility...
 } vkvg_glyph_info_t;
 #endif
-// Precompute everything necessary to draw one line of text, usefull to draw the same text multiple times.
+
+// Precompute everything necessary to measure and draw one line of text, usefull to draw the same text multiple times.
 typedef struct _vkvg_text_run_t {
-       _vkvg_font_identity_t*fontId;   /* vkvg font structure pointer */
-       _vkvg_font_t*           font;           /* vkvg font structure pointer */
-       VkvgDevice                      dev;            /* vkvg device associated with this text run */
-       vkvg_text_extents_t extents;    /* store computed text extends */
-       const char*                     text;           /* utf8 char array of text*/
-       unsigned int            glyph_count;/* Total glyph count */
+       _vkvg_font_identity_t*  fontId;         /* vkvg font structure pointer */
+       _vkvg_font_t*                   font;           /* vkvg font structure pointer */
+       VkvgDevice                              dev;            /* vkvg device associated with this text run */
+       vkvg_text_extents_t             extents;        /* store computed text extends */
+       const char*                             text;           /* utf8 char array of text*/
+       unsigned int                    glyph_count;/* Total glyph count */
 #ifdef VKVG_USE_HARFBUZZ
-       hb_buffer_t*            hbBuf;          /* HarfBuzz buffer of text */
-       hb_glyph_position_t *glyphs; /* HarfBuzz computed glyph positions array */
+       hb_buffer_t*                    hbBuf;          /* HarfBuzz buffer of text */
+       hb_glyph_position_t*    glyphs;         /* HarfBuzz computed glyph positions array */
 #else
-       vkvg_glyph_info_t       *glyphs; /* computed glyph positions array */
+       vkvg_glyph_info_t*              glyphs;         /* computed glyph positions array */
 #endif
 } vkvg_text_run_t;
+
 //Create font cache.
-void _init_fonts_cache         (VkvgDevice dev);
+void _fonts_cache_create               (VkvgDevice dev);
 //Release all ressources of font cache.
-void _destroy_font_cache       (VkvgDevice dev);
-//Select current font for context from font name, create new font entry in cache if required
-void _select_font_face         (VkvgContext ctx, const char* name);
-void _add_new_font_identity    (VkvgContext ctx, const char* fontFile, const char *name);
+void _font_cache_destroy       (VkvgDevice dev);
+void _font_cache_add_font_identity     (VkvgContext ctx, const char* fontFile, const char *name);
 //Draw text
-void _show_text                                (VkvgContext ctx, const char* text);
+void _font_cache_show_text                             (VkvgContext ctx, const char* text);
 //Get text dimmensions
-void _text_extents                     (VkvgContext ctx, const char* text, vkvg_text_extents_t *extents);
+void _font_cache_text_extents                  (VkvgContext ctx, const char* text, vkvg_text_extents_t *extents);
 //Get font global dimmensions
-void _font_extents                     (VkvgContext ctx, vkvg_font_extents_t* extents);
+void _font_cache_font_extents                  (VkvgContext ctx, vkvg_font_extents_t* extents);
 //Create text object that could be drawn multiple times minimizing harfbuzz and compute processing.
-void _create_text_run          (VkvgContext ctx, const char* text, VkvgText textRun);
+void _font_cache_create_text_run               (VkvgContext ctx, const char* text, VkvgText textRun);
 //Release ressources held by a text run.
-void _destroy_text_run         (VkvgText textRun);
+void _font_cache_destroy_text_run              (VkvgText textRun);
 //Draw text run
-void _show_text_run                    (VkvgContext ctx, VkvgText tr);
-//Trigger stagging buffer to be uploaded in font cache. Groupping upload improve performances.
-void _flush_chars_to_tex       (VkvgDevice dev, _vkvg_font_t* f);
+void _font_cache_show_text_run                 (VkvgContext ctx, VkvgText tr);
 #endif