From 87245a290a29e75d9537ec231196534624ca7c32 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 25 Jul 2021 22:55:17 +0000 Subject: [PATCH] Fix up SDL build to enable our multithread stuff. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5996 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- CMakeLists.txt | 2 +- engine/Makefile | 10 +++-- engine/client/in_sdl.c | 11 +++-- engine/client/pr_clcmd.c | 4 +- engine/client/pr_csqc.c | 2 +- engine/client/sys_sdl.c | 93 +++++++++++++++++++++++++++++++++++++-- engine/common/gl_q2bsp.c | 8 +++- engine/common/pr_bgcmd.c | 42 ++++++++++++++++++ engine/common/pr_common.h | 3 ++ engine/gl/gl_vidwayland.c | 4 +- engine/server/pr_cmds.c | 41 ----------------- 11 files changed, 160 insertions(+), 60 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 551a12ec..cc4a8431 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,7 +386,7 @@ ELSEIF(1) #SDL INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) #SDL2.0.7 supports vulkan, so lets use it. - SET(FTE_DEFINES ${FTE_DEFINES};FTE_SDL) + SET(FTE_DEFINES ${FTE_DEFINES};FTE_SDL;MULTITHREAD) SET(FTE_LIBS ${FTE_LIBS} ${SYS_LIBS} ${CMAKE_DL_LIBS} ${SDL2_LIBRARIES}) SET(FTE_ARCH_FILES engine/client/sys_sdl.c diff --git a/engine/Makefile b/engine/Makefile index 38245e9c..4f7bba63 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -1056,13 +1056,13 @@ else M_LDFLAGS=$(MLDFLAGS) $(IMAGELDFLAGS) `$(SDLCONFIG) --libs` SV_LDFLAGS=`$(SDLCONFIG) --libs` endif -GL_CFLAGS=-DFTE_SDL $(GLCFLAGS) `$(SDLCONFIG) --cflags` +GL_CFLAGS=-DFTE_SDL $(GLCFLAGS) -DMLTITHREAD `$(SDLCONFIG) --cflags` GLB_DIR=gl_$(FTE_FULLTARGET) GLCL_DIR=glcl_$(FTE_FULLTARGET) SV_DIR?=sv_$(FTE_FULLTARGET) VKCL_OBJS=$(VKQUAKE_OBJS) $(D3DGL_OBJS) gl_bloom.o $(BOTLIB_OBJS) gl_vidsdl.o snd_sdl.o cd_sdl.o sys_sdl.o in_sdl.o -VK_CFLAGS=-DFTE_SDL $(VKCFLAGS) `$(SDLCONFIG) --cflags` +VK_CFLAGS=-DFTE_SDL $(VKCFLAGS) -DMULTITHREAD `$(SDLCONFIG) --cflags` VKB_DIR=vk_$(FTE_FULLTARGET) VKCL_DIR=vk_$(FTE_FULLTARGET) VK_EXE_NAME=../$(EXE_NAME)-vk$(FTE_FULLTARGET) @@ -1070,15 +1070,17 @@ VKCL_EXE_NAME=../$(EXE_NAME)-vkcl$(FTE_FULLTARGET) SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(SERVERONLY_OBJS) $(BOTLIB_OBJS) SV_EXE_NAME=../$(EXE_NAME)-sv$(FTE_FULLTARGET) -SV_CFLAGS=-DFTE_SDL `$(SDLCONFIG) --cflags` $(SERVER_ONLY_CFLAGS) +SV_CFLAGS=-DFTE_SDL -DMULTITHREAD `$(SDLCONFIG) --cflags` $(SERVER_ONLY_CFLAGS) MINGL_DIR=mingl_$(FTE_FULLTARGET) MINGL_EXE_NAME=../$(EXE_NAME)-mingl$(FTE_FULLTARGET) MB_DIR=m_$(FTE_FULLTARGET) +MCL_DIR=mcl_$(FTE_FULLTARGET) M_EXE_NAME=../$(EXE_NAME)-$(FTE_FULLTARGET) +MCL_EXE_NAME=../$(EXE_NAME)-cl$(FTE_FULLTARGET) MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) $(BOTLIB_OBJS) gl_vidsdl.o snd_sdl.o cd_sdl.o sys_sdl.o in_sdl.o -M_CFLAGS=-DFTE_SDL $(VKCFLAGS) $(GLCFLAGS) `$(SDLCONFIG) --cflags` +M_CFLAGS=-DFTE_SDL $(VKCFLAGS) $(GLCFLAGS) -DMULTITHRED `$(SDLCONFIG) --cflags` QCC_DIR=qcc$(BITS) diff --git a/engine/client/in_sdl.c b/engine/client/in_sdl.c index db85dcef..24e78ca8 100644 --- a/engine/client/in_sdl.c +++ b/engine/client/in_sdl.c @@ -94,7 +94,7 @@ static uint32_t SDL_GiveFinger(SDL_JoystickID jid, SDL_TouchID tid, SDL_FingerID #endif #if SDL_MAJOR_VERSION >= 2 -#define MAX_JOYSTICKS 4 +#define MAX_JOYSTICKS 16 static struct sdljoy_s { //fte doesn't distinguish between joysticks and controllers. @@ -348,10 +348,11 @@ static void J_JoystickButton(SDL_JoystickID jid, int button, qboolean pressed) void J_Rumble(int id, uint16_t amp_low, uint16_t amp_high, int duration) { #if SDL_VERSION_ATLEAST(2,0,9) + int i; if (duration > 10000) duration = 10000; - for (int i = 0; i < MAX_JOYSTICKS; i++) + for (i = 0; i < MAX_JOYSTICKS; i++) { if (sdljoy[i].qdevid == id) { @@ -367,10 +368,11 @@ void J_Rumble(int id, uint16_t amp_low, uint16_t amp_high, int duration) void J_RumbleTriggers(int id, uint16_t left, uint16_t right, uint32_t duration) { #if SDL_VERSION_ATLEAST(2,0,14) + int i; if (duration > 10000) duration = 10000; - for (int i = 0; i < MAX_JOYSTICKS; i++) + for (i = 0; i < MAX_JOYSTICKS; i++) { if (sdljoy[i].qdevid == id) { @@ -386,12 +388,13 @@ void J_RumbleTriggers(int id, uint16_t left, uint16_t right, uint32_t duration) void J_SetLEDColor(int id, vec3_t color) { #if SDL_VERSION_ATLEAST(2,0,14) + int i; /* maybe we'll eventually get sRGB LEDs */ color[0] *= 255.0f; color[1] *= 255.0f; color[2] *= 255.0f; - for (int i = 0; i < MAX_JOYSTICKS; i++) + for (i = 0; i < MAX_JOYSTICKS; i++) { if (sdljoy[i].qdevid == id) { diff --git a/engine/client/pr_clcmd.c b/engine/client/pr_clcmd.c index fd1e1e09..e7ff6588 100644 --- a/engine/client/pr_clcmd.c +++ b/engine/client/pr_clcmd.c @@ -15,7 +15,7 @@ int MP_TranslateFTEtoQCCodes(keynum_t code) { safeswitch(code) { - case K_TAB: return 9; + case K_TAB: return 9; case K_ENTER: return 13; case K_ESCAPE: return 27; case K_SPACE: return 32; @@ -187,7 +187,6 @@ int MP_TranslateFTEtoQCCodes(keynum_t code) case K_MM_TRACK_NEXT: case K_MM_TRACK_PREV: case K_MM_TRACK_STOP: - case K_MAX: case K_MM_TRACK_PLAYPAUSE: case K_F13: case K_F14: @@ -200,6 +199,7 @@ int MP_TranslateFTEtoQCCodes(keynum_t code) case K_APP: case K_SEARCH: return -code; + case K_MAX: safedefault: if (code == -1) //mod bug return code; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 95286162..a8268a39 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -6764,7 +6764,7 @@ static void QCBUILTIN PF_cl_gp_settriggerfx(pubprogfuncs_t *prinst, struct globa { int device = G_FLOAT(OFS_PARM0); int size = G_INT(OFS_PARM2); - void *fxptr = PR_GetReadQCPtr(prinst, G_INT(OFS_PARM1), size); + const void *fxptr = PR_GetReadQCPtr(prinst, G_INT(OFS_PARM1), size); if (!fxptr) PR_BIError(prinst, "PF_cl_gp_settriggerfx: invalid pointer/size\n"); diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index 6dc655de..795cd2f2 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -309,6 +309,9 @@ void Sys_Quit (void) { Host_Shutdown(); + SDL_free((char*)host_parms.binarydir); + host_parms.binarydir = NULL; + exit (0); } @@ -670,6 +673,12 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) void *lib; lib = SDL_LoadObject(name); + if (!lib) + { + char libpath[MAX_OSPATH]; + Q_snprintfz(libpath, sizeof(libpath), "%s"ARCH_DL_POSTFIX, name); + lib = SDL_LoadObject(libpath); + } if (!lib) return NULL; @@ -812,6 +821,7 @@ int QDECL main(int argc, char **argv) memset(&parms, 0, sizeof(parms)); parms.basedir = "./"; + parms.binarydir = SDL_GetBasePath(); parms.argc = argc; parms.argv = (const char**)argv; @@ -940,14 +950,64 @@ void Sys_SaveClipboard(clipboardtype_t cbt, const char *text) #endif #ifdef MULTITHREAD -/* Thread creation calls */ + +/*Thread management stuff*/ +static SDL_threadID mainthread; +static SDL_TLSID tls_threadinfo; +struct threadinfo_s +{ + jmp_buf jmpbuf; //so we can actually abort our threads... + int (*threadfunc)(void *args); + void *args; +}; + +void Sys_ThreadsInit(void) +{ + mainthread = SDL_ThreadID(); +} +qboolean Sys_IsThread(void *thread) +{ + return SDL_GetThreadID(thread) == SDL_ThreadID(); +} +qboolean Sys_IsMainThread(void) +{ + return mainthread == SDL_ThreadID(); +} +void Sys_ThreadAbort(void) +{ + //SDL_KillThread(NULL) got removed... so we have to do things the shitty way. + + struct threadinfo_s *tinfo = SDL_TLSGet(tls_threadinfo); + if (!tinfo) + { //erk... not created via Sys_CreateThread?!? + SDL_Delay(10*1000); + exit(0); + } + longjmp(tinfo->jmpbuf, 1); +} +static int FTESDLThread(void *args) +{ //all for Sys_ThreadAbort + struct threadinfo_s *tinfo = args; + int r; + SDL_TLSSet(tls_threadinfo, tinfo, NULL); + if (setjmp(tinfo->jmpbuf)) + r = 0; //aborted... + else + r = tinfo->threadfunc(tinfo->args); + SDL_TLSSet(tls_threadinfo, NULL, NULL); + Z_Free(tinfo); + return r; +} void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize) { // SDL threads do not support setting thread stack size + struct threadinfo_s *tinfo = Z_Malloc(sizeof(*tinfo)); + tinfo->threadfunc = func; + tinfo->args = args; #if SDL_MAJOR_VERSION >= 2 - return (void *)SDL_CreateThread(func, name, args); + return (void *)SDL_CreateThread(FTESDLThread, name, tinfo); #else - return (void *)SDL_CreateThread(func, args); + return (void *)SDL_CreateThread(FTESDLThread, tinfo); #endif } @@ -958,6 +1018,32 @@ void Sys_WaitOnThread(void *thread) /* Mutex calls */ +#if SDL_MAJOR_VERSION >= 2 +void *Sys_CreateMutex(void) +{ + return (void *)SDL_CreateMutex(); +} + +qboolean Sys_TryLockMutex(void *mutex) +{ + return !SDL_TryLockMutex(mutex); +} + +qboolean Sys_LockMutex(void *mutex) +{ + return !SDL_LockMutex(mutex); +} + +qboolean Sys_UnlockMutex(void *mutex) +{ + return !SDL_UnlockMutex(mutex); +} + +void Sys_DestroyMutex(void *mutex) +{ + SDL_DestroyMutex(mutex); +} +#else // SDL mutexes don't have try-locks for mutexes in the spec so we stick with 1-value semaphores void *Sys_CreateMutex(void) { @@ -983,6 +1069,7 @@ void Sys_DestroyMutex(void *mutex) { SDL_DestroySemaphore(mutex); } +#endif /* Conditional wait calls */ typedef struct condvar_s diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index c03cc92a..70b51e40 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -4084,7 +4084,7 @@ static void CM_OpenAllPortals(model_t *mod, char *ents) //this is a compleate ha #endif -#if !defined(CLIENTONLY) && defined(Q3BSPS) +#if defined(HAVE_SERVER) && defined(Q3BSPS) static void CalcClusterPHS(cminfo_t *prv, int cluster) { int j, k, l, index; @@ -4742,7 +4742,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole BZ_Free(prv->faces); return NULL; } -#ifndef CLIENTONLY +#ifdef HAVE_SERVER CMQ3_CalcPHS(mod); #endif // BZ_Free(map_verts); @@ -6839,6 +6839,7 @@ qbyte *CM_ClusterPVS (model_t *mod, int cluster, pvsbuffer_t *buffer, pvsmerge_t } } +#ifdef HAVE_SERVER qbyte *CM_ClusterPHS (model_t *mod, int cluster, pvsbuffer_t *buffer) { cminfo_t *prv = (cminfo_t*)mod->meshinfo; @@ -6848,6 +6849,7 @@ qbyte *CM_ClusterPHS (model_t *mod, int cluster, pvsbuffer_t *buffer) if (buffer->buffersize < mod->pvsbytes) buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=mod->pvsbytes); +#ifdef Q3BSPS if (mod->fromgame != fg_quake2) { if (cluster != -1 && prv->q3phs->numclusters) @@ -6862,6 +6864,7 @@ qbyte *CM_ClusterPHS (model_t *mod, int cluster, pvsbuffer_t *buffer) return buffer->buffer; } } +#endif if (cluster == -1) memset (buffer->buffer, 0, (mod->numclusters+7)>>3); @@ -6869,6 +6872,7 @@ qbyte *CM_ClusterPHS (model_t *mod, int cluster, pvsbuffer_t *buffer) CM_DecompressVis (mod, ((qbyte*)prv->q2vis) + prv->q2vis->bitofs[cluster][DVIS_PHS], buffer->buffer, false); return buffer->buffer; } +#endif static unsigned int SV_Q2BSP_FatPVS (model_t *mod, const vec3_t org, pvsbuffer_t *result, qboolean merge) { diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 17ec9df5..9b7f41c6 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -7331,6 +7331,48 @@ void PR_Common_SaveGame(vfsfile_t *f, pubprogfuncs_t *prinst, qboolean binary) } +void *PR_GetWriteQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize) +{ +// void *r; + if (qcsize < 0) + return NULL; + if (!qcptr) + return NULL; + if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize) + { + if (qcptr + qcsize <= prinst->stringtablemaxsize) + return prinst->stringtable+qcptr; //its in bounds + } + /*else + { + r = PR_GetString(prinst, qcptr); + if (qcsize < strlen(r)) + return r; + }*/ + return NULL; +} +const void *PR_GetReadQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize) +{ + const char *r; + if (qcsize < 0) + return NULL; + if (!qcptr) + return NULL; + if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize) + { + if (qcptr + qcsize <= prinst->stringtablemaxsize) + return prinst->stringtable+qcptr; //its in bounds + } + else + { + r = PR_GetString(prinst, qcptr); + if (qcsize < strlen(r)) + return r; + } + return NULL; +} + + #define DEF_SAVEGLOBAL (1u<<15) static void PR_AutoCvarApply(pubprogfuncs_t *prinst, eval_t *val, etype_t type, cvar_t *var) { diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 4cfb9f61..a8727814 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -577,6 +577,9 @@ void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored); void PR_Common_SaveGame(vfsfile_t *f, pubprogfuncs_t *prinst, qboolean binary); qboolean PR_Common_LoadGame(pubprogfuncs_t *prinst, char *command, const char **file); +const void *PR_GetReadQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize); +void *PR_GetWriteQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize); + uploadfmt_t PR_TranslateTextureFormat(int qcformat); //FIXME diff --git a/engine/gl/gl_vidwayland.c b/engine/gl/gl_vidwayland.c index e549d2fe..5f6e2fd4 100644 --- a/engine/gl/gl_vidwayland.c +++ b/engine/gl/gl_vidwayland.c @@ -647,7 +647,7 @@ static const struct wl_shell_surface_listener shell_surface_listener = #endif //qkeys are ascii-compatible for the most part. -static qbyte waylandinputsucksbighairydonkeyballs[] = +static unsigned short waylandinputsucksbighairydonkeyballs[] = { 0, K_ESCAPE,'1','2','3','4','5','6', //0x '7','8','9','0','-','=',K_BACKSPACE,K_TAB, @@ -666,7 +666,7 @@ static qbyte waylandinputsucksbighairydonkeyballs[] = 0,0,0,0,0,0,0,K_PAUSE, //7x 0,0,0,0,0,K_LWIN,K_RWIN,K_APP }; -static qbyte waylandinputsucksbighairydonkeyballsshift[] = +static unsigned short waylandinputsucksbighairydonkeyballsshift[] = { 0, K_ESCAPE,'!','\"','3','$','%','^', //0x '&','*','(',')','_','+',K_BACKSPACE,K_TAB, diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index ddc87e26..af9df25e 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -272,47 +272,6 @@ static qcstate_t *PR_CreateThread(pubprogfuncs_t *prinst, float retval, float re return state; } -void *PR_GetWriteQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize) -{ -// void *r; - if (qcsize < 0) - return NULL; - if (!qcptr) - return NULL; - if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize) - { - if (qcptr + qcsize <= prinst->stringtablemaxsize) - return prinst->stringtable+qcptr; //its in bounds - } - /*else - { - r = PR_GetString(prinst, qcptr); - if (qcsize < strlen(r)) - return r; - }*/ - return NULL; -} -const void *PR_GetReadQCPtr(pubprogfuncs_t *prinst, int qcptr, int qcsize) -{ - const char *r; - if (qcsize < 0) - return NULL; - if (!qcptr) - return NULL; - if (qcptr >= 0 && qcptr <= prinst->stringtablemaxsize) - { - if (qcptr + qcsize <= prinst->stringtablemaxsize) - return prinst->stringtable+qcptr; //its in bounds - } - else - { - r = PR_GetString(prinst, qcptr); - if (qcsize < strlen(r)) - return r; - } - return NULL; -} - void PDECL ED_Spawned (struct edict_s *ent, int loading) { #ifdef VM_Q1