Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_TTF is currently not thread-safe #28

Open
SDLBugzilla opened this issue Feb 11, 2021 · 3 comments
Open

SDL_TTF is currently not thread-safe #28

SDLBugzilla opened this issue Feb 11, 2021 · 3 comments
Milestone

Comments

@SDLBugzilla
Copy link
Collaborator

This bug report was migrated from our old Bugzilla tracker.

Reported in version: 2.0.11
Reported for operating system, platform: Linux, All

Comments on the original bug report:

On 2012-07-02 06:50:41 +0000, Folkert van Heusden wrote:

SDL_TTF is currently not thread-safe. That is: SDL_TTF at itself might be thread-safe but the FreeType library underneath is not accessed in a thread-safe way.
Please consider extending SDL_TTF so that each thread can do a SDL_TTF_Init()-like call which returns a thread-specific structure containing the result of FT_Library (http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Library ).

@slouken slouken removed the bug label May 11, 2022
@klartext
Copy link

klartext commented Mar 5, 2023

This problem should be mentioned in the README, so that it's clear when someone starts using SDL_TTF.

@klartext
Copy link

klartext commented Mar 5, 2023

What are threads allowed to do?
https://discourse.libsdl.org/t/what-are-threads-allowed-to-do/11785

Someone also offered some code as a patch there.

@slouken
Copy link
Collaborator

slouken commented Jan 15, 2024

Here is the patch in the thread, however this has the overhead of the entire FreeType library in each individual font.

diff -Naurd old/SDL_ttf.c new/SDL_ttf.c
--- old/SDL_ttf.c	2005-01-24 16:11:26.000000000 -0500
+++ new/SDL_ttf.c	2005-01-24 16:28:21.000000000 -0500
@@ -90,6 +90,7 @@
 struct _TTF_Font {
 	/* Freetype2 maintains all sorts of useful info itself */
 	FT_Face face;
+	FT_Library library;
 
 	/* We'll cache these ourselves */
 	int height;
@@ -122,10 +123,7 @@
 	int font_size_family;
 };
 
-/* The FreeType font engine/library */
-static FT_Library library;
-static int TTF_initialized = 0;
-static int TTF_byteswapped = 0;
+static int TTF_byteswapped;
 
 /* UNICODE string utilities */
 static __inline__ int UNICODE_strlen(const Uint16 *text)
@@ -205,21 +203,10 @@
 #endif /* USE_FREETYPE_ERRORS */
 }
 
+/* this exists only to maintain the ABI */
 int TTF_Init( void )
 {
-	int status = 0;On Mon, 2005-01-24 at 12:40 -0500, Albert Cahalan wrote:
> On Mon, 2005-01-24 at 09:03 -0600, Bob Pendleton wrote:
-
-	if ( ! TTF_initialized ) {
-		FT_Error error = FT_Init_FreeType( &library );
-		if ( error ) {
-			TTF_SetFTError("Couldn't init FreeType engine", error);
-			status = -1;
-		}
-	}
-	if ( status == 0 ) {
-		++TTF_initialized;
-	}
-	return status;
+	return 0;
 }
 
 static unsigned long RWread(
@@ -245,11 +232,6 @@
 	FT_Stream stream;
 	int position;
 
-	if ( ! TTF_initialized ) {
-		TTF_SetError( "Library not initialized" );
-		return NULL;
-	}
-
 	/* Check to make sure we can seek in this stream */
 	position = SDL_RWtell(src);
 	if ( position < 0 ) {
@@ -267,6 +249,13 @@
 	font->src = src;
 	font->freesrc = freesrc;
 
+	FT_Error error = FT_Init_FreeType( &font->library );
+	if ( error ) {
+		TTF_SetFTError("Couldn't init FreeType engine", error);
+		free( font );
+		return NULL;
+	}
+
 	stream = (FT_Stream)malloc(sizeof(*stream));
 	if ( stream == NULL ) {
 		TTF_SetError( "Out of memory" );
@@ -275,7 +264,7 @@
 	}
 	memset(stream, 0, sizeof(*stream));
 
-	stream->memory = library->memory;
+	stream->memory = font->library->memory;
 	stream->read = RWread;
 	stream->descriptor.pointer = src;
 	stream->pos = (unsigned long)position;
@@ -286,7 +275,7 @@
 	font->args.flags = FT_OPEN_STREAM;
 	font->args.stream = stream;
 
-	error = FT_Open_Face( library, &font->args, index, &font->face );
+	error = FT_Open_Face( font->library, &font->args, index, &font->face );
 	if( error ) {
 		TTF_SetFTError( "Couldn't load font file", error );
 		TTF_CloseFont( font );
@@ -668,6 +657,7 @@
 	if ( font->freesrc ) {
 		SDL_RWclose( font->src );
 	}
+	FT_Done_FreeType( font->library );
 	free( font );
 }
 
@@ -849,10 +839,6 @@
 	FT_UInt prev_index = 0;
 
 	/* Initialize everything to 0 */
-	if ( ! TTF_initialized ) {
-		TTF_SetError( "Library not initialized" );
-		return -1;
-	}
 	status = 0;
 	minx = maxx = 0;
 	miny = maxy = 0;
@@ -1735,14 +1721,10 @@
 
 void TTF_Quit( void )
 {
-	if ( TTF_initialized ) {
-		if ( --TTF_initialized == 0 ) {
-			FT_Done_FreeType( library );
-		}
-	}
+	return;
 }
 
 int TTF_WasInit( void )
 {
-	return TTF_initialized;
+	return 1;  // this is a don't-care value to satisfy the ABI
 }

@slouken slouken added this to the 3.0 milestone Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants