Skip to content

Commit fc4cc4d

Browse files
committed
soil2 atomic init fix
1 parent b1038d3 commit fc4cc4d

1 file changed

Lines changed: 80 additions & 21 deletions

File tree

vendor/SOIL2/src/SOIL2/SOIL2.c

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@
105105
#include <stdlib.h>
106106
#include <string.h>
107107

108+
109+
/* thread-safe init/caches when C11 atomics are available. */
110+
#if !defined(__STDC_NO_ATOMICS__)
111+
#define SOIL2_HAVE_C11_ATOMICS 1
112+
#include <stdatomic.h>
113+
#else
114+
#define SOIL2_HAVE_C11_ATOMICS 0
115+
#endif
108116
// --- projectM patched GL discovery start ---
109117

110118
#if defined(_WIN32) || defined(SOIL_PLATFORM_WIN32)
@@ -206,43 +214,57 @@ static void soil2_init_stringi(void)
206214
// --- projectM patched GL discovery end ---
207215

208216
#if defined( SOIL_X11_PLATFORM ) || defined( SOIL_PLATFORM_WIN32 ) || defined( SOIL_PLATFORM_OSX ) || defined(__HAIKU__)
209-
typedef const GLubyte *(APIENTRY * P_SOIL_glGetStringiFunc) (GLenum, GLuint);
210217

211218
// --- projectM patched GL discovery start ---
212219

213220
static int isAtLeastGL3()
214221
{
222+
/* Cache result. If atomics are available, this is thread-safe. */
223+
#if SOIL2_HAVE_C11_ATOMICS
224+
static atomic_int cached = ATOMIC_VAR_INIT(SOIL_CAPABILITY_UNKNOWN);
225+
int cached_val = atomic_load_explicit(&cached, memory_order_acquire);
226+
if (cached_val != SOIL_CAPABILITY_UNKNOWN)
227+
return cached_val;
228+
#else
215229
static int cached = SOIL_CAPABILITY_UNKNOWN;
216-
if (cached != SOIL_CAPABILITY_UNKNOWN) return cached;
230+
if (cached != SOIL_CAPABILITY_UNKNOWN)
231+
return cached;
232+
#endif
217233

218234
const char* verstr = (const char*)glGetString(GL_VERSION);
219-
if (!verstr) {
235+
if (!verstr)
236+
{
237+
#if SOIL2_HAVE_C11_ATOMICS
238+
atomic_store_explicit(&cached, SOIL_CAPABILITY_NONE, memory_order_release);
239+
return SOIL_CAPABILITY_NONE;
240+
#else
220241
cached = SOIL_CAPABILITY_NONE;
221242
return cached;
243+
#endif
222244
}
223245

224-
// Desktop examples:
225-
// "3.3.0 NVIDIA 555.xx"
226-
// GLES examples:
227-
// "OpenGL ES 3.2 Mesa ..."
228-
// "OpenGL ES-CM 1.1 ..." (old)
229246
const int is_es = (strstr(verstr, "OpenGL ES") != NULL) || (strstr(verstr, " ES ") != NULL);
230247

248+
int result = SOIL_CAPABILITY_NONE;
231249
int maj = 0, min = 0;
232-
if (is_es) {
233-
// Best-effort: parse the first X.Y in the string
250+
if (is_es)
251+
{
234252
if (sscanf(verstr, "%*[^0-9]%d.%d", &maj, &min) == 2 && maj >= 3)
235-
cached = SOIL_CAPABILITY_PRESENT;
236-
else
237-
cached = SOIL_CAPABILITY_NONE;
238-
} else {
253+
result = SOIL_CAPABILITY_PRESENT;
254+
}
255+
else
256+
{
239257
if (sscanf(verstr, "%d.%d", &maj, &min) == 2 && maj >= 3)
240-
cached = SOIL_CAPABILITY_PRESENT;
241-
else
242-
cached = SOIL_CAPABILITY_NONE;
258+
result = SOIL_CAPABILITY_PRESENT;
243259
}
244260

261+
#if SOIL2_HAVE_C11_ATOMICS
262+
atomic_store_explicit(&cached, result, memory_order_release);
263+
return result;
264+
#else
265+
cached = result;
245266
return cached;
267+
#endif
246268
}
247269
// --- projectM patched GL discovery end ---
248270

@@ -335,13 +357,35 @@ typedef void (APIENTRY * P_SOIL_GLGENERATEMIPMAPPROC)(GLenum target);
335357
static P_SOIL_GLGENERATEMIPMAPPROC soilGlGenerateMipmap = NULL;
336358

337359

360+
#if SOIL2_HAVE_C11_ATOMICS
361+
/* 0=uninitialized, 1=initializing, 2=initialized */
362+
static atomic_int soil2GlInitState = ATOMIC_VAR_INIT(0);
363+
#else
338364
static int soil2GlInitialized = 0;
365+
#endif
339366

340367
void SOIL_GL_Init()
341368
{
342369
/* Must be called after a GL context exists and AFTER SOIL_GL_SetResolver(). */
370+
#if SOIL2_HAVE_C11_ATOMICS
371+
int state = atomic_load_explicit(&soil2GlInitState, memory_order_acquire);
372+
if (state == 2)
373+
return;
374+
375+
int expected = 0;
376+
if (!atomic_compare_exchange_strong_explicit(&soil2GlInitState, &expected, 1,
377+
memory_order_acq_rel, memory_order_acquire))
378+
{
379+
while ((state = atomic_load_explicit(&soil2GlInitState, memory_order_acquire)) == 1)
380+
{
381+
/* spin */
382+
}
383+
return;
384+
}
385+
#else
343386
if (soil2GlInitialized)
344387
return;
388+
#endif
345389

346390
/* Resolve compressed upload */
347391
soilGlCompressedTexImage2D =
@@ -366,12 +410,20 @@ void SOIL_GL_Init()
366410
(P_SOIL_GLGENERATEMIPMAPPROC)SOIL_GL_GetProcAddress("glGenerateMipmapOES");
367411
}
368412

413+
#if SOIL2_HAVE_C11_ATOMICS
414+
atomic_store_explicit(&soil2GlInitState, 2, memory_order_release);
415+
#else
369416
soil2GlInitialized = 1;
417+
#endif
370418
}
371419

372420
void SOIL_GL_Destroy()
373421
{
422+
#if SOIL2_HAVE_C11_ATOMICS
423+
atomic_store_explicit(&soil2GlInitState, 0, memory_order_release);
424+
#else
374425
soil2GlInitialized = 0;
426+
#endif
375427
soilGlCompressedTexImage2D = NULL;
376428
soilGlGenerateMipmap = NULL;
377429
soilGlGetStringi = NULL;
@@ -381,10 +433,17 @@ void SOIL_GL_Destroy()
381433
/* Ensure OpenGL function pointers are initialized (safe to call repeatedly). */
382434
static void soil2_ensure_gl_initialized(void)
383435
{
384-
if(!soil2GlInitialized)
385-
{
386-
SOIL_GL_Init();
387-
}
436+
#if SOIL2_HAVE_C11_ATOMICS
437+
if (atomic_load_explicit(&soil2GlInitState, memory_order_acquire) != 2)
438+
{
439+
SOIL_GL_Init();
440+
}
441+
#else
442+
if (!soil2GlInitialized)
443+
{
444+
SOIL_GL_Init();
445+
}
446+
#endif
388447
}
389448

390449
// --- projectM patched GL discovery end ---

0 commit comments

Comments
 (0)