Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ endif()

if(LOVR_BUILD_WITH_SYMBOLS)
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET "default")
if(WIN32)
set_target_properties(lovr PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
else()
set_target_properties(lovr PROPERTIES C_VISIBILITY_PRESET "hidden")
endif()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Contributors
- [@porglezomp](https://github.com/porglezomp)
- [@jmiskovic](https://github.com/jmiskovic)
- [@wallbraker](https://github.com/wallbraker)
- NVIDIA Corporation & Affiliates

License
---
Expand Down
33 changes: 31 additions & 2 deletions src/api/l_headset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,15 +1126,44 @@ int luaopen_lovr_headset(lua_State* L) {
lua_call(L, 2, 1);
size_t length;
const char* string = lua_tolstring(L, -1, &length);
char* extensions = lovrMalloc(length);
memcpy(extensions, string, length);
char* extensions = lovrMalloc(length + 1);
memcpy(extensions, string, length + 1);
config.extensionCount = count;
config.extensions = extensions;
}
lua_pop(L, 2);
}
}
lua_pop(L, 1);

lua_getfield(L, -1, "initproperties");
if (lua_istable(L, -1)) {
int count = luax_len(L, -1);
if (count > 0) {
InitProperty* properties = lovrMalloc(count * sizeof(InitProperty));
for (int i = 0; i < count; i++) {
lua_rawgeti(L, -1, i + 1);
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "name");
const char* name = lua_tostring(L, -1);
properties[i].name = name ? lovrStrdup(name) : NULL;
lua_pop(L, 1);

lua_getfield(L, -1, "value");
const char* value = lua_tostring(L, -1);
properties[i].value = value ? lovrStrdup(value) : NULL;
lua_pop(L, 1);
} else {
properties[i].name = NULL;
properties[i].value = NULL;
}
lua_pop(L, 1);
}
config.initPropertyCount = count;
config.initProperties = properties;
}
}
lua_pop(L, 1);
}
lua_pop(L, 1);
}
Expand Down
57 changes: 48 additions & 9 deletions src/modules/headset/headset.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,13 @@ static bool loadVisibilityMask(void);
bool lovrHeadsetInit(HeadsetConfig* config) {
if (state.initialized) {
lovrFree(config->extensions);
if (config->initProperties) {
for (uint32_t i = 0; i < config->initPropertyCount; i++) {
lovrFree(config->initProperties[i].name);
lovrFree(config->initProperties[i].value);
}
lovrFree(config->initProperties);
}
return true;
}

Expand Down Expand Up @@ -397,6 +404,13 @@ bool lovrHeadsetInit(HeadsetConfig* config) {
void lovrHeadsetDestroy(void) {
disconnect();
lovrFree(state.config.extensions);
if (state.config.initProperties) {
for (uint32_t i = 0; i < state.config.initPropertyCount; i++) {
lovrFree(state.config.initProperties[i].name);
lovrFree(state.config.initProperties[i].value);
}
lovrFree(state.config.initProperties);
}
Simulator simulator = state.simulator; // Keep simulator state between restarts, for convenience
memset(&state, 0, sizeof(state));
state.simulator = simulator;
Expand Down Expand Up @@ -437,6 +451,37 @@ bool lovrHeadsetConnect(void) {
}
#endif

// Initialize loader with properties (for custom runtime paths, etc.)
#if defined(__linux__) || defined(__APPLE__) || defined(_WIN32)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you have other code for Android so I targeted xrInitializeLoaderKHR to desktop platforms.

if (state.config.initPropertyCount > 0 && state.config.initProperties) {
static PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
XR_LOAD(xrInitializeLoaderKHR);
lovrAssert(xrInitializeLoaderKHR, "Failed to initialize loader");

// Build property list from config
XrLoaderInitPropertyValueEXT* propertyList = lovrMalloc(state.config.initPropertyCount * sizeof(XrLoaderInitPropertyValueEXT));
for (uint32_t i = 0; i < state.config.initPropertyCount; i++) {
propertyList[i].name = state.config.initProperties[i].name;
propertyList[i].value = state.config.initProperties[i].value;
}

XrLoaderInitInfoPropertiesEXT loaderProperties = {
.type = XR_TYPE_LOADER_INIT_INFO_PROPERTIES_EXT,
.next = NULL,
.propertyValueCount = state.config.initPropertyCount,
.propertyValues = propertyList
};

XrResult initResult = xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*) &loaderProperties);
lovrFree(propertyList);

if (XR_FAILED(initResult)) {
lovrLog(LOG_ERROR, "OpenXR", "Failed to initialize loader with properties: %d", initResult);
return false;
}
}
#endif

// Extensions

uint32_t extensionCount = 0;
Expand Down Expand Up @@ -4169,20 +4214,14 @@ static bool loadVisibilityMask(void) {
return true;
}

#ifdef _WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __attribute__((visibility("default")))
#endif

EXPORT uintptr_t xr_get_instance(void) {
LOVR_API uintptr_t xr_get_instance(void) {
return (uintptr_t) state.instance;
}

EXPORT uintptr_t xr_get_system(void) {
LOVR_API uintptr_t xr_get_system(void) {
return (uintptr_t) state.system;
}

EXPORT uintptr_t xr_get_session(void) {
LOVR_API uintptr_t xr_get_session(void) {
return (uintptr_t) state.session;
}
23 changes: 23 additions & 0 deletions src/modules/headset/headset.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

#pragma once

// API export/import macro for plugin functions
#ifdef _WIN32
#ifdef LOVR_API_IMPORT
#define LOVR_API __declspec(dllimport)
#else
#define LOVR_API __declspec(dllexport)
#endif
#else
#define LOVR_API __attribute__((visibility("default")))
#endif

#define HAND_JOINT_COUNT 26
#define MAX_LAYERS 10

Expand All @@ -20,6 +31,11 @@ typedef enum {
SKELETON_NATURAL
} ControllerSkeletonMode;

typedef struct {
char* name;
char* value;
} InitProperty;

typedef struct {
float supersample;
bool debug;
Expand All @@ -33,6 +49,8 @@ typedef struct {
ControllerSkeletonMode controllerSkeleton;
uint32_t extensionCount;
char* extensions;
uint32_t initPropertyCount;
InitProperty* initProperties;
} HeadsetConfig;

typedef struct {
Expand Down Expand Up @@ -252,3 +270,8 @@ bool lovrHeadsetIsSupported(void);
void lovrHeadsetGetVulkanPhysicalDevice(void* instance, uintptr_t physicalDevice);
uint32_t lovrHeadsetCreateVulkanInstance(void* instanceCreateInfo, void* allocator, uintptr_t instance, void* getInstanceProcAddr);
uint32_t lovrHeadsetCreateVulkanDevice(void* instance, void* deviceCreateInfo, void* allocatoor, uintptr_t device, void* getInstanceProcAddr);

// OpenXR handle accessors (for plugins)
LOVR_API uintptr_t xr_get_instance(void);
LOVR_API uintptr_t xr_get_system(void);
LOVR_API uintptr_t xr_get_session(void);