From 03c024309ffdac200f3d16e029ef4d9c60ef823e Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 31 May 2022 15:18:22 +0200 Subject: [PATCH] GLFW: allow multiple instantiation For now, use reference counting without any synchronization - glfwInit/Terminate should be called only from main thread, anyway. --- data/scripts/build_aja_lib_win64.sh | 2 +- src/host.cpp | 3 +++ src/host.h | 22 +++++++++++++++++++++- src/video_display/gl.cpp | 12 ++++++------ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/data/scripts/build_aja_lib_win64.sh b/data/scripts/build_aja_lib_win64.sh index cf4fd0a40..757c0db8b 100755 --- a/data/scripts/build_aja_lib_win64.sh +++ b/data/scripts/build_aja_lib_win64.sh @@ -41,7 +41,7 @@ cp src/video_display/aja.cpp aja_display.cpp MSVS_PATH=`/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/Installer/vswhere.exe -latest -property installationPath` eval vssetup=\"$MSVS_PATH\"'\\VC\\Auxiliary\\Build\\vcvars64.bat' -cmd //Q //C call "$vssetup" "&&" cl //LD //D_XKEYCHECK_H //DAJA_WINDOWS //DMSWindows //DAJA_NTV2SDK_VERSION_MAJOR=13 src/aja_common.cpp aja_capture.cpp aja_display.cpp src/video_capture/aja_win32_utils.cpp src/video_capture_params.cpp src/utils/config_file.cpp src/utils/video_frame_pool.cpp c:/AJA/lib/libajantv2.lib advapi32.lib Netapi32.lib Shell32.lib Shlwapi.lib user32.lib winmm.lib //Feaja +cmd //Q //C call "$vssetup" "&&" cl //std:c++latest //LD //D_XKEYCHECK_H //DAJA_WINDOWS //DMSWindows //DAJA_NTV2SDK_VERSION_MAJOR=13 src/aja_common.cpp aja_capture.cpp aja_display.cpp src/video_capture/aja_win32_utils.cpp src/video_capture_params.cpp src/utils/config_file.cpp src/utils/video_frame_pool.cpp c:/AJA/lib/libajantv2.lib advapi32.lib Netapi32.lib Shell32.lib Shlwapi.lib user32.lib winmm.lib //Feaja cp aja.lib /usr/local/lib cp aja.dll /usr/local/bin diff --git a/src/host.cpp b/src/host.cpp index 4f773ecd3..0553aed82 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -110,6 +110,9 @@ volatile bool should_exit = false; volatile int audio_offset; ///< added audio delay in ms (non-negative), can be used to tune AV sync volatile int video_offset; ///< added video delay in ms (non-negative), can be used to tune AV sync +/// 0->1 - call glfwInit, 1->0 call glfwTerminate; fncs shouls be called from main thr, no need to synchronize +int glfw_init_count; + std::unordered_map commandline_params; mainloop_t mainloop; diff --git a/src/host.h b/src/host.h index dc08a9dee..752116adc 100644 --- a/src/host.h +++ b/src/host.h @@ -105,6 +105,8 @@ typedef void (*mainloop_t)(void *); extern mainloop_t mainloop; extern void *mainloop_udata; +extern int glfw_init_count; + // Both of following varables are non-negative. It indicates amount of milliseconds that // audio or video should be delayed. This shall be used for AV sync control. For // getting/setting you can use get_av_delay()/set_av_delay(). All is in milliseconds. @@ -152,9 +154,27 @@ void register_should_exit_callback(struct module *mod, void (*callback)(void *), #endif #ifdef __cplusplus -#include +#include #include +#include extern std::unordered_map commandline_params; + +template struct ref_count_init_once { + std::optional operator()(T (*init)(void), int &i) { + if (i++ == 0) { + return std::optional(init()); + } + return std::nullopt; + } +}; + +struct ref_count_terminate_last { + void operator()(void (*terminate)(void), int &i) { + if (--i == 0) { + terminate(); + } + } +}; #endif #define MERGE_(a,b) a##b diff --git a/src/video_display/gl.cpp b/src/video_display/gl.cpp index 17ced8f2a..8e34e9d34 100644 --- a/src/video_display/gl.cpp +++ b/src/video_display/gl.cpp @@ -457,7 +457,7 @@ static void gl_render_vdpau(struct state_gl *s, char *data) ATTRIBUTE(unused); #endif static void gl_print_monitors(bool fullhelp) { - if (glfwInit() == GLFW_FALSE) { + if (ref_count_init_once()(glfwInit, glfw_init_count).value_or(GLFW_TRUE) == GLFW_FALSE) { LOG(LOG_LEVEL_ERROR) << "Cannot initialize GLFW!\n"; return; } @@ -493,7 +493,7 @@ static void gl_print_monitors(bool fullhelp) { cout << "(use \"fullhelp\" to see modes)\n"; } - glfwTerminate(); + ref_count_terminate_last()(glfwTerminate, glfw_init_count); } /** @@ -674,7 +674,7 @@ static void * display_gl_init(struct module *parent, const char *fmt, unsigned i free(tmp); if (ret != s) { delete s; - glfwTerminate(); + ref_count_terminate_last()(glfwTerminate, glfw_init_count); return ret; } } @@ -1321,8 +1321,8 @@ static bool display_gl_init_opengl(struct state_gl *s) { glfwSetErrorCallback(glfw_print_error); - if (glfwInit() == GLFW_FALSE) { - LOG(LOG_LEVEL_ERROR) << MOD_NAME << "glfwInit failed!\n"; + if (ref_count_init_once()(glfwInit, glfw_init_count).value_or(GLFW_TRUE) == GLFW_FALSE) { + LOG(LOG_LEVEL_ERROR) << "Cannot initialize GLFW!\n"; return false; } @@ -1442,7 +1442,7 @@ static void display_gl_cleanup_opengl(struct state_gl *s){ #endif } - glfwTerminate(); + ref_count_terminate_last()(glfwTerminate, glfw_init_count); } static void display_gl_run(void *arg)