Atlas - SDL_gpu_openxr.c
Home / ext / SDL / src / gpu / xr Lines: 1 | Size: 9055 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21 22#include "SDL_internal.h" 23 24#ifdef HAVE_GPU_OPENXR 25 26#include "SDL_gpu_openxr.h" 27 28#ifdef SDL_PLATFORM_ANDROID 29#include "../../core/android/SDL_android.h" 30#endif 31 32#define VALIDATION_LAYER_API_NAME "XR_APILAYER_LUNARG_core_validation" 33 34/* On Android, the OpenXR loader is initialized by SDL_OpenXR_LoadLibrary() in SDL_openxrdyn.c 35 * which must be called before this. That function handles the complex initialization using 36 * direct SDL_LoadFunction calls to avoid issues with xrGetInstanceProcAddr from runtime 37 * negotiation not supporting pre-instance calls. This stub is kept for API compatibility. */ 38#ifdef SDL_PLATFORM_ANDROID 39static bool SDL_OPENXR_INTERNAL_InitializeAndroidLoader(void) 40{ 41 /* The loader should already be initialized by SDL_OpenXR_LoadLibrary(). 42 * We just verify that xrGetInstanceProcAddr is available. */ 43 if (xrGetInstanceProcAddr == NULL) { 44 SDL_LogError(SDL_LOG_CATEGORY_GPU, "xrGetInstanceProcAddr is NULL - SDL_OpenXR_LoadLibrary was not called first"); 45 return false; 46 } 47 SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Android OpenXR loader verified (was initialized by SDL_OpenXR_LoadLibrary)"); 48 return true; 49} 50#endif /* SDL_PLATFORM_ANDROID */ 51 52static bool SDL_OPENXR_INTERNAL_ValidationLayerAvailable(void) 53{ 54#ifdef SDL_PLATFORM_ANDROID 55 /* On Android/Quest, the xrGetInstanceProcAddr obtained through runtime negotiation 56 * crashes when used for pre-instance global functions. Skip validation layer check. */ 57 return false; 58#else 59 60 Uint32 apiLayerCount; 61 if (XR_FAILED(xrEnumerateApiLayerProperties(0, &apiLayerCount, NULL))) { 62 return false; 63 } 64 65 if (apiLayerCount <= 0) { 66 return false; 67 } 68 69 XrApiLayerProperties *apiLayerProperties = SDL_stack_alloc(XrApiLayerProperties, apiLayerCount); 70 if (XR_FAILED(xrEnumerateApiLayerProperties(apiLayerCount, &apiLayerCount, apiLayerProperties))) { 71 SDL_stack_free(apiLayerProperties); 72 return false; 73 } 74 75 bool found = false; 76 for (Uint32 i = 0; i < apiLayerCount; i++) { 77 XrApiLayerProperties apiLayer = apiLayerProperties[i]; 78 SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "api layer available: %s", apiLayer.layerName); 79 if (SDL_strcmp(apiLayer.layerName, VALIDATION_LAYER_API_NAME) == 0) { 80 found = true; 81 break; 82 } 83 } 84 85 SDL_stack_free(apiLayerProperties); 86 return found; 87#endif 88} 89 90XrResult SDL_OPENXR_INTERNAL_GPUInitOpenXR( 91 bool debugMode, 92 XrExtensionProperties gpuExtension, 93 SDL_PropertiesID props, 94 XrInstance *instance, 95 XrSystemId *systemId, 96 XrInstancePfns **xr) 97{ 98 XrResult xrResult; 99 100#ifdef SDL_PLATFORM_ANDROID 101 // Android requires loader initialization before any other XR calls 102 if (!SDL_OPENXR_INTERNAL_InitializeAndroidLoader()) { 103 SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to initialize Android OpenXR loader"); 104 return XR_ERROR_INITIALIZATION_FAILED; 105 } 106#endif 107 108 bool validationLayersAvailable = SDL_OPENXR_INTERNAL_ValidationLayerAvailable(); 109 110 Uint32 userApiLayerCount = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_COUNT_NUMBER, 0); 111 const char *const *userApiLayerNames = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_LAYER_NAMES_POINTER, NULL); 112 113 Uint32 userExtensionCount = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_COUNT_NUMBER, 0); 114 const char *const *userExtensionNames = SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_EXTENSION_NAMES_POINTER, NULL); 115 116 // allocate enough space for the validation layer + the user's api layers 117 const char **apiLayerNames = SDL_stack_alloc(const char *, userApiLayerCount + 1); 118 SDL_memcpy((void *)apiLayerNames, userApiLayerNames, sizeof(const char *) * (userApiLayerCount)); 119 apiLayerNames[userApiLayerCount] = VALIDATION_LAYER_API_NAME; 120 121 // On Android, we need an extra extension for android_create_instance 122#ifdef SDL_PLATFORM_ANDROID 123 const Uint32 platformExtensionCount = 2; // GPU extension + Android create instance 124#else 125 const Uint32 platformExtensionCount = 1; // GPU extension only 126#endif 127 128 const char **extensionNames = SDL_stack_alloc(const char *, userExtensionCount + platformExtensionCount); 129 SDL_memcpy((void *)extensionNames, userExtensionNames, sizeof(const char *) * (userExtensionCount)); 130 extensionNames[userExtensionCount] = gpuExtension.extensionName; 131#ifdef SDL_PLATFORM_ANDROID 132 extensionNames[userExtensionCount + 1] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME; 133#endif 134 135 XrInstanceCreateInfo xrInstanceCreateInfo; 136 SDL_zero(xrInstanceCreateInfo); 137 xrInstanceCreateInfo.type = XR_TYPE_INSTANCE_CREATE_INFO; 138 xrInstanceCreateInfo.applicationInfo.apiVersion = SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_VERSION_NUMBER, XR_API_VERSION_1_0); 139 xrInstanceCreateInfo.enabledApiLayerCount = userApiLayerCount + ((debugMode && validationLayersAvailable) ? 1 : 0); // in debug mode, we enable the validation layer 140 xrInstanceCreateInfo.enabledApiLayerNames = apiLayerNames; 141 xrInstanceCreateInfo.enabledExtensionCount = userExtensionCount + platformExtensionCount; 142 xrInstanceCreateInfo.enabledExtensionNames = extensionNames; 143 144#ifdef SDL_PLATFORM_ANDROID 145 // Get JNI environment and JavaVM for Android instance creation 146 JNIEnv *env = (JNIEnv *)SDL_GetAndroidJNIEnv(); 147 JavaVM *vm = NULL; 148 if (env) { 149 (*env)->GetJavaVM(env, &vm); 150 } 151 void *activity = SDL_GetAndroidActivity(); 152 153 XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {}; 154 instanceCreateInfoAndroid.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR; 155 instanceCreateInfoAndroid.applicationVM = vm; 156 instanceCreateInfoAndroid.applicationActivity = activity; 157 xrInstanceCreateInfo.next = &instanceCreateInfoAndroid; 158#endif 159 160 const char *applicationName = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_NAME_STRING, "SDL Application"); 161 Uint32 applicationVersion = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_APPLICATION_VERSION_NUMBER, 0); 162 163 SDL_strlcpy(xrInstanceCreateInfo.applicationInfo.applicationName, applicationName, XR_MAX_APPLICATION_NAME_SIZE); 164 xrInstanceCreateInfo.applicationInfo.applicationVersion = applicationVersion; 165 166 const char *engineName = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_NAME_STRING, "SDLGPU"); 167 uint32_t engineVersion = (uint32_t)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_ENGINE_VERSION_NUMBER, SDL_VERSION); 168 169 SDL_strlcpy(xrInstanceCreateInfo.applicationInfo.engineName, engineName, XR_MAX_APPLICATION_NAME_SIZE); 170 xrInstanceCreateInfo.applicationInfo.engineVersion = engineVersion; 171 172 if ((xrResult = xrCreateInstance(&xrInstanceCreateInfo, instance)) != XR_SUCCESS) { 173 SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to create OpenXR instance"); 174 SDL_stack_free(apiLayerNames); 175 SDL_stack_free(extensionNames); 176 return false; 177 } 178 179 SDL_stack_free(apiLayerNames); 180 SDL_stack_free(extensionNames); 181 182 *xr = SDL_OPENXR_LoadInstanceSymbols(*instance); 183 if (!*xr) { 184 SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to load required OpenXR instance symbols"); 185 /* NOTE: we can't actually destroy the created OpenXR instance here, 186 as we only get that function pointer by loading the instance symbols... 187 let's just hope that doesn't happen. */ 188 return false; 189 } 190 191 XrSystemGetInfo systemGetInfo; 192 SDL_zero(systemGetInfo); 193 systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO; 194 systemGetInfo.formFactor = (XrFormFactor)SDL_GetNumberProperty(props, SDL_PROP_GPU_DEVICE_CREATE_XR_FORM_FACTOR_NUMBER, XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY); 195 if ((xrResult = (*xr)->xrGetSystem(*instance, &systemGetInfo, systemId)) != XR_SUCCESS) { 196 SDL_LogDebug(SDL_LOG_CATEGORY_GPU, "Failed to get OpenXR system"); 197 (*xr)->xrDestroyInstance(*instance); 198 SDL_free(*xr); 199 return false; 200 } 201 202 return true; 203} 204 205#endif /* HAVE_GPU_OPENXR */ 206[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.