From: Jean-Philippe Bruyère Date: Tue, 1 Feb 2022 11:34:20 +0000 (+0100) Subject: font cache mutex, func renames X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=3e40d8dc9cf566b072555a2235bf96f67ed7d93c;p=jp%2Fvkvg.git font cache mutex, func renames --- diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 8feab5c..dca954e 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -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){ diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 0a0d2b6..42a35c6 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -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; +} diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index bbce0e8..cf01d58 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -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 diff --git a/src/vkvg_device.c b/src/vkvg_device.c index ddb2129..6beb912 100644 --- a/src/vkvg_device.c +++ b/src/vkvg_device.c @@ -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; } } diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c index 90f7766..61fd138 100644 --- a/src/vkvg_fonts.c +++ b/src/vkvg_fonts.c @@ -38,9 +38,12 @@ 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; iglyph_count; i++) { #ifdef VKVG_USE_FREETYPE - uint32_t gindex = FT_Get_Char_Index( textRun->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; } diff --git a/src/vkvg_fonts.h b/src/vkvg_fonts.h index 3a2be10..d7d656a 100644 --- a/src/vkvg_fonts.h +++ b/src/vkvg_fonts.h @@ -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