Skip to content

Commit b68012d

Browse files
committed
remove shutdown, locking fixes
1 parent 3096218 commit b68012d

2 files changed

Lines changed: 84 additions & 76 deletions

File tree

src/libprojectM/Renderer/PlatformGLResolver.cpp

Lines changed: 47 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <Logging.hpp>
1414

1515
#include <array>
16+
#include <cstdint>
1617
#include <cstdio>
1718

1819
#ifdef _WIN32
@@ -30,12 +31,13 @@ namespace Platform {
3031

3132
GLResolver::~GLResolver()
3233
{
33-
SOIL_GL_Destroy();
34-
35-
// make sure handles are released
36-
m_eglLib.Close();
37-
m_glLib.Close();
38-
m_glxLib.Close();
34+
/*
35+
* Process-lifetime singleton: destructor runs during process teardown.
36+
* Do not call into GL or unload GL driver libraries here:
37+
* - GL context may already be destroyed on this thread.
38+
* - Other threads may still be running.
39+
* OS will reclaim mappings on exit.
40+
*/
3941
}
4042

4143
auto GLResolver::Instance() -> GLResolver&
@@ -50,6 +52,8 @@ void GLResolver::SetBackendDefault()
5052
{
5153
#ifdef __EMSCRIPTEN__
5254
m_backend = Backend::WebGl;
55+
#elif defined(__APPLE__)
56+
m_backend = Backend::Cgl;
5357
#elif defined(USE_GLES)
5458
m_backend = Backend::Egl;
5559
#elif defined(_WIN32)
@@ -63,7 +67,7 @@ void GLResolver::SetBackendDefault()
6367
auto GLResolver::Initialize(UserResolver resolver, void* userData) -> bool
6468
{
6569
// Avoids holding m_mutex while calling into GLAD (prevents deadlocks),
66-
// Prevent concurrent Initialize()/Shutdown(),
70+
// Prevent concurrent Initialize()
6771
std::unique_lock<std::mutex> lock(m_mutex);
6872

6973
if (m_loaded)
@@ -101,17 +105,17 @@ auto GLResolver::Initialize(UserResolver resolver, void* userData) -> bool
101105

102106
lock.lock();
103107

104-
if (loaded)
108+
if (!loaded)
109+
{
110+
m_loaded = false;
111+
}
112+
else
105113
{
106114
// set default in case detection failed, but loading succeeded
107115
SetBackendDefault();
108116

109117
lock.unlock();
110118

111-
// init SOIL2 gl functions
112-
SOIL_GL_SetResolver(&GLResolver::GladResolverThunk);
113-
SOIL_GL_Init();
114-
115119
GLContextCheck::Builder glCheck;
116120
#ifdef USE_GLES
117121
glCheck
@@ -125,16 +129,29 @@ auto GLResolver::Initialize(UserResolver resolver, void* userData) -> bool
125129
.WithRequireCoreProfile(true);
126130
#endif
127131

132+
const auto glDetails = glCheck.Check();
133+
128134
lock.lock();
129135

130-
auto glDetails = glCheck.Check();
131-
LOG_INFO(std::string("[GLResolver] GL Info: ") + GLContextCheck::FormatCompactLine(glDetails.info) + " backend=" + BackendToString(m_backend));
136+
LOG_INFO(std::string("[GLResolver] GL Info: ") +
137+
GLContextCheck::FormatCompactLine(glDetails.info) +
138+
" backend=" + BackendToString(m_backend));
132139
if (!glDetails.success)
133140
{
134141
LOG_FATAL(std::string("[GLResolver] GL Check failed: ") + glDetails.reason);
135142
}
136143

137-
m_loaded = glDetails.success;
144+
lock.unlock();
145+
146+
const bool ready = glDetails.success;
147+
if (ready)
148+
{
149+
SOIL_GL_SetResolver(&GLResolver::GladResolverThunk);
150+
SOIL_GL_Init();
151+
}
152+
153+
lock.lock();
154+
m_loaded = ready;
138155
}
139156

140157
m_initializing = false;
@@ -144,35 +161,6 @@ auto GLResolver::Initialize(UserResolver resolver, void* userData) -> bool
144161
return m_loaded;
145162
}
146163

147-
void GLResolver::Shutdown()
148-
{
149-
std::unique_lock<std::mutex> lock(m_mutex);
150-
151-
while (m_initializing)
152-
{
153-
m_initCv.wait(lock);
154-
}
155-
156-
SOIL_GL_Destroy();
157-
158-
m_loaded = false;
159-
m_backend = Backend::None;
160-
161-
m_userResolver = nullptr;
162-
m_userData = nullptr;
163-
164-
m_eglGetProcAddress = nullptr;
165-
#ifndef _WIN32
166-
m_glxGetProcAddress = nullptr;
167-
#else
168-
m_wglGetProcAddress = nullptr;
169-
#endif
170-
171-
m_eglLib.Close();
172-
m_glLib.Close();
173-
m_glxLib.Close();
174-
}
175-
176164
auto GLResolver::IsLoaded() const -> bool
177165
{
178166
const std::lock_guard<std::mutex> lock(m_mutex);
@@ -370,14 +358,17 @@ void GLResolver::ResolveProviderFunctions()
370358
}
371359
#endif
372360

373-
{
374-
std::array<char, 256> buf{};
375-
std::snprintf(buf.data(), buf.size(), "[GLResolver] Library handles: egl=%p gl=%p glx=%p",
376-
reinterpret_cast<void*>(m_eglLib.Handle()),
377-
reinterpret_cast<void*>(m_glLib.Handle()),
378-
reinterpret_cast<void*>(m_glxLib.Handle()));
379-
LOG_DEBUG(std::string(buf.data()));
380-
}
361+
LOG_DEBUG(std::string("[GLResolver] EGL handle=") +
362+
std::to_string(reinterpret_cast<std::uintptr_t>(m_eglLib.Handle())) +
363+
" lib=\"" + m_eglLib.LoadedName() + "\"");
364+
365+
LOG_DEBUG(std::string("[GLResolver] GL handle=") +
366+
std::to_string(reinterpret_cast<std::uintptr_t>(m_glLib.Handle())) +
367+
" lib=\"" + m_glLib.LoadedName() + "\"");
368+
369+
LOG_DEBUG(std::string("[GLResolver] GLX handle=") +
370+
std::to_string(reinterpret_cast<std::uintptr_t>(m_glxLib.Handle())) +
371+
" lib=\"" + m_glxLib.LoadedName() + "\"");
381372

382373
}
383374

@@ -514,10 +505,11 @@ auto GLResolver::ResolveUnlocked(const char* name,
514505
// 2) Platform provider getProcAddress (prefer for correctness, extensions, GLVND dispatch)
515506
if ((backend == Backend::Egl || backend == Backend::None) && eglGetProcAddressFn != nullptr)
516507
{
517-
void* ptr = eglGetProcAddressFn(name);
518-
if (ptr != nullptr)
508+
// eglGetProcAddress returns a function pointer type; convert only at the boundary.
509+
EglProc proc = eglGetProcAddressFn(name);
510+
if (proc != nullptr)
519511
{
520-
return ptr;
512+
return reinterpret_cast<void*>(proc);
521513
}
522514
}
523515

src/libprojectM/Renderer/PlatformGLResolver.hpp

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ enum class Backend : std::uint8_t
4242
/**
4343
* WegGl proc resolver (Emscripten only).
4444
*/
45-
WebGl = 4
45+
WebGl = 4,
46+
47+
/**
48+
* MacOS native CGL.
49+
* Note: CGL will be reported as None until it is assigned in the default fallback.
50+
*/
51+
Cgl = 5
4652
};
4753

4854
/**
@@ -57,19 +63,30 @@ using UserResolver = void* (*)(const char* name, void* userData);
5763
* @brief Cross-platform runtime GL/GLES resolver.
5864
*
5965
* This resolver:
60-
* - Supports: EGL, GLES, GLX, WGL, WebGL or a user supplied resolver.
61-
* - Platforms: Android, Emscripten, Linux, Mac, Windows.
62-
* - Must be initialized after a GL/GLES context has been created and made current.
63-
* - Probes for EGL/GLX/WGL by checking for a current context.
64-
* - Uses GLAD2 non-MX entrypoints (gladLoadGL / gladLoadGLES2) via a universal resolver.
65-
* - Resolves symbols using the following order (GL/GLES):
66-
* 1) User resolver callback (if any)
67-
* 2) Platform provider eglGetProcAddress / glXGetProcAddress* / wglGetProcAddress (when available)
66+
* - Supports backends: CGL (macOS native), EGL (incl. GLES), GLX, WGL, WebGL, libGLVND, ANGLE, or a user supplied resolver.
67+
* - Supports platforms: Android, Emscripten, Linux, macOS, Windows.
68+
* - Must be initialized after a GL/GLES context has been created and made current on the calling thread.
69+
* - Detects the active backend by probing for a current context:
70+
* - EGL via eglGetCurrentContext
71+
* - GLX via glXGetCurrentContext*
72+
* - WGL via wglGetCurrentContext
73+
* - macOS native falls back to CGL/NSOpenGL (no provider GetProcAddress)
74+
* - Uses GLAD2 non-MX entrypoints (gladLoadGL / gladLoadGLES2) with a single universal resolver.
75+
* - Supports libGLVND dispatch on Linux (libOpenGL.so + libGLX.so).
76+
* - Supports ANGLE when libEGL/libGLESv2 are present.
77+
*
78+
* - Resolves symbols in the following order (native GL / GLES):
79+
* 1) User resolver callback (if provided)
80+
* 2) Platform provider:
81+
* - eglGetProcAddress (EGL / ANGLE)
82+
* - glXGetProcAddress / glXGetProcAddressARB (GLX / GLVND)
83+
* - wglGetProcAddress (WGL)
6884
* 3) Global symbol table (RTLD_DEFAULT / main module)
69-
* 4) Symbols from opened libEGL / libGL / opengl32
70-
* - Resolves symbols using the following order (Emscripten):
71-
* 1) User resolver callback (if any)
72-
* 2) emscripten_webgl_get_proc_address()
85+
* 4) Symbols from explicitly opened libraries (libEGL, libGL, OpenGL.framework, opengl32)
86+
*
87+
* - Resolves symbols in the following order (Emscripten):
88+
* 1) User resolver callback (if provided)
89+
* 2) emscripten_webgl_get_proc_address / emscripten_webgl2_get_proc_address
7390
*/
7491
class GLResolver
7592
{
@@ -103,11 +120,6 @@ class GLResolver
103120
*/
104121
auto Initialize(UserResolver resolver = nullptr, void* userData = nullptr) -> bool;
105122

106-
/**
107-
* @brief Shuts down the resolver and releases library handles.
108-
*/
109-
void Shutdown();
110-
111123
/**
112124
* @brief Returns true if the resolver was successfully initialized.
113125
*/
@@ -141,12 +153,12 @@ class GLResolver
141153
void SetBackendDefault();
142154
auto LoadGlad() -> bool;
143155

144-
/* Provider function types (kept private to avoid header pollution elsewhere). */
145-
using EglGetProcAddressFn = void* (*)(const char*);
156+
using EglProc = void (*)();
157+
using EglGetProcAddressFn = EglProc (*)(const char* name);
146158

147159
#ifndef _WIN32
148160
/* glXGetProcAddress/glXGetProcAddressARB return a function pointer. */
149-
using GlxGetProcAddressFn = void (*(*)(const unsigned char*))(void);
161+
using GlxGetProcAddressFn = void (*(*)(const unsigned char*))();
150162
#else
151163
using WglGetProcAddressFn = PROC (WINAPI*)(LPCSTR);
152164
#endif
@@ -214,6 +226,10 @@ inline auto BackendToString(Backend backend) -> const char*
214226
{
215227
return "WebGL";
216228
}
229+
case Backend::Cgl:
230+
{
231+
return "CGL";
232+
}
217233
default:
218234
{
219235
return "Unknown";

0 commit comments

Comments
 (0)