[TextServer] Add mutex for FreeType face creation/deletion operations.

This commit is contained in:
bruvzg 2023-02-26 17:55:04 +02:00
parent 1bd0b296e1
commit c950a1ab94
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
4 changed files with 92 additions and 66 deletions

View File

@ -384,6 +384,8 @@ int64_t TextServerAdvanced::_get_features() const {
void TextServerAdvanced::_free_rid(const RID &p_rid) { void TextServerAdvanced::_free_rid(const RID &p_rid) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) { if (font_owner.owns(p_rid)) {
MutexLock ftlock(ft_mutex);
FontAdvanced *fd = font_owner.get_or_null(p_rid); FontAdvanced *fd = font_owner.get_or_null(p_rid);
{ {
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
@ -1319,45 +1321,48 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
// Init dynamic font. // Init dynamic font.
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
int error = 0; int error = 0;
if (!ft_library) { {
error = FT_Init_FreeType(&ft_library); MutexLock ftlock(ft_mutex);
if (error != 0) { if (!ft_library) {
memdelete(fd); error = FT_Init_FreeType(&ft_library);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); if (error != 0) {
} memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
#ifdef MODULE_SVG_ENABLED #ifdef MODULE_SVG_ENABLED
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
#endif #endif
} }
memset(&fd->stream, 0, sizeof(FT_StreamRec)); memset(&fd->stream, 0, sizeof(FT_StreamRec));
fd->stream.base = (unsigned char *)p_font_data->data_ptr; fd->stream.base = (unsigned char *)p_font_data->data_ptr;
fd->stream.size = p_font_data->data_size; fd->stream.size = p_font_data->data_size;
fd->stream.pos = 0; fd->stream.pos = 0;
FT_Open_Args fargs; FT_Open_Args fargs;
memset(&fargs, 0, sizeof(FT_Open_Args)); memset(&fargs, 0, sizeof(FT_Open_Args));
fargs.memory_base = (unsigned char *)p_font_data->data_ptr; fargs.memory_base = (unsigned char *)p_font_data->data_ptr;
fargs.memory_size = p_font_data->data_size; fargs.memory_size = p_font_data->data_size;
fargs.flags = FT_OPEN_MEMORY; fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &fd->stream; fargs.stream = &fd->stream;
int max_index = 0; int max_index = 0;
FT_Face tmp_face = nullptr; FT_Face tmp_face = nullptr;
error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
if (tmp_face && error == 0) { if (tmp_face && error == 0) {
max_index = tmp_face->num_faces - 1; max_index = tmp_face->num_faces - 1;
} }
if (tmp_face) { if (tmp_face) {
FT_Done_Face(tmp_face); FT_Done_Face(tmp_face);
} }
error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face);
if (error) { if (error) {
FT_Done_Face(fd->face); FT_Done_Face(fd->face);
fd->face = nullptr; fd->face = nullptr;
memdelete(fd); memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'.");
}
} }
if (p_font_data->msdf) { if (p_font_data->msdf) {
@ -1784,6 +1789,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
} }
_FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) { _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) {
MutexLock ftlock(ft_mutex);
for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : p_font_data->cache) { for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : p_font_data->cache) {
memdelete(E.value); memdelete(E.value);
} }
@ -1890,6 +1897,8 @@ int64_t TextServerAdvanced::_font_get_face_count(const RID &p_font_rid) const {
fargs.flags = FT_OPEN_MEMORY; fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &stream; fargs.stream = &stream;
MutexLock ftlock(ft_mutex);
FT_Face tmp_face = nullptr; FT_Face tmp_face = nullptr;
error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
if (error == 0) { if (error == 0) {
@ -2281,6 +2290,7 @@ void TextServerAdvanced::_font_clear_size_cache(const RID &p_font_rid) {
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
MutexLock ftlock(ft_mutex);
for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) { for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) {
memdelete(E.value); memdelete(E.value);
} }
@ -2292,6 +2302,7 @@ void TextServerAdvanced::_font_remove_size_cache(const RID &p_font_rid, const Ve
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
MutexLock ftlock(ft_mutex);
if (fd->cache.has(p_size)) { if (fd->cache.has(p_size)) {
memdelete(fd->cache[p_size]); memdelete(fd->cache[p_size]);
fd->cache.erase(p_size); fd->cache.erase(p_size);

View File

@ -616,6 +616,8 @@ class TextServerAdvanced : public TextServerExtension {
_FORCE_INLINE_ void _add_featuers(const Dictionary &p_source, Vector<hb_feature_t> &r_ftrs); _FORCE_INLINE_ void _add_featuers(const Dictionary &p_source, Vector<hb_feature_t> &r_ftrs);
Mutex ft_mutex;
// HarfBuzz bitmap font interface. // HarfBuzz bitmap font interface.
static hb_font_funcs_t *funcs; static hb_font_funcs_t *funcs;

View File

@ -113,6 +113,8 @@ int64_t TextServerFallback::_get_features() const {
void TextServerFallback::_free_rid(const RID &p_rid) { void TextServerFallback::_free_rid(const RID &p_rid) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
if (font_owner.owns(p_rid)) { if (font_owner.owns(p_rid)) {
MutexLock ftlock(ft_mutex);
FontFallback *fd = font_owner.get_or_null(p_rid); FontFallback *fd = font_owner.get_or_null(p_rid);
{ {
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
@ -760,45 +762,48 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
// Init dynamic font. // Init dynamic font.
#ifdef MODULE_FREETYPE_ENABLED #ifdef MODULE_FREETYPE_ENABLED
int error = 0; int error = 0;
if (!ft_library) { {
error = FT_Init_FreeType(&ft_library); MutexLock ftlock(ft_mutex);
if (error != 0) { if (!ft_library) {
memdelete(fd); error = FT_Init_FreeType(&ft_library);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); if (error != 0) {
} memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'.");
}
#ifdef MODULE_SVG_ENABLED #ifdef MODULE_SVG_ENABLED
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks());
#endif #endif
} }
memset(&fd->stream, 0, sizeof(FT_StreamRec)); memset(&fd->stream, 0, sizeof(FT_StreamRec));
fd->stream.base = (unsigned char *)p_font_data->data_ptr; fd->stream.base = (unsigned char *)p_font_data->data_ptr;
fd->stream.size = p_font_data->data_size; fd->stream.size = p_font_data->data_size;
fd->stream.pos = 0; fd->stream.pos = 0;
FT_Open_Args fargs; FT_Open_Args fargs;
memset(&fargs, 0, sizeof(FT_Open_Args)); memset(&fargs, 0, sizeof(FT_Open_Args));
fargs.memory_base = (unsigned char *)p_font_data->data_ptr; fargs.memory_base = (unsigned char *)p_font_data->data_ptr;
fargs.memory_size = p_font_data->data_size; fargs.memory_size = p_font_data->data_size;
fargs.flags = FT_OPEN_MEMORY; fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &fd->stream; fargs.stream = &fd->stream;
int max_index = 0; int max_index = 0;
FT_Face tmp_face = nullptr; FT_Face tmp_face = nullptr;
error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
if (tmp_face && error == 0) { if (tmp_face && error == 0) {
max_index = tmp_face->num_faces - 1; max_index = tmp_face->num_faces - 1;
} }
if (tmp_face) { if (tmp_face) {
FT_Done_Face(tmp_face); FT_Done_Face(tmp_face);
} }
error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face);
if (error) { if (error) {
FT_Done_Face(fd->face); FT_Done_Face(fd->face);
fd->face = nullptr; fd->face = nullptr;
memdelete(fd); memdelete(fd);
ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'.");
}
} }
if (p_font_data->msdf) { if (p_font_data->msdf) {
@ -907,6 +912,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
} }
_FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) { _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) {
MutexLock ftlock(ft_mutex);
for (const KeyValue<Vector2i, FontForSizeFallback *> &E : p_font_data->cache) { for (const KeyValue<Vector2i, FontForSizeFallback *> &E : p_font_data->cache) {
memdelete(E.value); memdelete(E.value);
} }
@ -1010,6 +1017,8 @@ int64_t TextServerFallback::_font_get_face_count(const RID &p_font_rid) const {
fargs.flags = FT_OPEN_MEMORY; fargs.flags = FT_OPEN_MEMORY;
fargs.stream = &stream; fargs.stream = &stream;
MutexLock ftlock(ft_mutex);
FT_Face tmp_face = nullptr; FT_Face tmp_face = nullptr;
error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face);
if (error == 0) { if (error == 0) {
@ -1391,6 +1400,7 @@ void TextServerFallback::_font_clear_size_cache(const RID &p_font_rid) {
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
MutexLock ftlock(ft_mutex);
for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) { for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) {
memdelete(E.value); memdelete(E.value);
} }
@ -1402,6 +1412,7 @@ void TextServerFallback::_font_remove_size_cache(const RID &p_font_rid, const Ve
ERR_FAIL_COND(!fd); ERR_FAIL_COND(!fd);
MutexLock lock(fd->mutex); MutexLock lock(fd->mutex);
MutexLock ftlock(ft_mutex);
if (fd->cache.has(p_size)) { if (fd->cache.has(p_size)) {
memdelete(fd->cache[p_size]); memdelete(fd->cache[p_size]);
fd->cache.erase(p_size); fd->cache.erase(p_size);

View File

@ -531,6 +531,8 @@ class TextServerFallback : public TextServerExtension {
void _realign(ShapedTextDataFallback *p_sd) const; void _realign(ShapedTextDataFallback *p_sd) const;
Mutex ft_mutex;
protected: protected:
static void _bind_methods(){}; static void _bind_methods(){};