Fixed memory leaks if OpenVR initialization fails

This commit is contained in:
Sam Lantinga
2024-10-21 14:59:18 -07:00
parent 7b492553c4
commit d199586683

View File

@@ -271,7 +271,6 @@ static bool OPENVR_VideoInit(SDL_VideoDevice *_this)
{ {
SDL_VideoData *data = (SDL_VideoData *)_this->internal; SDL_VideoData *data = (SDL_VideoData *)_this->internal;
{
const char * hintWidth = SDL_GetHint("SDL_DEFAULT_WIDTH"); const char * hintWidth = SDL_GetHint("SDL_DEFAULT_WIDTH");
const char * hintHeight = SDL_GetHint("SDL_DEFAULT_HEIGHT"); const char * hintHeight = SDL_GetHint("SDL_DEFAULT_HEIGHT");
const char * hintFPS = SDL_GetHint("SDL_DEFAULT_FPS"); const char * hintFPS = SDL_GetHint("SDL_DEFAULT_FPS");
@@ -287,7 +286,6 @@ static bool OPENVR_VideoInit(SDL_VideoDevice *_this)
} else { } else {
openvr_vd_default.desktop_mode.refresh_rate = data->oSystem->GetFloatTrackedDeviceProperty(k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty_Prop_DisplayFrequency_Float, 0); openvr_vd_default.desktop_mode.refresh_rate = data->oSystem->GetFloatTrackedDeviceProperty(k_unTrackedDeviceIndex_Hmd, ETrackedDeviceProperty_Prop_DisplayFrequency_Float, 0);
} }
}
openvr_vd_default.internal = (SDL_DisplayData *)data; openvr_vd_default.internal = (SDL_DisplayData *)data;
openvr_vd_default.name = (char*)"OpenVRDisplay"; openvr_vd_default.name = (char*)"OpenVRDisplay";
@@ -306,7 +304,19 @@ static void OPENVR_VideoQuit(SDL_VideoDevice *_this)
static void OPENVR_Destroy(SDL_VideoDevice *device) static void OPENVR_Destroy(SDL_VideoDevice *device)
{ {
// Don't need to destroy and free internal, since it is already done in SDL_VideoQuit SDL_VideoData *data = device->internal;
#ifdef SDL_PLATFORM_WINDOWS
SDL_UnregisterApp();
#endif
if (data) {
if (data->openVRLIB) {
SDL_UnloadObject(data->openVRLIB);
}
}
SDL_free(device->internal);
SDL_free(device);
} }
static uint32_t *ImageSDLToOpenVRGL(SDL_Surface * surf, bool bFlipY) static uint32_t *ImageSDLToOpenVRGL(SDL_Surface * surf, bool bFlipY)
@@ -1552,10 +1562,13 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
data = NULL; data = NULL;
} }
if (!data) { if (!data) {
#ifdef SDL_PLATFORM_WINDOWS
SDL_UnregisterApp();
#endif
SDL_free(device); SDL_free(device);
SDL_OutOfMemory();
return NULL; return NULL;
} }
device->internal = data;
{ {
const char * hint = SDL_GetHint(SDL_HINT_OPENVR_LIBRARY); const char * hint = SDL_GetHint(SDL_HINT_OPENVR_LIBRARY);
@@ -1570,16 +1583,18 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
#endif #endif
} }
if (data->openVRLIB) { if (!data->openVRLIB) {
SDL_SetError("Could not open OpenVR API Library");
goto error;
}
data->FN_VR_InitInternal = (intptr_t(*)(EVRInitError * peError, EVRApplicationType eType))SDL_LoadFunction(data->openVRLIB, "VR_InitInternal"); data->FN_VR_InitInternal = (intptr_t(*)(EVRInitError * peError, EVRApplicationType eType))SDL_LoadFunction(data->openVRLIB, "VR_InitInternal");
data->FN_VR_GetVRInitErrorAsEnglishDescription = (const char *(*)(EVRInitError error))SDL_LoadFunction(data->openVRLIB, "VR_GetVRInitErrorAsEnglishDescription"); data->FN_VR_GetVRInitErrorAsEnglishDescription = (const char *(*)(EVRInitError error))SDL_LoadFunction(data->openVRLIB, "VR_GetVRInitErrorAsEnglishDescription");
data->FN_VR_GetGenericInterface = (intptr_t (*)(const char *pchInterfaceVersion, EVRInitError * peError))SDL_LoadFunction(data->openVRLIB, "VR_GetGenericInterface"); data->FN_VR_GetGenericInterface = (intptr_t (*)(const char *pchInterfaceVersion, EVRInitError * peError))SDL_LoadFunction(data->openVRLIB, "VR_GetGenericInterface");
} else { if (!data->FN_VR_InitInternal || !data->FN_VR_GetVRInitErrorAsEnglishDescription || !data->FN_VR_GetGenericInterface) {
SDL_SetError("Could not open OpenVR API Library"); goto error;
return NULL;
} }
if (data->FN_VR_InitInternal) {
char fnname[128]; char fnname[128];
EVRInitError e; EVRInitError e;
data->vrtoken = data->FN_VR_InitInternal(&e, EVRApplicationType_VRApplication_Overlay); data->vrtoken = data->FN_VR_InitInternal(&e, EVRApplicationType_VRApplication_Overlay);
@@ -1588,7 +1603,7 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
if (data->FN_VR_GetVRInitErrorAsEnglishDescription != NULL) if (data->FN_VR_GetVRInitErrorAsEnglishDescription != NULL)
err = data->FN_VR_GetVRInitErrorAsEnglishDescription(e); err = data->FN_VR_GetVRInitErrorAsEnglishDescription(e);
SDL_SetError("Could not generate OpenVR Context (%s)", err); SDL_SetError("Could not generate OpenVR Context (%s)", err);
return NULL; goto error;
} }
SDL_snprintf(fnname, 127, "FnTable:%s", IVRSystem_Version); SDL_snprintf(fnname, 127, "FnTable:%s", IVRSystem_Version);
@@ -1598,12 +1613,10 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
SDL_snprintf(fnname, 127, "FnTable:%s", IVRInput_Version); SDL_snprintf(fnname, 127, "FnTable:%s", IVRInput_Version);
data->oInput = (struct VR_IVRInput_FnTable *)data->FN_VR_GetGenericInterface(fnname, &e); data->oInput = (struct VR_IVRInput_FnTable *)data->FN_VR_GetGenericInterface(fnname, &e);
if (!data->oOverlay || !data->oSystem) { if (!data->oOverlay || !data->oSystem || !data->oInput) {
SDL_SetError("Could not get interfaces for the OpenVR System (%s), Overlay (%s) and Input (%s) versions", IVRSystem_Version, IVROverlay_Version, IVRInput_Version); SDL_SetError("Could not get interfaces for the OpenVR System (%s), Overlay (%s) and Input (%s) versions", IVRSystem_Version, IVROverlay_Version, IVRInput_Version);
} }
}
{
const char *hint = SDL_GetHint("SDL_OPENVR_INPUT_PROFILE"); const char *hint = SDL_GetHint("SDL_OPENVR_INPUT_PROFILE");
char *loadpath = 0; char *loadpath = 0;
EVRInputError err; EVRInputError err;
@@ -1614,9 +1627,8 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
const char *basepath = SDL_GetBasePath(); const char *basepath = SDL_GetBasePath();
SDL_asprintf(&loadpath, "%ssdloverlay_actions.json", basepath); SDL_asprintf(&loadpath, "%ssdloverlay_actions.json", basepath);
} }
if (!loadpath) { if (!loadpath) {
return NULL; goto error;
} }
err = data->oInput->SetActionManifestPath(loadpath); err = data->oInput->SetActionManifestPath(loadpath);
@@ -1631,20 +1643,14 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
// If we didn't have a hint, this is a soft fail. // If we didn't have a hint, this is a soft fail.
// If we did have the hint, then it's a hard fail. // If we did have the hint, then it's a hard fail.
if (hint) { if (hint) {
return NULL; goto error;
} }
} } else {
else
{
int e = OPENVR_SetupJoystckBasedOnLoadedActionManifest(data); int e = OPENVR_SetupJoystckBasedOnLoadedActionManifest(data);
if(e) { if(e) {
return NULL; goto error;
} }
} }
}
device->internal = data;
device->wakeup_lock = SDL_CreateMutex();
// Setup amount of available displays // Setup amount of available displays
device->num_displays = 0; device->num_displays = 0;
@@ -1722,6 +1728,10 @@ static SDL_VideoDevice *OPENVR_CreateDevice(void)
device->SetWindowIcon = OPENVR_SetWindowIcon; device->SetWindowIcon = OPENVR_SetWindowIcon;
return device; return device;
error:
OPENVR_Destroy(device);
return NULL;
} }
VideoBootStrap OPENVR_bootstrap = { VideoBootStrap OPENVR_bootstrap = {