From 1b35ca9c32e2eac091378838ada01c24575e0c14 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 12 Feb 2025 12:10:36 -0800 Subject: [PATCH] Refactored GameInput initialization --- VisualC-GDK/SDL/SDL.vcxproj | 2 + VisualC-GDK/SDL/SDL.vcxproj.filters | 2 + VisualC/SDL/SDL.vcxproj | 2 + VisualC/SDL/SDL.vcxproj.filters | 9 +++ src/core/windows/SDL_gameinput.c | 98 ++++++++++++++++++++++++ src/core/windows/SDL_gameinput.h | 36 +++++++++ src/joystick/gdk/SDL_gameinputjoystick.c | 33 +------- src/video/windows/SDL_windowsgameinput.c | 26 ++----- 8 files changed, 158 insertions(+), 50 deletions(-) create mode 100644 src/core/windows/SDL_gameinput.c create mode 100644 src/core/windows/SDL_gameinput.h diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index 7376967129..ce0c92a282 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -425,6 +425,7 @@ + @@ -640,6 +641,7 @@ + diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters index 247bbdc0b0..1753f24768 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -27,6 +27,7 @@ + @@ -314,6 +315,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 79d5c46813..02fa7d6097 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -336,6 +336,7 @@ + @@ -538,6 +539,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index 176bea64c9..e021390875 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -486,6 +486,12 @@ audio + + core\windows + + + core\windows + core\windows @@ -1028,6 +1034,9 @@ core + + core\windows + core\windows diff --git a/src/core/windows/SDL_gameinput.c b/src/core/windows/SDL_gameinput.c new file mode 100644 index 0000000000..9ac5912db9 --- /dev/null +++ b/src/core/windows/SDL_gameinput.c @@ -0,0 +1,98 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifdef HAVE_GAMEINPUT_H + +#include "SDL_windows.h" +#include "SDL_gameinput.h" + +#ifdef SDL_PLATFORM_WIN32 +#include +// {11BE2A7E-4254-445A-9C09-FFC40F006918} +DEFINE_GUID(SDL_IID_GameInput, 0x11BE2A7E, 0x4254, 0x445A, 0x9C, 0x09, 0xFF, 0xC4, 0x0F, 0x00, 0x69, 0x18); +#endif + +static SDL_SharedObject *g_hGameInputDLL; +static IGameInput *g_pGameInput; +static int g_nGameInputRefCount; + +bool SDL_InitGameInput(IGameInput **ppGameInput) +{ + if (g_nGameInputRefCount == 0) { + g_hGameInputDLL = SDL_LoadObject("gameinput.dll"); + if (!g_hGameInputDLL) { + return false; + } + + typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput); + GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate"); + if (!GameInputCreateFunc) { + SDL_UnloadObject(g_hGameInputDLL); + return false; + } + + IGameInput *pGameInput = NULL; + HRESULT hr = GameInputCreateFunc(&pGameInput); + if (FAILED(hr)) { + SDL_UnloadObject(g_hGameInputDLL); + return WIN_SetErrorFromHRESULT("GameInputCreate failed", hr); + } + +#ifdef SDL_PLATFORM_WIN32 + hr = IGameInput_QueryInterface(pGameInput, &SDL_IID_GameInput, (void **)&g_pGameInput); + IGameInput_Release(pGameInput); + if (FAILED(hr)) { + SDL_UnloadObject(g_hGameInputDLL); + return WIN_SetErrorFromHRESULT("GameInput QueryInterface failed", hr); + } +#else + // Assume that the version we get is compatible with the current SDK + // If that isn't the case, define the correct GUID for SDL_IID_GameInput above + g_pGameInput = pGameInput; +#endif + } + ++g_nGameInputRefCount; + + if (ppGameInput) { + *ppGameInput = g_pGameInput; + } + return true; +} + +void SDL_QuitGameInput(void) +{ + SDL_assert(g_nGameInputRefCount > 0); + + --g_nGameInputRefCount; + if (g_nGameInputRefCount == 0) { + if (g_pGameInput) { + IGameInput_Release(g_pGameInput); + g_pGameInput = NULL; + } + if (g_hGameInputDLL) { + SDL_UnloadObject(g_hGameInputDLL); + g_hGameInputDLL = NULL; + } + } +} + +#endif // HAVE_GAMEINPUT_H diff --git a/src/core/windows/SDL_gameinput.h b/src/core/windows/SDL_gameinput.h new file mode 100644 index 0000000000..0022c0bdde --- /dev/null +++ b/src/core/windows/SDL_gameinput.h @@ -0,0 +1,36 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#ifndef SDL_gameinput_h_ +#define SDL_gameinput_h_ + +#ifdef HAVE_GAMEINPUT_H + +#define COBJMACROS +#include + +extern bool SDL_InitGameInput(IGameInput **ppGameInput); +extern void SDL_QuitGameInput(void); + +#endif // HAVE_GAMEINPUT_H + +#endif // SDL_gameinput_h_ diff --git a/src/joystick/gdk/SDL_gameinputjoystick.c b/src/joystick/gdk/SDL_gameinputjoystick.c index 27e36e00c5..8674ca0d4a 100644 --- a/src/joystick/gdk/SDL_gameinputjoystick.c +++ b/src/joystick/gdk/SDL_gameinputjoystick.c @@ -24,9 +24,7 @@ #include "../SDL_sysjoystick.h" #include "../usb_ids.h" - -#define COBJMACROS -#include +#include "../../core/windows/SDL_gameinput.h" // Default value for SDL_HINT_JOYSTICK_GAMEINPUT #if defined(SDL_PLATFORM_GDK) @@ -67,12 +65,10 @@ typedef struct joystick_hwdata } GAMEINPUT_InternalJoystickHwdata; static GAMEINPUT_InternalList g_GameInputList = { NULL }; -static SDL_SharedObject *g_hGameInputDLL = NULL; static IGameInput *g_pGameInput = NULL; static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE; static Uint64 g_GameInputTimestampOffset; - static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info) { if (info->supportedInput & GameInputKindGamepad) { @@ -245,24 +241,8 @@ static bool GAMEINPUT_JoystickInit(void) return true; } - if (!g_hGameInputDLL) { - g_hGameInputDLL = SDL_LoadObject("gameinput.dll"); - if (!g_hGameInputDLL) { - return false; - } - } - - if (!g_pGameInput) { - typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput); - GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate"); - if (!GameInputCreateFunc) { - return false; - } - - hR = GameInputCreateFunc(&g_pGameInput); - if (FAILED(hR)) { - return SDL_SetError("GameInputCreate failure with HRESULT of %08lX", hR); - } + if (!SDL_InitGameInput(&g_pGameInput)) { + return false; } hR = IGameInput_RegisterDeviceCallback(g_pGameInput, @@ -689,14 +669,9 @@ static void GAMEINPUT_JoystickQuit(void) GAMEINPUT_InternalRemoveByIndex(0); } - IGameInput_Release(g_pGameInput); + SDL_QuitGameInput(); g_pGameInput = NULL; } - - if (g_hGameInputDLL) { - SDL_UnloadObject(g_hGameInputDLL); - g_hGameInputDLL = NULL; - } } static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out) diff --git a/src/video/windows/SDL_windowsgameinput.c b/src/video/windows/SDL_windowsgameinput.c index ddc116af35..79b3d98ab2 100644 --- a/src/video/windows/SDL_windowsgameinput.c +++ b/src/video/windows/SDL_windowsgameinput.c @@ -27,9 +27,7 @@ #ifdef HAVE_GAMEINPUT_H -#define COBJMACROS -#include - +#include "../../core/windows/SDL_gameinput.h" #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_keyboard_c.h" #include "../../events/scancodes_windows.h" @@ -61,7 +59,6 @@ typedef struct GAMEINPUT_Device struct WIN_GameInputData { - void *hGameInputDLL; IGameInput *pGameInput; GameInputCallbackToken gameinput_callback_token; int num_devices; @@ -237,20 +234,7 @@ bool WIN_InitGameInput(SDL_VideoDevice *_this) goto done; } - data->hGameInputDLL = SDL_LoadObject("gameinput.dll"); - if (!data->hGameInputDLL) { - goto done; - } - - typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput); - GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(data->hGameInputDLL, "GameInputCreate"); - if (!GameInputCreateFunc) { - goto done; - } - - hr = GameInputCreateFunc(&data->pGameInput); - if (FAILED(hr)) { - SDL_SetError("GameInputCreate failure with HRESULT of %08X", hr); + if (!SDL_InitGameInput(&data->pGameInput)) { goto done; } @@ -587,9 +571,9 @@ void WIN_QuitGameInput(SDL_VideoDevice *_this) data->pGameInput = NULL; } - if (data->hGameInputDLL) { - SDL_UnloadObject(data->hGameInputDLL); - data->hGameInputDLL = NULL; + if (data->pGameInput) { + SDL_QuitGameInput(); + data->pGameInput = NULL; } if (data->lock) {