From 38f603d7bf0580ffc9c21b4b09a03cea463ab41d Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Wed, 30 Dec 2020 13:35:28 -0600 Subject: [PATCH] wineopenxr: Add openxr support --- .gitmodules | 3 + Makefile | 5 + OpenXR-SDK | 1 + build/makefile_base.mak | 131 +- proton | 3 + wine | 2 +- wineopenxr/dxvk-interop.h | 362 +++++ wineopenxr/loader_structs.h | 30 + wineopenxr/make_openxr | 2893 ++++++++++++++++++++++++++++++++++ wineopenxr/openxr.c | 1441 +++++++++++++++++ wineopenxr/openxr_private.h | 85 + wineopenxr/openxr_thunks.c | 561 +++++++ wineopenxr/openxr_thunks.h | 212 +++ wineopenxr/wineopenxr.h | 1957 +++++++++++++++++++++++ wineopenxr/wineopenxr.spec | 3 + wineopenxr/wineopenxr64.json | 6 + 16 files changed, 7690 insertions(+), 5 deletions(-) create mode 160000 OpenXR-SDK create mode 100644 wineopenxr/dxvk-interop.h create mode 100644 wineopenxr/loader_structs.h create mode 100755 wineopenxr/make_openxr create mode 100644 wineopenxr/openxr.c create mode 100644 wineopenxr/openxr_private.h create mode 100644 wineopenxr/openxr_thunks.c create mode 100644 wineopenxr/openxr_thunks.h create mode 100644 wineopenxr/wineopenxr.h create mode 100644 wineopenxr/wineopenxr.spec create mode 100644 wineopenxr/wineopenxr64.json diff --git a/.gitmodules b/.gitmodules index 9a4eef3b..41e09459 100644 --- a/.gitmodules +++ b/.gitmodules @@ -28,3 +28,6 @@ [submodule "vkd3d-proton"] path = vkd3d-proton url = https://github.com/HansKristian-Work/vkd3d-proton +[submodule "OpenXR-SDK"] + path = OpenXR-SDK + url = https://github.com/KhronosGroup/OpenXR-SDK diff --git a/Makefile b/Makefile index ab6fe63f..220fe918 100644 --- a/Makefile +++ b/Makefile @@ -172,3 +172,8 @@ vrclient: configure vagrant ssh -c 'make -C $(BUILD_DIR)/ $(UNSTRIPPED) $(CCACHE_FLAG) vrclient && \ cp -f $(BUILD_DIR)/dist/dist/lib/wine/vrclient.dll.so /vagrant/vrclient/lib/wine && \ cp -f $(BUILD_DIR)/dist/dist/lib64/wine/vrclient_x64.dll.so /vagrant/vrclient/lib64/wine' + +wineopenxr: configure + mkdir -p vagrant_share/wineopenxr/lib64/wine + vagrant ssh -c 'make -C $(BUILD_DIR)/ $(UNSTRIPPED) $(CCACHE_FLAG) wineopenxr && \ + cp -f $(BUILD_DIR)/dist/dist/lib64/wine/wineopenxr.dll.so /vagrant/wineopenxr/lib64/wine' diff --git a/OpenXR-SDK b/OpenXR-SDK new file mode 160000 index 00000000..5197afbf --- /dev/null +++ b/OpenXR-SDK @@ -0,0 +1 @@ +Subproject commit 5197afbf199c026eca82a47a8573ed10b0c6fa4e diff --git a/build/makefile_base.mak b/build/makefile_base.mak index 6acce47a..8d2554bc 100644 --- a/build/makefile_base.mak +++ b/build/makefile_base.mak @@ -238,6 +238,15 @@ LSTEAMCLIENT64 := ./syn-lsteamclient64/lsteamclient LSTEAMCLIENT_OBJ32 := ./obj-lsteamclient32 LSTEAMCLIENT_OBJ64 := ./obj-lsteamclient64 +WINEOPENXR := $(SRCDIR)/wineopenxr +WINEOPENXR64 := ./syn-wineopenxr64/wineopenxr +WINEOPENXR_OBJ64 := ./obj-wineopenxr64 +WINEOPENXR_JSON64 := $(SRCDIR)/wineopenxr/wineopenxr64.json +WINEOPENXR_FAKEDLL64 := $(WINEOPENXR_OBJ64)/wineopenxr.dll.fake + +OPENXR := $(SRCDIR)/OpenXR-SDK +OPENXR_OBJ64 := ./obj-openxr64 + STEAMEXE_SRC := $(SRCDIR)/steam_helper STEAMEXE_OBJ := ./obj-steam STEAMEXE_SYN := ./syn-steam/steam @@ -289,6 +298,8 @@ OBJ_DIRS := $(TOOLS_DIR32) $(TOOLS_DIR64) \ $(FAUDIO_OBJ32) $(FAUDIO_OBJ64) \ $(JXRLIB_OBJ32) $(JXRLIB_OBJ64) \ $(LSTEAMCLIENT_OBJ32) $(LSTEAMCLIENT_OBJ64) \ + $(WINEOPENXR_OBJ64) \ + $(OPENXR_OBJ64) \ $(STEAMEXE_OBJ) \ $(WINE_OBJ32) $(WINE_OBJ64) \ $(VRCLIENT_OBJ32) $(VRCLIENT_OBJ64) \ @@ -366,6 +377,8 @@ DIST_GECKO64 := $(DIST_GECKO_DIR)/wine-gecko-$(GECKO_VER)-x86_64 DIST_WINEMONO_DIR := $(DST_DIR)/share/wine/mono DIST_WINEMONO := $(DIST_WINEMONO_DIR)/wine-mono-$(WINEMONO_VER) DIST_FONTS := $(DST_DIR)/share/fonts +DIST_WINEOPENXR_JSON64 := $(DIST_PREFIX)/drive_c/openxr/wineopenxr64.json +DIST_WINEOPENXR64 := $(DIST_PREFIX)/drive_c/windows/system32/wineopenxr.dll DIST_TARGETS := $(DIST_COPY_TARGETS) $(DIST_OVR32) $(DIST_OVR64) \ $(DIST_GECKO32) $(DIST_GECKO64) $(DIST_WINEMONO) \ @@ -444,19 +457,31 @@ $(DIST_FONTS): fonts cp $(FONTS_OBJ)/*.ttf "$@" cp $(FONTS_OBJ)/*.otf "$@" +$(DIST_WINEOPENXR_JSON64): $(WINEOPENXR_JSON64) + mkdir -p $(dir $@) + cp -a $< $@ + +$(DIST_WINEOPENXR64): wineopenxr64 + mkdir -p $(dir $@) + cp -a $(WINEOPENXR_FAKEDLL64) $@ + .PHONY: dist ALL_TARGETS += dist GOAL_TARGETS += dist -dist: $(DIST_TARGETS) wine gst_good vrclient lsteamclient steam dxvk vkd3d-proton mediaconv | $(DST_DIR) - echo `date '+%s'` `GIT_DIR=$(abspath $(SRCDIR)/.git) git describe --tags` > $(DIST_VERSION) - cp $(DIST_VERSION) $(DST_BASE)/ +dist_prefix: wine gst_good find $(DST_DIR)/lib/wine -type f -execdir chmod a-w '{}' '+' find $(DST_DIR)/lib64/wine -type f -execdir chmod a-w '{}' '+' rm -rf $(abspath $(DIST_PREFIX)) python3 $(SRCDIR)/default_pfx.py $(abspath $(DIST_PREFIX)) $(abspath $(DST_DIR)) $(STEAM_RUNTIME_RUNSH) +dist_wineopenxr: dist_prefix $(DIST_WINEOPENXR_JSON64) $(DIST_WINEOPENXR64) + +dist: $(DIST_TARGETS) vrclient lsteamclient wineopenxr steam dxvk vkd3d-proton mediaconv dist_wineopenxr | $(DST_DIR) + echo `date '+%s'` `GIT_DIR=$(abspath $(SRCDIR)/.git) git describe --tags` > $(DIST_VERSION) + cp $(DIST_VERSION) $(DST_BASE)/ + deploy: dist | $(filter-out dist deploy install redist,$(MAKECMDGOALS)) mkdir -p $(DEPLOY_DIR) && \ cp -a $(DEPLOY_COPY_TARGETS) $(DEPLOY_DIR) && \ @@ -1052,6 +1077,104 @@ lsteamclient32: $(LSTEAMCLIENT_CONFIGURE_FILES32) | $(WINE_BUILDTOOLS32) $(filte mkdir -pv $(DST_DIR)/lib/wine/ cp -af $(LSTEAMCLIENT_OBJ32)/lsteamclient.dll.so $(DST_DIR)/lib/wine/ + +## +## openxr +## Note 32-bit is not supported by SteamVR, so we don't build it. +## + +OPENXR_CMAKE_FLAGS = -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_LIBDIR="lib" + +OPENXR_TARGETS = openxr openxr64 + +ALL_TARGETS += $(OPENXR_TARGETS) +GOAL_TARGETS_LIBS += openxr + +.PHONY: openxr openxr64 + +openxr: openxr64 + +OPENXR_CONFIGURE_FILES64 := $(OPENXR_OBJ64)/Makefile + +$(OPENXR_CONFIGURE_FILES64): SHELL = $(CONTAINER_SHELL64) +$(OPENXR_CONFIGURE_FILES64): $(OPENXR)/CMakeLists.txt $(MAKEFILE_DEP) | $(OPENXR_OBJ64) + cd $(dir $@) && \ + CFLAGS="$(OPTIMIZE_FLAGS)" \ + cmake $(abspath $(OPENXR)) \ + -DCMAKE_INSTALL_PREFIX="$(abspath $(TOOLS_DIR64))" \ + $(OPENXR_CMAKE_FLAGS) + +openxr64: SHELL = $(CONTAINER_SHELL64) +openxr64: $(OPENXR_CONFIGURE_FILES64) + +$(MAKE) -C $(OPENXR_OBJ64) VERBOSE=1 + +$(MAKE) -C $(OPENXR_OBJ64) install VERBOSE=1 + mkdir -p $(DST_DIR)/lib64 + cp -a $(TOOLS_DIR64)/lib/libopenxr_loader* $(DST_DIR)/lib64/ + [ x"$(STRIP)" = x ] || $(STRIP) $(DST_DIR)/lib64/libopenxr_loader.so + +## +## wineopenxr +## Note 32-bit is not supported by SteamVR, so we don't build it. +## + +# The source directory for wineopenxr is a synthetic symlink clone of the source directory, because we need to run +# winemaker in tree and it can stomp itself in parallel builds. +$(WINEOPENXR64)/.created: $(WINEOPENXR) $(MAKEFILE_DEP) + rm -rf ./$(WINEOPENXR64) + mkdir -p $(WINEOPENXR64)/ + cd $(WINEOPENXR64)/ && ln -sfv ../../$(WINEOPENXR)/* . + touch $@ + +$(WINEOPENXR64): $(WINEOPENXR64)/.created + +## Create & configure object directory for wineopenxr + +WINEOPENXR_CONFIGURE_FILES64 := $(WINEOPENXR_OBJ64)/Makefile + +# 64bit-configure +$(WINEOPENXR_CONFIGURE_FILES64): SHELL = $(CONTAINER_SHELL64) +$(WINEOPENXR_CONFIGURE_FILES64): $(WINEOPENXR64) $(MAKEFILE_DEP) | $(WINEOPENXR_OBJ64) $(WINEMAKER) + cd $(dir $@) && \ + $(WINEMAKER) --nosource-fix --nolower-include --nodlls --nomsvcrt \ + -I"../$(TOOLS_DIR64)"/include/ \ + -I"../$(TOOLS_DIR64)"/include/wine/ \ + -I"../$(TOOLS_DIR64)"/include/wine/windows/ \ + -I"../$(WINE)"/include/ \ + -I"$(abspath $(OPENXR))"/include/ \ + -L"../$(TOOLS_DIR64)"/lib/ \ + -l"openxr_loader" \ + -l"dxgi" \ + -l"vulkan" \ + --dll ../$(WINEOPENXR64) && \ + cp ../$(WINEOPENXR64)/Makefile . && \ + echo >> ./Makefile 'SRCDIR := ../$(WINEOPENXR64)' && \ + echo >> ./Makefile 'vpath % $$(SRCDIR)' && \ + echo >> ./Makefile 'wineopenxr_dll_LDFLAGS := -ldl $$(patsubst %.spec,$$(SRCDIR)/%.spec,$$(wineopenxr_dll_LDFLAGS))' + +# -L"../$(TOOLS_DIR64)"/lib64/wine/ \ +## wineopenxr goals +WINEOPENXR_TARGETS = wineopenxr wineopenxr_configure wineopenxr64 wineopenxr_configure64 + +ALL_TARGETS += $(WINEOPENXR_TARGETS) +GOAL_TARGETS_LIBS += wineopenxr + +.PHONY: $(WINEOPENXR_TARGETS) + +wineopenxr_configure: $(WINEOPENXR_CONFIGURE_FILES64) + +wineopenxr_configure64: $(WINEOPENXR_CONFIGURE_FILES64) + +wineopenxr: wineopenxr64 + +wineopenxr64: SHELL = $(CONTAINER_SHELL64) +wineopenxr64: $(WINEOPENXR_CONFIGURE_FILES64) openxr64 | $(WINE_BUILDTOOLS64) $(filter $(MAKECMDGOALS),wine64 wine32 wine) + +env PATH="$(abspath $(TOOLS_DIR64))/bin:$(PATH)" CFLAGS="$(COMMON_FLAGS) -g" \ + $(MAKE) -C $(WINEOPENXR_OBJ64) + $(TOOLS_DIR64)/bin/winebuild -m64 --dll --fake-module -E $(abspath $(WINEOPENXR))/wineopenxr.spec -o $(WINEOPENXR_OBJ64)/wineopenxr.dll.fake + [ x"$(STRIP)" = x ] || $(STRIP) $(WINEOPENXR_OBJ64)/wineopenxr.dll.so + mkdir -pv $(DST_DIR)/lib64/wine/ + cp -af $(WINEOPENXR_OBJ64)/wineopenxr.dll.so $(DST_DIR)/lib64/wine/ + ## steam.exe $(STEAMEXE_SYN)/.created: $(STEAMEXE_SRC) $(MAKEFILE_DEP) @@ -1322,7 +1445,7 @@ DXVK_CONFIGURE_FILES32 := $(DXVK_OBJ32)/build.ninja DXVK_CONFIGURE_FILES64 := $(DXVK_OBJ64)/build.ninja # 64bit-configure. Remove coredata file if already configured (due to e.g. makefile changing) -$(DXVK_CONFIGURE_FILES64): $(MAKEFILE_DEP) $(DXVK)/build-win64.txt | $(DXVK_OBJ64) +$(DXVK_CONFIGURE_FILES64): $(MAKEFILE_DEP) $(DXVK)/build-win64.txt wineopenxr64 | $(DXVK_OBJ64) if [ -e "$(abspath $(DXVK_OBJ64))"/build.ninja ]; then \ rm -f "$(abspath $(DXVK_OBJ64))"/meson-private/coredata.dat; \ fi diff --git a/proton b/proton index 4d6e551d..2745753f 100755 --- a/proton +++ b/proton @@ -540,6 +540,9 @@ class CompatData: try_copy(g_proton.lib_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/syswow64/") try_copy(g_proton.lib64_dir + "wine/dxvk/openvr_api_dxvk.dll", self.prefix_dir + "/drive_c/windows/system32/") + makedirs(self.prefix_dir + "/drive_c/openxr/") + try_copy(g_proton.default_pfx_dir + "drive_c/openxr/wineopenxr64.json", self.prefix_dir + "/drive_c/openxr/") + if use_wined3d: dxvkfiles = ["dxvk_config"] wined3dfiles = ["d3d11", "d3d10", "d3d10core", "d3d10_1", "d3d9"] diff --git a/wine b/wine index 7f9f4285..ee64c2b2 160000 --- a/wine +++ b/wine @@ -1 +1 @@ -Subproject commit 7f9f4285c2dfb81234c01996f6d33fae07701629 +Subproject commit ee64c2b291290753eefdca064b89ad86e2e6fcbe diff --git a/wineopenxr/dxvk-interop.h b/wineopenxr/dxvk-interop.h new file mode 100644 index 00000000..0871b91f --- /dev/null +++ b/wineopenxr/dxvk-interop.h @@ -0,0 +1,362 @@ +/*** Autogenerated by WIDL 3.5 from /home/yorha-2b/Valve/Proton/wine/include/wine/dxvk-interop.idl - Do not edit ***/ + +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include +#include + +#ifndef COM_NO_WINDOWS_H +#include +#include +#endif + +#ifndef __dxvk_interop_h__ +#define __dxvk_interop_h__ + +/* Forward declarations */ + +#ifndef __IDXGIVkInteropSurface_FWD_DEFINED__ +#define __IDXGIVkInteropSurface_FWD_DEFINED__ +typedef interface IDXGIVkInteropSurface IDXGIVkInteropSurface; +#ifdef __cplusplus +interface IDXGIVkInteropSurface; +#endif /* __cplusplus */ +#endif + +#ifndef __IDXGIVkInteropDevice_FWD_DEFINED__ +#define __IDXGIVkInteropDevice_FWD_DEFINED__ +typedef interface IDXGIVkInteropDevice IDXGIVkInteropDevice; +typedef interface IDXGIVkInteropDevice2 IDXGIVkInteropDevice2; +#ifdef __cplusplus +interface IDXGIVkInteropDevice; +interface IDXGIVkInteropDevice2; +#endif /* __cplusplus */ +#endif + +/* Headers for imported files */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************** + * IDXGIVkInteropSurface interface + */ +#ifndef __IDXGIVkInteropSurface_INTERFACE_DEFINED__ +#define __IDXGIVkInteropSurface_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IDXGIVkInteropSurface, 0x5546cf8c, 0x77e7, 0x4341, 0xb0,0x5d, 0x8d,0x4d,0x50,0x00,0xe7,0x7d); +#if defined(__cplusplus) && !defined(CINTERFACE) +MIDL_INTERFACE("5546cf8c-77e7-4341-b05d-8d4d5000e77d") +IDXGIVkInteropSurface : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetDevice( + IDXGIVkInteropDevice** ppDevice) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVulkanImageInfo( + VkImage *pHandle, + VkImageLayout *pLayout, + VkImageCreateInfo *pInfo) = 0; + +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IDXGIVkInteropSurface, 0x5546cf8c, 0x77e7, 0x4341, 0xb0,0x5d, 0x8d,0x4d,0x50,0x00,0xe7,0x7d) +#endif +#else +typedef struct IDXGIVkInteropSurfaceVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IDXGIVkInteropSurface *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IDXGIVkInteropSurface *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IDXGIVkInteropSurface *This); + + /*** IDXGIVkInteropSurface methods ***/ + HRESULT (STDMETHODCALLTYPE *GetDevice)( + IDXGIVkInteropSurface *This, + IDXGIVkInteropDevice **ppDevice); + + HRESULT (STDMETHODCALLTYPE *GetVulkanImageInfo)( + IDXGIVkInteropSurface *This, + VkImage *pHandle, + VkImageLayout *pLayout, + VkImageCreateInfo *pInfo); + + END_INTERFACE +} IDXGIVkInteropSurfaceVtbl; + +interface IDXGIVkInteropSurface { + CONST_VTBL IDXGIVkInteropSurfaceVtbl* lpVtbl; +}; + +#ifdef COBJMACROS +#ifndef WIDL_C_INLINE_WRAPPERS +/*** IUnknown methods ***/ +#define IDXGIVkInteropSurface_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IDXGIVkInteropSurface_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IDXGIVkInteropSurface_Release(This) (This)->lpVtbl->Release(This) +/*** IDXGIVkInteropSurface methods ***/ +#define IDXGIVkInteropSurface_GetVulkanImageInfo(This,pHandle,pLayout,pInfo) (This)->lpVtbl->GetVulkanImageInfo(This,pHandle,pLayout,pInfo) +#else +/*** IUnknown methods ***/ +static FORCEINLINE HRESULT IDXGIVkInteropSurface_QueryInterface(IDXGIVkInteropSurface* This,REFIID riid,void **ppvObject) { + return This->lpVtbl->QueryInterface(This,riid,ppvObject); +} +static FORCEINLINE ULONG IDXGIVkInteropSurface_AddRef(IDXGIVkInteropSurface* This) { + return This->lpVtbl->AddRef(This); +} +static FORCEINLINE ULONG IDXGIVkInteropSurface_Release(IDXGIVkInteropSurface* This) { + return This->lpVtbl->Release(This); +} +/*** IDXGIVkInteropSurface methods ***/ +static FORCEINLINE HRESULT IDXGIVkInteropSurface_GetVulkanImageInfo(IDXGIVkInteropSurface* This,VkImage *pHandle,VkImageLayout *pLayout,VkImageCreateInfo *pInfo) { + return This->lpVtbl->GetVulkanImageInfo(This,pHandle,pLayout,pInfo); +} +#endif +#endif + +#endif + + +#endif /* __IDXGIVkInteropSurface_INTERFACE_DEFINED__ */ + +/***************************************************************************** + * IDXGIVkInteropDevice interface + */ +#ifndef __IDXGIVkInteropDevice_INTERFACE_DEFINED__ +#define __IDXGIVkInteropDevice_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IDXGIVkInteropDevice, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x23); +DEFINE_GUID(IID_IDXGIVkInteropDevice2, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x24); +#if defined(__cplusplus) && !defined(CINTERFACE) +MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09323") +IDXGIVkInteropDevice : public IUnknown +{ + virtual void STDMETHODCALLTYPE GetVulkanHandles( + VkInstance *pInstance, + VkPhysicalDevice *pPhysDev, + VkDevice *pDevice) = 0; + + virtual void STDMETHODCALLTYPE GetSubmissionQueue( + VkQueue *pQueue, + uint32_t *pQueueFamilyIndex) = 0; + + virtual void STDMETHODCALLTYPE TransitionSurfaceLayout( + IDXGIVkInteropSurface *pSurface, + const VkImageSubresourceRange *pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout) = 0; + + virtual void STDMETHODCALLTYPE FlushRenderingCommands( + ) = 0; + + virtual void STDMETHODCALLTYPE LockSubmissionQueue( + ) = 0; + + virtual void STDMETHODCALLTYPE ReleaseSubmissionQueue( + ) = 0; + +}; +MIDL_INTERFACE("e2ef5fa5-dc21-4af7-90c4-f67ef6a09324") +IDXGIVkInteropDevice2 : public IDXGIVkInteropDevice +{ + virtual void STDMETHODCALLTYPE GetSubmissionQueue2( + VkQueue *pQueue, + uint32_t *pQueueIndex, + uint32_t *pQueueFamilyIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage( + const D3D11_TEXTURE2D_DESC1 *pDesc, + VkImage vkImage, + ID3D11Texture2D **ppTexture2D) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IDXGIVkInteropDevice, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x23) +__CRT_UUID_DECL(IDXGIVkInteropDevice2, 0xe2ef5fa5, 0xdc21, 0x4af7, 0x90,0xc4, 0xf6,0x7e,0xf6,0xa0,0x93,0x24) +#endif +#else +typedef struct IDXGIVkInteropDeviceVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IDXGIVkInteropDevice *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IDXGIVkInteropDevice *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IDXGIVkInteropDevice *This); + + /*** IDXGIVkInteropDevice methods ***/ + void (STDMETHODCALLTYPE *GetVulkanHandles)( + IDXGIVkInteropDevice *This, + VkInstance *pInstance, + VkPhysicalDevice *pPhysDev, + VkDevice *pDevice); + + void (STDMETHODCALLTYPE *GetSubmissionQueue)( + IDXGIVkInteropDevice *This, + VkQueue *pQueue, + uint32_t *pQueueFamilyIndex); + + void (STDMETHODCALLTYPE *TransitionSurfaceLayout)( + IDXGIVkInteropDevice *This, + IDXGIVkInteropSurface *pSurface, + const VkImageSubresourceRange *pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + void (STDMETHODCALLTYPE *FlushRenderingCommands)( + IDXGIVkInteropDevice *This); + + void (STDMETHODCALLTYPE *LockSubmissionQueue)( + IDXGIVkInteropDevice *This); + + void (STDMETHODCALLTYPE *ReleaseSubmissionQueue)( + IDXGIVkInteropDevice *This); + + END_INTERFACE +} IDXGIVkInteropDeviceVtbl; + +interface IDXGIVkInteropDevice { + CONST_VTBL IDXGIVkInteropDeviceVtbl* lpVtbl; +}; + +typedef struct IDXGIVkInteropDevice2Vtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IDXGIVkInteropDevice2 *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IDXGIVkInteropDevice2 *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IDXGIVkInteropDevice2 *This); + + /*** IDXGIVkInteropDevice methods ***/ + void (STDMETHODCALLTYPE *GetVulkanHandles)( + IDXGIVkInteropDevice2 *This, + VkInstance *pInstance, + VkPhysicalDevice *pPhysDev, + VkDevice *pDevice); + + void (STDMETHODCALLTYPE *GetSubmissionQueue)( + IDXGIVkInteropDevice2 *This, + VkQueue *pQueue, + uint32_t *pQueueFamilyIndex); + + void (STDMETHODCALLTYPE *TransitionSurfaceLayout)( + IDXGIVkInteropDevice2 *This, + IDXGIVkInteropSurface *pSurface, + const VkImageSubresourceRange *pSubresources, + VkImageLayout OldLayout, + VkImageLayout NewLayout); + + void (STDMETHODCALLTYPE *FlushRenderingCommands)( + IDXGIVkInteropDevice2 *This); + + void (STDMETHODCALLTYPE *LockSubmissionQueue)( + IDXGIVkInteropDevice2 *This); + + void (STDMETHODCALLTYPE *ReleaseSubmissionQueue)( + IDXGIVkInteropDevice2 *This); + + void (STDMETHODCALLTYPE *GetSubmissionQueue2)( + IDXGIVkInteropDevice2 *This, + VkQueue *pQueue, + uint32_t *pQueueIndex, + uint32_t *pQueueFamilyIndex); + + HRESULT (STDMETHODCALLTYPE *CreateTexture2DFromVkImage)( + IDXGIVkInteropDevice2 *This, + const D3D11_TEXTURE2D_DESC1 *pDesc, + VkImage vkImage, + ID3D11Texture2D **ppTexture2D); + + END_INTERFACE +} IDXGIVkInteropDevice2Vtbl; + +interface IDXGIVkInteropDevice2 { + CONST_VTBL IDXGIVkInteropDevice2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS +#ifndef WIDL_C_INLINE_WRAPPERS +/*** IUnknown methods ***/ +#define IDXGIVkInteropDevice_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IDXGIVkInteropDevice_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IDXGIVkInteropDevice_Release(This) (This)->lpVtbl->Release(This) +/*** IDXGIVkInteropDevice methods ***/ +#define IDXGIVkInteropDevice_GetVulkanHandles(This,pInstance,pPhysDev,pDevice) (This)->lpVtbl->GetVulkanHandles(This,pInstance,pPhysDev,pDevice) +#define IDXGIVkInteropDevice_GetSubmissionQueue(This,pQueue,pQueueFamilyIndex) (This)->lpVtbl->GetSubmissionQueue(This,pQueue,pQueueFamilyIndex) +#define IDXGIVkInteropDevice_TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout) (This)->lpVtbl->TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout) +#define IDXGIVkInteropDevice_FlushRenderingCommands(This) (This)->lpVtbl->FlushRenderingCommands(This) +#define IDXGIVkInteropDevice_LockSubmissionQueue(This) (This)->lpVtbl->LockSubmissionQueue(This) +#define IDXGIVkInteropDevice_ReleaseSubmissionQueue(This) (This)->lpVtbl->ReleaseSubmissionQueue(This) +#else +/*** IUnknown methods ***/ +static FORCEINLINE HRESULT IDXGIVkInteropDevice_QueryInterface(IDXGIVkInteropDevice* This,REFIID riid,void **ppvObject) { + return This->lpVtbl->QueryInterface(This,riid,ppvObject); +} +static FORCEINLINE ULONG IDXGIVkInteropDevice_AddRef(IDXGIVkInteropDevice* This) { + return This->lpVtbl->AddRef(This); +} +static FORCEINLINE ULONG IDXGIVkInteropDevice_Release(IDXGIVkInteropDevice* This) { + return This->lpVtbl->Release(This); +} +/*** IDXGIVkInteropDevice methods ***/ +static FORCEINLINE void IDXGIVkInteropDevice_GetVulkanHandles(IDXGIVkInteropDevice* This,VkInstance *pInstance,VkPhysicalDevice *pPhysDev,VkDevice *pDevice) { + This->lpVtbl->GetVulkanHandles(This,pInstance,pPhysDev,pDevice); +} +static FORCEINLINE void IDXGIVkInteropDevice_GetSubmissionQueue(IDXGIVkInteropDevice* This,VkQueue *pQueue,uint32_t *pQueueFamilyIndex) { + This->lpVtbl->GetSubmissionQueue(This,pQueue,pQueueFamilyIndex); +} +static FORCEINLINE void IDXGIVkInteropDevice_TransitionSurfaceLayout(IDXGIVkInteropDevice* This,IDXGIVkInteropSurface *pSurface,const VkImageSubresourceRange *pSubresources,VkImageLayout OldLayout,VkImageLayout NewLayout) { + This->lpVtbl->TransitionSurfaceLayout(This,pSurface,pSubresources,OldLayout,NewLayout); +} +static FORCEINLINE void IDXGIVkInteropDevice_FlushRenderingCommands(IDXGIVkInteropDevice* This) { + This->lpVtbl->FlushRenderingCommands(This); +} +static FORCEINLINE void IDXGIVkInteropDevice_LockSubmissionQueue(IDXGIVkInteropDevice* This) { + This->lpVtbl->LockSubmissionQueue(This); +} +static FORCEINLINE void IDXGIVkInteropDevice_ReleaseSubmissionQueue(IDXGIVkInteropDevice* This) { + This->lpVtbl->ReleaseSubmissionQueue(This); +} +#endif +#endif + +#endif + + +#endif /* __IDXGIVkInteropDevice_INTERFACE_DEFINED__ */ + +/* Begin additional prototypes for all interfaces */ + + +/* End additional prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __dxvk_interop_h__ */ diff --git a/wineopenxr/loader_structs.h b/wineopenxr/loader_structs.h new file mode 100644 index 00000000..8a4ba66d --- /dev/null +++ b/wineopenxr/loader_structs.h @@ -0,0 +1,30 @@ +typedef struct WINE_XR_STRUCT_NAME(XrNegotiateLoaderInfo) { + XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO + uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION + size_t structSize; // sizeof(XrNegotiateLoaderInfo) + uint32_t minInterfaceVersion; + uint32_t maxInterfaceVersion; + XrVersion minApiVersion; + XrVersion maxApiVersion; +} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateLoaderInfo); + +typedef struct WINE_XR_STRUCT_NAME(XrNegotiateRuntimeRequest) { + XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST + uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION + size_t structSize; // sizeof(XrNegotiateRuntimeRequest) + uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION + XrVersion runtimeApiVersion; + PFN_xrGetInstanceProcAddr getInstanceProcAddr; +} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateRuntimeRequest); + +/* +typedef struct WINE_XR_STRUCT_NAME(XrNegotiateApiLayerRequest) { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + uint32_t layerInterfaceVersion; + XrVersion layerApiVersion; + PFN_xrGetInstanceProcAddr getInstanceProcAddr; + PFN_xrCreateApiLayerInstance createApiLayerInstance; +} WINE_XR_STRUCT_ATTR WINE_XR_STRUCT_NAME(XrNegotiateApiLayerRequest); +*/ diff --git a/wineopenxr/make_openxr b/wineopenxr/make_openxr new file mode 100755 index 00000000..4a41d0d9 --- /dev/null +++ b/wineopenxr/make_openxr @@ -0,0 +1,2893 @@ +#!/usr/bin/python3 +# Wine Vulkan generator +# +# Copyright 2017-2018 Roderick Colenbrander +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +# + +import argparse +import logging +import os +import re +import sys +import urllib.request +import xml.etree.ElementTree as ET +from collections import OrderedDict +from collections.abc import Sequence +from enum import Enum + +# This script generates code for a Wine Vulkan ICD driver from Vulkan's xr.xml. +# Generating the code is like 10x worse than OpenGL, which is mostly a calling +# convention passthrough. +# +# The script parses xr.xml and maps functions and types to helper objects. These +# helper objects simplify the xml parsing and map closely to the Vulkan types. +# The code generation utilizes the helper objects during code generation and +# most of the ugly work is carried out by these objects. +# +# Vulkan ICD challenges: +# - Vulkan ICD loader (vulkan-1.dll) relies on a section at the start of +# 'dispatchable handles' (e.g. XrDevice, XrInstance) for it to insert +# its private data. It uses this area to stare its own dispatch tables +# for loader internal use. This means any dispatchable objects need wrapping. +# +# - Vulkan structures have different alignment between win32 and 32-bit Linux. +# This means structures with alignment differences need conversion logic. +# Often structures are nested, so the parent structure may not need any +# conversion, but some child may need some. +# +# xr.xml parsing challenges: +# - Contains type data for all platforms (generic Vulkan, Windows, Linux,..). +# Parsing of extension information required to pull in types and functions +# we really want to generate. Just tying all the data together is tricky. +# +# - Arrays are used all over the place for parameters or for structure members. +# Array length is often stored in a previous parameter or another structure +# member and thus needs careful parsing. + +LOGGER = logging.Logger("openxr") +LOGGER.addHandler(logging.StreamHandler()) + +XR_XML_VERSION = "1.0.11" +WINE_XR_VERSION = (1, 0) + +# Filenames to create. +WINE_OPENXR_H = "./wineopenxr.h" +WINE_OPENXR_DRIVER_H = "./wineopenxr_driver.h" +WINE_OPENXR_JSON = "./wineopenxr.json" +WINE_OPENXR_THUNKS_C = "./openxr_thunks.c" +WINE_OPENXR_THUNKS_H = "./openxr_thunks.h" + +# Extension enum values start at a certain offset (EXT_BASE). +# Relative to the offset each extension has a block (EXT_BLOCK_SIZE) +# of values. +# Start for a given extension is: +# EXT_BASE + (extension_number-1) * EXT_BLOCK_SIZE +EXT_BASE = 1000000000 +EXT_BLOCK_SIZE = 1000 + +UNSUPPORTED_EXTENSIONS = [ + # Instance extensions + "XR_EXT_debug_report", + # Handling of XR_EXT_debug_report requires some consideration. The win32 + # loader already provides it for us and it is somewhat usable. If we add + # plumbing down to the native layer, we will get each message twice as we + # use 2 loaders (win32+native), but we may get output from the driver. + # In any case callback conversion is required. + "XR_EXT_debug_utils", + "XR_EXT_validation_features", + "XR_EXT_validation_flags", + "XR_KHR_display", # Needs WSI work. + "XR_KHR_surface_protected_capabilities", + + # Device extensions + "XR_AMD_display_native_hdr", + "XR_EXT_display_control", # Requires XR_EXT_display_surface_counter + "XR_EXT_full_screen_exclusive", + "XR_EXT_hdr_metadata", # Needs WSI work. + "XR_EXT_pipeline_creation_feedback", + "XR_GOOGLE_display_timing", + "XR_KHR_external_fence_win32", + "XR_KHR_external_memory_win32", + "XR_KHR_external_semaphore_win32", + # Relates to external_semaphore and needs type conversions in bitflags. + "XR_KHR_shared_presentable_image", # Needs WSI work. + "XR_KHR_win32_keyed_mutex", + + # Extensions for other platforms + "XR_EXT_external_memory_dma_buf", + "XR_EXT_image_drm_format_modifier", + "XR_KHR_external_fence_fd", + "XR_KHR_external_memory_fd", + "XR_KHR_external_semaphore_fd", + + # Deprecated extensions + "XR_NV_external_memory_capabilities", + "XR_NV_external_memory_win32", +] + +ALLOWED_PROTECTS = [ + "XR_USE_PLATFORM_WIN32", + "XR_USE_GRAPHICS_API_VULKAN", + "XR_USE_GRAPHICS_API_OPENGL", + "XR_USE_GRAPHICS_API_D3D11", + "XR_USE_GRAPHICS_API_D3D12", +] + +# Functions part of our wineopenxr graphics driver interface. +# DRIVER_VERSION should be bumped on any change to driver interface +# in FUNCTION_OVERRIDES +DRIVER_VERSION = 1 + +# Table of functions for which we have a special implementation. +# These are regular device / instance functions for which we need +# to do more work compared to a regular thunk or because they are +# part of the driver interface. +# - dispatch set whether we need a function pointer in the device +# / instance dispatch table. +# - driver sets whether the API is part of the driver interface. +# - thunk sets whether to create a thunk in openxr_thunks.c. +FUNCTION_OVERRIDES = { + # Global functions + "xrCreateInstance" : {"dispatch" : False, "driver" : True, "thunk" : False}, + "xrDestroyInstance" : {"dispatch" : False, "driver" : True, "thunk" : False}, + + "xrCreateSession" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrDestroySession" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + "xrCreateHandTrackerEXT" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrDestroyHandTrackerEXT" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + "xrCreateSpatialAnchorMSFT" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrDestroySpatialAnchorMSFT" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + "xrGetInstanceProcAddr" : {"dispatch" : False, "driver" : True, "thunk" : False}, + "xrEnumerateInstanceExtensionProperties" : {"dispatch" : False, "driver" : True, "thunk" : False}, + + "xrConvertTimeToWin32PerformanceCounterKHR" : {"dispatch" : False, "driver" : True, "thunk" : False}, + "xrConvertWin32PerformanceCounterToTimeKHR" : {"dispatch" : False, "driver" : True, "thunk" : False}, + "xrGetD3D11GraphicsRequirementsKHR" : {"dispatch" : False, "driver" : True, "thunk" : False}, + "xrGetD3D12GraphicsRequirementsKHR" : {"dispatch" : False, "driver" : True, "thunk" : False}, + + "xrGetVulkanGraphicsDeviceKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrGetVulkanDeviceExtensionsKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrGetVulkanInstanceExtensionsKHR" : {"dispatch" : True, "driver" : True, "thunk" : False}, + + "xrPollEvent" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrEnumerateSwapchainImages" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrGetSystem" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrEnumerateSwapchainFormats" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrCreateSwapchain" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrDestroySwapchain" : {"dispatch" : True, "driver" : True, "thunk" : False}, + "xrEndFrame" : {"dispatch" : True, "driver" : True, "thunk" : False}, +} + +STRUCT_CHAIN_CONVERSIONS = [ + "XrInstanceCreateInfo", +] + + +class Direction(Enum): + """ Parameter direction: input, output, input_output. """ + INPUT = 1 + OUTPUT = 2 + INPUT_OUTPUT = 3 + + +class XrBaseType(object): + def __init__(self, name, _type, text, alias=None, requires=None): + """ OpenXR base type class. + + XrBaseType is mostly used by OpenXR to define its own + base types like XrFlags through typedef out of e.g. uint32_t. + + Args: + name (:obj:'str'): Name of the base type. + _type (:obj:'str'): Underlying type + alias (bool): type is an alias or not. + requires (:obj:'str', optional): Other types required. + Often bitmask values pull in a *FlagBits type. + """ + self.name = name + self.type = _type + self.alias = alias + self.requires = requires + self.required = False + self.text = text + + def definition(self): + # Definition is similar for alias or non-alias as type + # is already set to alias. + return self.text + "\n" + + def is_alias(self): + return bool(self.alias) + + +class XrConstant(object): + def __init__(self, name, value): + self.name = name + self.value = value + + def definition(self): + text = "#define {0} {1}\n".format(self.name, self.value) + return text + + +class XrDefine(object): + def __init__(self, name, value): + self.name = name + self.value = value + + @staticmethod + def from_xml(define): + name_elem = define.find("name") + + if name_elem is None: + # some_value + # At the time of writing there is only 1 define of this category + # 'XR_DEFINE_NON_DISPATCHABLE_HANDLE'. + name = define.attrib.get("name") + + # We override behavior of XR_DEFINE_NON_DISPATCHABLE handle as the default + # definition various between 64-bit (uses pointers) and 32-bit (uses uint64_t). + # This complicates TRACEs in the thunks, so just use uint64_t. + if name == "XR_DEFINE_NON_DISPATCHABLE_HANDLE": + value = "#define XR_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;" + else: + value = define.text + return XrDefine(name, value) + + # With a name element the structure is like: + # some_namesome_value + name = name_elem.text + + # Perform minimal parsing for constants, which we don't need, but are referenced + # elsewhere in xr.xml. + # - XR_API_VERSION is a messy, deprecated constant and we don't want generate code for it. + # - AHardwareBuffer/ANativeWindow are forward declarations for Android types, which leaked + # into the define region. + if name in ["XR_API_VERSION", "ANativeWindow"]: + return XrDefine(name, None) + + # The body of the define is basically unstructured C code. It is not meant for easy parsing. + # Some lines contain deprecated values or comments, which we try to filter out. + value = "" + for line in define.text.splitlines(): + value += "\n" + # Skip comments or deprecated values. + if "//" in line: + continue + value += line + + for child in define: + value += child.text + if child.tail is not None: + # Split comments for XR_API_VERSION_1_0 / XR_API_VERSION_1_1 + if "//" in child.tail: + value += child.tail.split("//")[0] + else: + value += child.tail + + return XrDefine(name, value.rstrip(' ')) + + def definition(self): + if self.value is None: + return "" + + # Nothing to do as the value was already put in the right form during parsing. + return "{0}\n".format(self.value) + + def is_alias(self): + return False + + +class XrEnum(object): + def __init__(self, name, values, alias=None): + self.name = name + self.values = values + self.required = False + self.alias = alias + self.aliased_by = [] + + @staticmethod + def from_alias(enum, alias): + name = enum.attrib.get("name") + aliasee = XrEnum(name, alias.values, alias=alias) + + alias.add_aliased_by(aliasee) + return aliasee + + @staticmethod + def from_xml(enum): + name = enum.attrib.get("name") + values = [] + + for v in enum.findall("enum"): + # Value is either a value or a bitpos, only one can exist. + value = v.attrib.get("value") + alias_name = v.attrib.get("alias") + if alias_name: + alias = next(x for x in values if x.name == alias_name) + values.append(XrEnumValue(v.attrib.get("name"), value=alias.value, hex=alias.hex)) + elif value: + # Some values are in hex form. We want to preserve the hex representation + # at least when we convert back to a string. Internally we want to use int. + if "0x" in value: + values.append(XrEnumValue(v.attrib.get("name"), value=int(value, 0), hex=True)) + else: + values.append(XrEnumValue(v.attrib.get("name"), value=int(value, 0))) + else: + # bitmask + value = 1 << int(v.attrib.get("bitpos")) + values.append(XrEnumValue(v.attrib.get("name"), value=value, hex=True)) + + # vulkan.h contains a *_MAX_ENUM value set to 32-bit at the time of writing, + # which is to prepare for extensions as they can add values and hence affect + # the size definition. + max_name = re.sub(r'([0-9a-z_])([A-Z0-9])',r'\1_\2', name).upper() + "_MAX_ENUM" + values.append(XrEnumValue(max_name, value=0x7fffffff, hex=True)) + + return XrEnum(name, values) + + def add(self, value): + """ Add a value to enum. """ + + # Extensions can add new enum values. When an extension is promoted to Core + # the registry defines the value twice once for old extension and once for + # new Core features. Add the duplicate if it's explicitly marked as an + # alias, otherwise ignore it. + for v in self.values: + if not value.is_alias() and v.value == value.value: + LOGGER.debug("Adding duplicate enum value {0} to {1}".format(v, self.name)) + return + # Avoid adding duplicate aliases multiple times + if not any(x.name == value.name for x in self.values): + self.values.append(value) + + def definition(self): + if self.is_alias(): + return "" + + text = "typedef enum {0}\n{{\n".format(self.name) + + # Print values sorted, values can have been added in a random order. + values = sorted(self.values, key=lambda value: value.value if value.value is not None else 0x7ffffffe) + for value in values: + text += " {0},\n".format(value.definition()) + text += "}} {0};\n".format(self.name) + + for aliasee in self.aliased_by: + text += "typedef {0} {1};\n".format(self.name, aliasee.name) + + text += "\n" + return text + + def is_alias(self): + return bool(self.alias) + + def add_aliased_by(self, aliasee): + self.aliased_by.append(aliasee) + + +class XrEnumValue(object): + def __init__(self, name, value=None, hex=False, alias=None): + self.name = name + self.value = value + self.hex = hex + self.alias = alias + + def __repr__(self): + if self.is_alias(): + return "{0}={1}".format(self.name, self.alias) + return "{0}={1}".format(self.name, self.value) + + def definition(self): + """ Convert to text definition e.g. XR_FOO = 1 """ + if self.is_alias(): + return "{0} = {1}".format(self.name, self.alias) + + # Hex is commonly used for FlagBits and sometimes within + # a non-FlagBits enum for a bitmask value as well. + if self.hex: + return "{0} = 0x{1:08x}".format(self.name, self.value) + else: + return "{0} = {1}".format(self.name, self.value) + + def is_alias(self): + return self.alias is not None + + +class XrFunction(object): + def __init__(self, _type=None, name=None, params=[], extensions=[], alias=None): + self.extensions = [] + self.name = name + self.type = _type + self.params = params + self.alias = alias + + # For some functions we need some extra metadata from FUNCTION_OVERRIDES. + func_info = FUNCTION_OVERRIDES.get(self.name, None) + self.dispatch = func_info["dispatch"] if func_info else True + self.driver = func_info["driver"] if func_info else False + self.thunk_needed = func_info["thunk"] if func_info else True + self.private_thunk = func_info["private_thunk"] if func_info and "private_thunk" in func_info else False + if self.private_thunk: + self.thunk_needed = True + + # Required is set while parsing which APIs and types are required + # and is used by the code generation. + self.required = True if func_info else False + + @staticmethod + def from_alias(command, alias): + """ Create XrFunction from an alias command. + + Args: + command: xml data for command + alias (XrFunction): function to use as a base for types / parameters. + + Returns: + XrFunction + """ + func_name = command.attrib.get("name") + func_type = alias.type + params = alias.params + + return XrFunction(_type=func_type, name=func_name, params=params, alias=alias) + + @staticmethod + def from_xml(command, types): + proto = command.find("proto") + func_name = proto.find("name").text + func_type = proto.find("type").text + + params = [] + for param in command.findall("param"): + xr_param = XrParam.from_xml(param, types) + params.append(xr_param) + + return XrFunction(_type=func_type, name=func_name, params=params) + + def get_conversions(self): + """ Get a list of conversion functions required for this function if any. + Parameters which are structures may require conversion between win32 + and the host platform. This function returns a list of conversions + required. + """ + + conversions = [] + for param in self.params: + convs = param.get_conversions() + if convs is not None: + conversions.extend(convs) + + return conversions + + def is_alias(self): + return bool(self.alias) + + def is_core_func(self): + """ Returns whether the function is a core function. + Core functions are APIs defined by the spec to be part of the + Core API. + """ + return not self.extensions + + def is_driver_func(self): + """ Returns if function is part of Wine driver interface. """ + return self.driver + + def is_global_func(self): + # Treat xrGetInstanceProcAddr as a global function as it + # can operate with NULL for xrInstance. + if self.name == "xrGetInstanceProcAddr": + return True + # Global functions are not passed a dispatchable object. + elif self.params[0].is_dispatchable(): + return False + return True + + def is_instance_func(self): + # Instance functions are passed XrInstance. + if self.params[0].type in ["XrInstance"]: + return True + return False + + def is_required(self): + return self.required + + def needs_conversion(self): + """ Check if the function needs any input/output type conversion. + Functions need input/output conversion if struct parameters have + alignment differences between Win32 and Linux 32-bit. + """ + + for p in self.params: + if p.needs_conversion(): + LOGGER.debug("Parameter {0} to {1} requires conversion".format(p.name, self.name)) + return True + + return False + + def needs_dispatch(self): + return self.dispatch + + def needs_thunk(self): + return self.thunk_needed + + def needs_private_thunk(self): + return self.private_thunk + + def pfn(self, prefix="p", call_conv=None, conv=False): + """ Create function pointer. """ + + if call_conv: + pfn = "{0} ({1} *{2}_{3})(".format(self.type, call_conv, prefix, self.name) + else: + pfn = "{0} (*{1}_{2})(".format(self.type, prefix, self.name) + + for i, param in enumerate(self.params): + if param.const: + pfn += param.const + " " + + pfn += param.type + if conv and param.needs_conversion(): + pfn += "_host" + + if param.is_pointer(): + pfn += " " + param.pointer + + if param.array_len is not None: + pfn += "[{0}]".format(param.array_len) + + if i < len(self.params) - 1: + pfn += ", " + pfn += ")" + return pfn + + def prototype(self, call_conv=None, prefix=None, postfix=None): + """ Generate prototype for given function. + + Args: + call_conv (str, optional): calling convention e.g. WINAPI + prefix (str, optional): prefix to append prior to function name e.g. xrFoo -> wine_xrFoo + postfix (str, optional): text to append after function name but prior to semicolon e.g. DECLSPEC_HIDDEN + """ + + proto = "{0}".format(self.type) + + if call_conv is not None: + proto += " {0}".format(call_conv) + + if prefix is not None: + proto += " {0}{1}(".format(prefix, self.name) + else: + proto += " {0}(".format(self.name) + + # Add all the parameters. + proto += ", ".join([p.definition() for p in self.params]) + + if postfix is not None: + proto += ") {0}".format(postfix) + else: + proto += ")" + + return proto + + def body(self): + body = "" + + if not self.needs_private_thunk(): + body += " {0}".format(self.trace()) + + params = ", ".join([p.variable(conv=False) for p in self.params]) + + # Call the native Vulkan function. + if self.is_core_func(): + # core functions are exported by the native loader, so avoid dispatch for those + if self.type == "void": + body += " {0}({1});\n".format(self.name, params) + else: + body += " return {0}({1});\n".format(self.name, params) + else: + if self.type == "void": + body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + else: + body += " return {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + + return body + + def body_conversion(self): + body = "" + + # Declare a variable to hold the result for non-void functions. + if self.type != "void": + body += " {0} result;\n".format(self.type) + + # Declare any tmp parameters for conversion. + for p in self.params: + if not p.needs_conversion(): + continue + + if p.is_dynamic_array(): + body += " {0}_host *{1}_host;\n".format(p.type, p.name) + else: + body += " {0}_host {1}_host;\n".format(p.type, p.name) + + if not self.needs_private_thunk(): + body += " {0}\n".format(self.trace()) + + # Call any win_to_host conversion calls. + for p in self.params: + if not p.needs_input_conversion(): + continue + + body += p.copy(Direction.INPUT) + + # Build list of parameters containing converted and non-converted parameters. + # The param itself knows if conversion is needed and applies it when we set conv=True. + params = ", ".join([p.variable(conv=True) for p in self.params]) + + # Call the native function. + if self.type == "void": + body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + else: + body += " result = {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + + body += "\n" + + # Call any host_to_win conversion calls. + for p in self.params: + if not p.needs_output_conversion(): + continue + + body += p.copy(Direction.OUTPUT) + + # Perform any required cleanups. Most of these are for array functions. + for p in self.params: + if not p.needs_free(): + continue + + body += p.free() + + # Finally return the result. + if self.type != "void": + body += " return result;\n" + + return body + + def stub(self, call_conv=None, prefix=None): + stub = self.prototype(call_conv=call_conv, prefix=prefix) + stub += "\n{\n" + stub += " {0}".format(self.trace(message="stub: ", trace_func="WINE_FIXME")) + + if self.type == "XrResult": + stub += " return XR_ERROR_OUT_OF_HOST_MEMORY;\n" + elif self.type == "XrBool32": + stub += " return XR_FALSE;\n" + elif self.type == "PFN_xrVoidFunction": + stub += " return NULL;\n" + + stub += "}\n\n" + return stub + + def thunk(self, call_conv=None, prefix=None): + thunk = self.prototype(call_conv=call_conv, prefix=prefix) + thunk += "\n{\n" + + if self.needs_conversion(): + thunk += "#if defined(USE_STRUCT_CONVERSION)\n" + thunk += self.body_conversion() + thunk += "#else\n" + thunk += self.body() + thunk += "#endif\n" + else: + thunk += self.body() + + thunk += "}\n\n" + return thunk + + def trace(self, message=None, trace_func=None): + """ Create a trace string including all parameters. + + Args: + message (str, optional): text to print at start of trace message e.g. 'stub: ' + trace_func (str, optional): used to override trace function e.g. FIXME, printf, etcetera. + """ + if trace_func is not None: + trace = "{0}(\"".format(trace_func) + else: + trace = "WINE_TRACE(\"" + + if message is not None: + trace += message + + # First loop is for all the format strings. + trace += ", ".join([p.format_string() for p in self.params]) + trace += "\\n\"" + + # Second loop for parameter names and optional conversions. + for param in self.params: + if param.format_conv is not None: + trace += ", " + param.format_conv.format(param.name) + else: + trace += ", {0}".format(param.name) + trace += ");\n" + + return trace + + +class XrFunctionPointer(object): + def __init__(self, _type, name, members): + self.name = name + self.members = members + self.type = _type + self.required = False + + @staticmethod + def from_xml(funcpointer): + members = [] + begin = None + + for t in funcpointer.findall("type"): + # General form: + # void* pUserData, + # Parsing of the tail (anything past ) is tricky since there + # can be other data on the next line like: const int.. + + const = True if begin and "const" in begin else False + _type = t.text + lines = t.tail.split(",\n") + if lines[0][0] == "*": + pointer = "*" + name = lines[0][1:].strip() + else: + pointer = None + name = lines[0].strip() + + # Filter out ); if it is contained. + name = name.partition(");")[0] + + # If tail encompasses multiple lines, assign the second line to begin + # for the next line. + try: + begin = lines[1].strip() + except IndexError: + begin = None + + members.append(XrMember(const=const, _type=_type, pointer=pointer, name=name)) + + _type = funcpointer.text + name = funcpointer.find("name").text + return XrFunctionPointer(_type, name, members) + + def definition(self): + text = "{0} {1})(\n".format(self.type, self.name) + + first = True + if len(self.members) > 0: + for m in self.members: + if first: + text += " " + m.definition() + first = False + else: + text += ",\n " + m.definition() + else: + # Just make the compiler happy by adding a void parameter. + text += "void" + text += ");\n" + return text + + +class XrHandle(object): + def __init__(self, name, _type, parent, alias=None): + self.name = name + self.type = _type + self.parent = parent + self.alias = alias + self.required = False + + @staticmethod + def from_alias(handle, alias): + name = handle.attrib.get("name") + return XrHandle(name, alias.type, alias.parent, alias=alias) + + @staticmethod + def from_xml(handle): + name = handle.find("name").text + _type = handle.find("type").text + parent = handle.attrib.get("parent") + return XrHandle(name, _type, parent) + + def dispatch_table(self): + if not self.is_dispatchable(): + return None + + if self.parent is None: + # Should only happen for XrInstance + return "funcs" + if self.parent in ["XrInstance"]: + return "wine_instance->funcs" + if self.parent in ["XrSession"]: + return "wine_session->wine_instance->funcs" + if self.parent in ["XrActionSet"]: + return "wine_action_set->wine_instance->funcs" + + LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent)) + + def definition(self): + """ Generates handle definition e.g. XR_DEFINE_HANDLE(xrInstance) """ + + # Legacy types are typedef'ed to the new type if they are aliases. + if self.is_alias(): + return "typedef {0} {1};\n".format(self.alias.name, self.name) + + return "{0}({1})\n".format(self.type, self.name) + + def is_alias(self): + return self.alias is not None + + def is_dispatchable(self): + """ Some handles, like XrInstance, are dispatchable objects, + which means they contain a dispatch table of function pointers. + """ + return self.type == "XR_DEFINE_HANDLE" + + def is_required(self): + return self.required + + def native_handle(self, name): + """ Provide access to the native handle of a wrapped object. """ + + # Remember to add any new native handle whose parent is XrDevice + # to unwrap_object_handle() in openxr.c + if self.name == "XrCommandPool": + return "wine_cmd_pool_from_handle({0})->command_pool".format(name) + + native_handle_name = None + + if self.name == "XrInstance": + native_handle_name = "instance" + if self.name == "XrSession": + native_handle_name = "session" + if self.name == "XrHandTrackerEXT": + native_handle_name = "hand_tracker" + if self.name == "XrSpatialAnchorMSFT": + native_handle_name = "spatial_anchor" + if self.name == "XrSwapchain": + native_handle_name = "swapchain" + if self.name == "XrActionSet": + return None + if self.name == "XrAction": + return None + if self.name == "XrSpace": + return None + + if native_handle_name: + return "((wine_{0} *){1})->{2}".format(self.name, name, native_handle_name) + + if self.is_dispatchable(): + LOGGER.error("Unhandled native handle for: {0}".format(self.name)) + return None + + +class XrMember(object): + def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, + dyn_array_len=None, optional=False, values=None): + self.const = const + self.struct_fwd_decl = struct_fwd_decl + self.name = name + self.pointer = pointer + self.type = _type + self.type_info = None + self.array_len = array_len + self.dyn_array_len = dyn_array_len + self.optional = optional + self.values = values + + def __eq__(self, other): + """ Compare member based on name against a string. + + This method is for convenience by XrStruct, which holds a number of members and needs quick checking + if certain members exist. + """ + + return self.name == other + + def __repr__(self): + return "{0} {1} {2} {3} {4} {5} {6}".format(self.const, self.struct_fwd_decl, self.type, self.pointer, + self.name, self.array_len, self.dyn_array_len) + + @staticmethod + def from_xml(member): + """ Helper function for parsing a member tag within a struct or union. """ + + name_elem = member.find("name") + type_elem = member.find("type") + + const = False + struct_fwd_decl = False + member_type = None + pointer = None + array_len = None + + values = member.get("values") + + if member.text: + if "const" in member.text: + const = True + + # Some members contain forward declarations: + # - XrBaseInstructure has a member "const struct XrBaseInStructure *next" + # - XrWaylandSurfaceCreateInfoKHR has a member "struct wl_display *display" + if "struct" in member.text: + struct_fwd_decl = True + + if type_elem is not None: + member_type = type_elem.text + if type_elem.tail is not None: + pointer = type_elem.tail.strip() if type_elem.tail.strip() != "" else None + + # Name of other member within, which stores the number of + # elements pointed to be by this member. + dyn_array_len = member.get("len") + + # Some members are optional, which is important for conversion code e.g. not dereference NULL pointer. + optional = True if member.get("optional") else False + + # Usually we need to allocate memory for dynamic arrays. We need to do the same in a few other cases + # like for XrCommandBufferBeginInfo.pInheritanceInfo. Just threat such cases as dynamic arrays of + # size 1 to simplify code generation. + if dyn_array_len is None and pointer is not None: + dyn_array_len = 1 + + # Some members are arrays, attempt to parse these. Formats include: + # charextensionName[XR_MAX_EXTENSION_NAME_SIZE] + # uint32_tfoo[4] + if name_elem.tail and name_elem.tail[0] == '[': + LOGGER.debug("Found array type") + enum_elem = member.find("enum") + if enum_elem is not None: + array_len = enum_elem.text + else: + # Remove brackets around length + array_len = name_elem.tail.strip("[]") + + return XrMember(const=const, struct_fwd_decl=struct_fwd_decl, _type=member_type, pointer=pointer, name=name_elem.text, + array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, values=values) + + def copy(self, input, output, direction): + """ Helper method for use by conversion logic to generate a C-code statement to copy this member. """ + + if self.needs_conversion(): + if self.is_dynamic_array(): + if direction == Direction.OUTPUT: + LOGGER.warn("TODO: implement copying of returnedonly dynamic array for {0}.{1}".format(self.type, self.name)) + else: + # Array length is either a variable name (string) or an int. + count = self.dyn_array_len if isinstance(self.dyn_array_len, int) else "{0}{1}".format(input, self.dyn_array_len) + return "{0}{1} = convert_{2}_array_win_to_host({3}{1}, {4});\n".format(output, self.name, self.type, input, count) + elif self.is_static_array(): + count = self.array_len + if direction == Direction.OUTPUT: + # Needed by XrMemoryHeap.memoryHeaps + return "convert_{0}_static_array_host_to_win({2}{1}, {3}{1}, {4});\n".format(self.type, self.name, input, output, count) + else: + # Nothing needed this yet. + LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name)) + else: + if direction == Direction.OUTPUT: + return "convert_{0}_host_to_win(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output) + else: + return "convert_{0}_win_to_host(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output) + elif self.is_static_array(): + bytes_count = "{0} * sizeof({1})".format(self.array_len, self.type) + return "memcpy({0}{1}, {2}{1}, {3});\n".format(output, self.name, input, bytes_count) + else: + return "{0}{1} = {2}{1};\n".format(output, self.name, input) + + def definition(self, align=False, conv=False): + """ Generate prototype for given function. + + Args: + align (bool, optional): Enable alignment if a type needs it. This adds WINE_XR_ALIGN(8) to a member. + conv (bool, optional): Enable conversion if a type needs it. This appends '_host' to the name. + """ + + text = "" + if self.is_const(): + text += "const " + + if self.is_struct_forward_declaration(): + text += "struct " + + if conv and self.is_struct(): + text += "{0}_host".format(self.type) + else: + text += self.type + + if self.is_pointer(): + text += " {0}{1}".format(self.pointer, self.name) + else: + if align and self.needs_alignment(): + text += " WINE_XR_ALIGN(8) " + self.name + else: + text += " " + self.name + + if self.is_static_array(): + text += "[{0}]".format(self.array_len) + + return text + + def get_conversions(self): + """ Return any conversion description for this member and its children when conversion is needed. """ + + # Check if we need conversion either for this member itself or for any child members + # in case member represents a struct. + if not self.needs_conversion(): + return None + + conversions = [] + + # Collect any conversion for any member structs. + struct = self.type_info["data"] + for m in struct: + m.needs_struct_extensions_conversion() + if m.needs_conversion(): + conversions.extend(m.get_conversions()) + + struct.needs_struct_extensions_conversion() + + struct = self.type_info["data"] + direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT + if self.is_dynamic_array(): + conversions.append(ConversionFunction(False, True, direction, struct)) + elif self.is_static_array(): + conversions.append(ConversionFunction(True, False, direction, struct)) + else: + conversions.append(ConversionFunction(False, False, direction, struct)) + + if self.needs_free(): + conversions.append(FreeFunction(self.is_dynamic_array(), struct)) + + return conversions + + def is_const(self): + return self.const + + def is_dynamic_array(self): + """ Returns if the member is an array element. + OpenXR uses this for dynamically sized arrays for which + there is a 'count' parameter. + """ + return self.dyn_array_len is not None + + def is_handle(self): + return self.type_info["category"] == "handle" + + def is_pointer(self): + return self.pointer is not None + + def is_static_array(self): + """ Returns if the member is an array. + OpenXR uses this often for fixed size arrays in which the + length is part of the member. + """ + return self.array_len is not None + + def is_struct(self): + return self.type_info["category"] == "struct" + + def is_struct_forward_declaration(self): + return self.struct_fwd_decl + + def is_union(self): + return self.type_info["category"] == "union" + + def needs_alignment(self): + """ Check if this member needs alignment for 64-bit data. + Various structures need alignment on 64-bit variables due + to compiler differences on 32-bit between Win32 and Linux. + """ + + if self.is_pointer(): + return False + elif self.type == "size_t": + return False + elif self.type in ["uint64_t"]: + return True + elif self.is_struct(): + struct = self.type_info["data"] + return struct.needs_alignment() + elif self.is_handle(): + # Dispatchable handles are pointers to objects, while + # non-dispatchable are uint64_t and hence need alignment. + handle = self.type_info["data"] + return False if handle.is_dispatchable() else True + return False + + def needs_conversion(self): + """ Structures requiring alignment, need conversion between win32 and host. """ + + if not self.is_struct(): + return False + + struct = self.type_info["data"] + return struct.needs_conversion() + + def needs_free(self): + if not self.needs_conversion(): + return False + + if self.is_dynamic_array(): + return True + + # TODO: some non-pointer structs and optional pointer structs may need freeing, + # though none of this type have been encountered yet. + return False + + def needs_struct_extensions_conversion(self): + if not self.is_struct(): + return False + + struct = self.type_info["data"] + return struct.needs_struct_extensions_conversion() + + def set_type_info(self, type_info): + """ Helper function to set type information from the type registry. + This is needed, because not all type data is available at time of + parsing. + """ + self.type_info = type_info + + +class XrParam(object): + """ Helper class which describes a parameter to a function call. """ + + def __init__(self, type_info, const=None, pointer=None, name=None, array_len=None, dyn_array_len=None): + self.const = const + self.name = name + self.array_len = array_len + self.dyn_array_len = dyn_array_len + self.pointer = pointer + self.type_info = type_info + self.type = type_info["name"] # For convenience + self.handle = type_info["data"] if type_info["category"] == "handle" else None + self.struct = type_info["data"] if type_info["category"] == "struct" else None + + self._set_direction() + self._set_format_string() + self._set_conversions() + + def __repr__(self): + return "{0} {1} {2} {3} {4} {5}".format(self.const, self.type, self.pointer, self.name, self.array_len, self.dyn_array_len) + + @staticmethod + def from_xml(param, types): + """ Helper function to create XrParam from xml. """ + + # Parameter parsing is slightly tricky. All the data is contained within + # a param tag, but some data is within subtags while others are text + # before or after the type tag. + # Common structure: + # const char* pLayerName + + name_elem = param.find("name") + array_len = None + name = name_elem.text + # Tail contains array length e.g. for blendConstants param of xrSetBlendConstants + if name_elem.tail is not None: + array_len = name_elem.tail.strip("[]") + + # Name of other parameter in function prototype, which stores the number of + # elements pointed to be by this parameter. + dyn_array_len = param.get("len", None) + + const = param.text.strip() if param.text else None + type_elem = param.find("type") + pointer = type_elem.tail.strip() if type_elem.tail.strip() != "" else None + + # Since we have parsed all types before hand, this should not happen. + type_info = types.get(type_elem.text, None) + if type_info is None: + LOGGER.err("type info not found for: {0}".format(type_elem.text)) + + return XrParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len) + + def _set_conversions(self): + """ Internal helper function to configure any needed conversion functions. """ + + self.free_func = None + self.input_conv = None + self.output_conv = None + if not self.needs_conversion(): + return + + # Input functions require win to host conversion. + if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: + self.input_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.INPUT, self.struct) + + # Output functions require host to win conversion. + if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]: + self.output_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.OUTPUT, self.struct) + + # Dynamic arrays, but also some normal structs (e.g. XrCommandBufferBeginInfo) need memory + # allocation and thus some cleanup. + if self.is_dynamic_array() or self.struct.needs_free(): + self.free_func = FreeFunction(self.is_dynamic_array(), self.struct) + + def _set_direction(self): + """ Internal helper function to set parameter direction (input/output/input_output). """ + + # The parameter direction needs to be determined from hints in xr.xml like returnedonly, + # parameter constness and other heuristics. + # For now we need to get this right for structures as we need to convert these, we may have + # missed a few other edge cases (e.g. count variables). + # See also https://github.com/KhronosGroup/Vulkan-Docs/issues/610 + + if not self.is_pointer(): + self._direction = Direction.INPUT + elif self.is_const() and self.is_pointer(): + self._direction = Direction.INPUT + elif self.is_struct(): + if not self.struct.returnedonly: + self._direction = Direction.INPUT + return + + # Returnedonly hints towards output, however in some cases + # it is inputoutput. In particular if next / type exist, + # which are used to link in other structures without having + # to introduce new APIs. E.g. xrGetPhysicalDeviceProperties2KHR. + if "next" in self.struct: + self._direction = Direction.INPUT_OUTPUT + return + + self._direction = Direction.OUTPUT + else: + # This should mostly be right. Count variables can be inout, but we don't care about these yet. + self._direction = Direction.OUTPUT + + def _set_format_string(self): + """ Internal helper function to be used by constructor to set format string. """ + + # Determine a format string used by code generation for traces. + # 64-bit types need a conversion function. + self.format_conv = None + if self.is_static_array() or self.is_pointer(): + self.format_str = "%p" + else: + if self.type_info["category"] in ["bitmask", "enum"]: + self.format_str = "%#x" + elif self.is_handle(): + # We use uint64_t for non-dispatchable handles as opposed to pointers + # for dispatchable handles. + if self.handle.is_dispatchable(): + self.format_str = "%p" + else: + self.format_str = "0x%s" + self.format_conv = "wine_dbgstr_longlong({0})" + elif self.type == "float": + self.format_str = "%f" + elif self.type == "int": + self.format_str = "%d" + elif self.type == "int32_t": + self.format_str = "%d" + elif self.type == "size_t": + self.format_str = "0x%s" + self.format_conv = "wine_dbgstr_longlong({0})" + elif self.type in ["uint16_t", "uint32_t", "XrBool32"]: + self.format_str = "%u" + elif self.type in ["uint64_t"]: + self.format_str = "0x%s" + self.format_conv = "wine_dbgstr_longlong({0})" + elif self.type == "HANDLE": + self.format_str = "%p" + elif self.type in ["XrSystemId", "XrPath", "XrTime"]: + self.format_str = "0x%s" + self.format_conv = "wine_dbgstr_longlong({0})" + elif self.type in ["XrVector2f"]: + self.format_str = "%f, %f" + self.format_conv = "{0}.x, {0}.y" + elif self.type in ["VisualID", "xcb_visualid_t", "VkInstance", "XrPosef"]: + # Don't care about Linux specific types. + self.format_str = "" + else: + LOGGER.warning("Unhandled type: {0}".format(self.type_info)) + + def copy(self, direction): + if direction == Direction.INPUT: + if self.is_dynamic_array(): + return " {0}_host = convert_{1}_array_win_to_host({0}, {2});\n".format(self.name, self.type, self.dyn_array_len) + else: + return " convert_{0}_win_to_host({1}, &{1}_host);\n".format(self.type, self.name) + else: + if self.is_dynamic_array(): + LOGGER.error("Unimplemented output conversion for: {0}".format(self.name)) + else: + return " convert_{0}_host_to_win(&{1}_host, {1});\n".format(self.type, self.name) + + def definition(self, postfix=None): + """ Return prototype for the parameter. E.g. 'const char *foo' """ + + proto = "" + if self.const: + proto += self.const + " " + + proto += self.type + + if self.is_pointer(): + proto += " {0}{1}".format(self.pointer, self.name) + else: + proto += " " + self.name + + # Allows appending something to the variable name useful for + # win32 to host conversion. + if postfix is not None: + proto += postfix + + if self.is_static_array(): + proto += "[{0}]".format(self.array_len) + + return proto + + def direction(self): + """ Returns parameter direction: input, output, input_output. + + Parameter direction in OpenXR is not straight-forward, which this function determines. + """ + + return self._direction + + def dispatch_table(self): + """ Return functions dispatch table pointer for dispatchable objects. """ + + if not self.is_dispatchable(): + return None + + return "((wine_{0} *){1})->{2}".format(self.type, self.name, self.handle.dispatch_table()) + + def format_string(self): + return self.format_str + + def free(self): + if self.is_dynamic_array(): + if self.struct.returnedonly: + # For returnedonly, counts is stored in a pointer. + return " free_{0}_array({1}_host, *{2});\n".format(self.type, self.name, self.dyn_array_len) + else: + return " free_{0}_array({1}_host, {2});\n".format(self.type, self.name, self.dyn_array_len) + else: + # We are operating on a single structure. Some structs (very rare) contain dynamic members, + # which would need freeing. + if self.struct.needs_free(): + return " free_{0}(&{1}_host);\n".format(self.type, self.name) + return "" + + def get_conversions(self): + """ Get a list of conversions required for this parameter if any. + Parameters which are structures may require conversion between win32 + and the host platform. This function returns a list of conversions + required. + """ + + if not self.is_struct(): + return None + + self.struct.needs_struct_extensions_conversion() + for m in self.struct: + m.needs_struct_extensions_conversion() + + if not self.needs_conversion(): + return None + + conversions = [] + + # Collect any member conversions first, so we can guarantee + # those functions will be defined prior to usage by the + # 'parent' param requiring conversion. + for m in self.struct: + if not m.is_struct(): + continue + + if not m.needs_conversion(): + continue + + conversions.extend(m.get_conversions()) + + # Conversion requirements for the 'parent' parameter. + if self.input_conv is not None: + conversions.append(self.input_conv) + if self.output_conv is not None: + conversions.append(self.output_conv) + if self.free_func is not None: + conversions.append(self.free_func) + + return conversions + + def is_const(self): + return self.const is not None + + def is_dynamic_array(self): + return self.dyn_array_len is not None + + def is_dispatchable(self): + if not self.is_handle(): + return False + + return self.handle.is_dispatchable() + + def is_handle(self): + return self.handle is not None + + def is_pointer(self): + return self.pointer is not None + + def is_static_array(self): + return self.array_len is not None + + def is_struct(self): + return self.struct is not None + + def needs_conversion(self): + """ Returns if parameter needs conversion between win32 and host. """ + + if not self.is_struct(): + return False + + # If a structure needs alignment changes, it means we need to + # perform parameter conversion between win32 and host. + if self.struct.needs_conversion(): + return True + + return False + + def needs_free(self): + return self.free_func is not None + + def needs_input_conversion(self): + return self.input_conv is not None + + def needs_output_conversion(self): + return self.output_conv is not None + + def variable(self, conv=False): + """ Returns 'glue' code during generation of a function call on how to access the variable. + This function handles various scenarios such as 'unwrapping' if dispatchable objects and + renaming of parameters in case of win32 -> host conversion. + + Args: + conv (bool, optional): Enable conversion if the param needs it. This appends '_host' to the name. + """ + + if conv and self.needs_conversion(): + if self.is_dynamic_array(): + return "{0}_host".format(self.name) + else: + return "&{0}_host".format(self.name) + else: + # We need to pass the native handle to the native calls. + native_handle = self.handle.native_handle(self.name) if self.is_handle() else None + return native_handle if native_handle else self.name + + +class XrStruct(Sequence): + """ Class which represents the type union and struct. """ + + def __init__(self, name, members, returnedonly, structextends, alias=None, union=False): + self.name = name + self.members = members + self.returnedonly = returnedonly + self.structextends = structextends + self.required = False + self.alias = alias + self.union = union + self.type_info = None # To be set later. + self.struct_extensions = [] + self.aliased_by = [] + + def __getitem__(self, i): + return self.members[i] + + def __len__(self): + return len(self.members) + + @staticmethod + def from_alias(struct, alias): + name = struct.attrib.get("name") + aliasee = XrStruct(name, alias.members, alias.returnedonly, alias.structextends, alias=alias) + + alias.add_aliased_by(aliasee) + return aliasee + + @staticmethod + def from_xml(struct): + # Unions and structs are the same parsing wise, but we need to + # know which one we are dealing with later on for code generation. + union = True if struct.attrib["category"] == "union" else False + + name = struct.attrib.get("name") + + # 'Output' structures for which data is filled in by the API are + # marked as 'returnedonly'. + returnedonly = True if struct.attrib.get("returnedonly") else False + + structextends = struct.attrib.get("structextends") + structextends = structextends.split(",") if structextends else [] + + members = [] + for member in struct.findall("member"): + xr_member = XrMember.from_xml(member) + members.append(xr_member) + + return XrStruct(name, members, returnedonly, structextends, union=union) + + @staticmethod + def decouple_structs(structs): + """ Helper function which decouples a list of structs. + Structures often depend on other structures. To make the C compiler + happy we need to define 'substructures' first. This function analyzes + the list of structures and reorders them in such a way that they are + decoupled. + """ + + tmp_structs = list(structs) # Don't modify the original structures. + decoupled_structs = [] + + while (len(tmp_structs) > 0): + for struct in tmp_structs: + dependends = False + + if not struct.required: + tmp_structs.remove(struct) + continue + + for m in struct: + if not (m.is_struct() or m.is_union()): + continue + + # XrBaseInstructure and XrBaseOutStructure reference themselves. + if m.type == struct.name: + break + + found = False + # Check if a struct we depend on has already been defined. + for s in decoupled_structs: + if s.name == m.type: + found = True + break + + if not found: + # Check if the struct we depend on is even in the list of structs. + # If found now, it means we haven't met all dependencies before we + # can operate on the current struct. + # When generating 'host' structs we may not be able to find a struct + # as the list would only contain the structs requiring conversion. + for s in tmp_structs: + if s.name == m.type: + dependends = True + break + + if dependends == False: + decoupled_structs.append(struct) + tmp_structs.remove(struct) + + return decoupled_structs + + def typedef(self): + if self.union: + text = "typedef union {0} {0};\n".format(self.name) + else: + text = "typedef struct {0} {0};\n".format(self.name) + + for aliasee in self.aliased_by: + text += "typedef {0} {1};\n".format(self.name, aliasee.name) + + return text + + def definition(self, align=False, conv=False, postfix=None): + """ Convert structure to textual definition. + + Args: + align (bool, optional): enable alignment to 64-bit for win32 struct compatibility. + conv (bool, optional): enable struct conversion if the struct needs it. + postfix (str, optional): text to append to end of struct name, useful for struct renaming. + """ + + # Only define alias structs when doing conversions + if self.is_alias() and not conv: + return "" + + if self.union: + text = "union {0}".format(self.name) + else: + text = "struct {0}".format(self.name) + + if postfix is not None: + text += postfix + + text += "\n{\n" + + for m in self: + if align and m.needs_alignment(): + text += " {0};\n".format(m.definition(align=align)) + elif conv and m.needs_conversion(): + text += " {0};\n".format(m.definition(conv=conv)) + else: + text += " {0};\n".format(m.definition()) + + if postfix is not None: + text += "}} {1};\n\n".format(self.name, postfix) + else: + text += "}};\n".format(self.name) + + text += "\n" + + return text + + def is_alias(self): + return bool(self.alias) + + def add_aliased_by(self, aliasee): + self.aliased_by.append(aliasee) + + def needs_alignment(self): + """ Check if structure needs alignment for 64-bit data. + Various structures need alignment on 64-bit variables due + to compiler differences on 32-bit between Win32 and Linux. + """ + + for m in self.members: + if m.needs_alignment(): + return True + return False + + def needs_conversion(self): + """ Returns if struct members needs conversion between win32 and host. + Structures need conversion if they contain members requiring alignment + or if they include other structures which need alignment. + """ + + if self.needs_alignment(): + return True + + for m in self.members: + if m.needs_conversion(): + return True + return False + + def needs_free(self): + """ Check if any struct member needs some memory freeing.""" + + for m in self.members: + if m.needs_free(): + return True + + continue + + return False + + def needs_struct_extensions_conversion(self): + """ Checks if structure extensions in next chain need conversion. """ + ret = False + + for e in self.struct_extensions: + if e.required and e.needs_conversion(): + LOGGER.error("Unhandled next chain conversion for {0}".format(e.name)) + ret = True + + return ret + + def set_type_info(self, types): + """ Helper function to set type information from the type registry. + This is needed, because not all type data is available at time of + parsing. + """ + for m in self.members: + type_info = types[m.type] + m.set_type_info(type_info) + + +class ConversionFunction(object): + def __init__(self, array, dyn_array, direction, struct): + self.array = array + self.direction = direction + self.dyn_array = dyn_array + self.struct = struct + self.type = struct.name + + self._set_name() + + def __eq__(self, other): + return self.name == other.name + + def _generate_array_conversion_func(self): + """ Helper function for generating a conversion function for array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "uint32_t count"] + return_type = self.type + else: + params = ["const {0} *in".format(self.type), "uint32_t count"] + return_type = "{0}_host".format(self.type) + + # Generate function prototype. + body = "static inline {0} *{1}(".format(return_type, self.name) + body += ", ".join(p for p in params) + body += ")\n{\n" + + body += " {0} *out;\n".format(return_type) + body += " unsigned int i;\n\n" + body += " if (!in) return NULL;\n\n" + + body += " out = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*out));\n" + + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + # TODO: support copying of next extension structures! + # Luckily though no extension struct at this point needs conversion. + body += " " + m.copy("in[i].", "out[i].", self.direction) + + body += " }\n\n" + body += " return out;\n" + body += "}\n\n" + return body + + def _generate_conversion_func(self): + """ Helper function for generating a conversion function for non-array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type)] + else: + params = ["const {0} *in".format(self.type), "{0}_host *out".format(self.type)] + + body = "static inline void {0}(".format(self.name) + + # Generate parameter list + body += ", ".join(p for p in params) + body += ")\n{\n" + + body += " if (!in) return;\n\n" + + if self.direction == Direction.INPUT and "next" in self.struct and self.struct.returnedonly: + # We are dealing with an input_output parameter. For these we only need to copy + # next and type as the other fields are filled in by the host. We do potentially + # have to iterate over next and perform conversions based on switch(type)! + # Luckily though no extension structs at this point need conversion. + # TODO: support copying of next extension structures! + body += " out->next = in->next;\n" + body += " out->type = in->type;\n" + else: + for m in self.struct: + # TODO: support copying of next extension structures! + body += " " + m.copy("in->", "out->", self.direction) + + body += "}\n\n" + return body + + def _generate_static_array_conversion_func(self): + """ Helper function for generating a conversion function for array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type), "uint32_t count"] + else: + params = ["const {0} *in".format(self.type), "{0} *out_host".format(self.type), "uint32_t count"] + + # Generate function prototype. + body = "static inline void {0}(".format(self.name) + body += ", ".join(p for p in params) + body += ")\n{\n" + body += " unsigned int i;\n\n" + body += " if (!in) return;\n\n" + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + # TODO: support copying of next extension structures! + body += " " + m.copy("in[i].", "out[i].", self.direction) + + body += " }\n" + body += "}\n\n" + return body + + def _set_name(self): + if self.direction == Direction.INPUT: + if self.array: + name = "convert_{0}_static_array_win_to_host".format(self.type) + elif self.dyn_array: + name = "convert_{0}_array_win_to_host".format(self.type) + else: + name = "convert_{0}_win_to_host".format(self.type) + else: # Direction.OUTPUT + if self.array: + name = "convert_{0}_static_array_host_to_win".format(self.type) + elif self.dyn_array: + name = "convert_{0}_array_host_to_win".format(self.type) + else: + name = "convert_{0}_host_to_win".format(self.type) + + self.name = name + + def definition(self): + if self.array: + return self._generate_static_array_conversion_func() + elif self.dyn_array: + return self._generate_array_conversion_func() + else: + return self._generate_conversion_func() + + +class FreeFunction(object): + def __init__(self, dyn_array, struct): + self.dyn_array = dyn_array + self.struct = struct + self.type = struct.name + + if dyn_array: + self.name = "free_{0}_array".format(self.type) + else: + self.name = "free_{0}".format(self.type) + + def __eq__(self, other): + return self.name == other.name + + def _generate_array_free_func(self): + """ Helper function for cleaning up temporary buffers required for array conversions. """ + + # Generate function prototype. + body = "static inline void {0}({1}_host *in, uint32_t count)\n{{\n".format(self.name, self.type) + + # E.g. XrGraphicsPipelineCreateInfo_host needs freeing for pStages. + if self.struct.needs_free(): + body += " unsigned int i;\n\n" + body += " if (!in) return;\n\n" + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + if m.needs_conversion() and m.is_dynamic_array(): + if m.is_const(): + # Add a cast to ignore const on conversion structs we allocated ourselves. + body += " free_{0}_array(({0}_host *)in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len) + else: + body += " free_{0}_array(in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len) + elif m.needs_conversion(): + LOGGER.error("Unhandled conversion for {0}".format(m.name)) + body += " }\n" + else: + body += " if (!in) return;\n\n" + + body += " HeapFree(GetProcessHeap(), 0, in);\n" + + body += "}\n\n" + return body + + def _generate_free_func(self): + # E.g. XrCommandBufferBeginInfo.pInheritanceInfo needs freeing. + if not self.struct.needs_free(): + return "" + + # Generate function prototype. + body = "static inline void {0}({1}_host *in)\n{{\n".format(self.name, self.type) + + for m in self.struct: + if m.needs_conversion() and m.is_dynamic_array(): + count = m.dyn_array_len if isinstance(m.dyn_array_len, int) else "in->{0}".format(m.dyn_array_len) + if m.is_const(): + # Add a cast to ignore const on conversion structs we allocated ourselves. + body += " free_{0}_array(({0}_host *)in->{1}, {2});\n".format(m.type, m.name, count) + else: + body += " free_{0}_array(in->{1}, {2});\n".format(m.type, m.name, count) + + body += "}\n\n" + return body + + def definition(self): + if self.dyn_array: + return self._generate_array_free_func() + else: + # Some structures need freeing too if they contain dynamic arrays. + # E.g. XrCommandBufferBeginInfo + return self._generate_free_func() + + +class StructChainConversionFunction(object): + def __init__(self, direction, struct): + self.direction = direction + self.struct = struct + self.type = struct.name + + self.name = "convert_{0}_struct_chain".format(self.type) + + def __eq__(self, other): + return self.name == other.name + + def prototype(self, postfix=""): + return "XrResult {0}(const void *next, {1} *out_struct) {2}".format(self.name, self.type, postfix).strip() + + def definition(self): + body = self.prototype() + body += "\n{\n" + + body += " XrBaseOutStructure *out_header = (XrBaseOutStructure *)out_struct;\n"; + body += " const XrBaseInStructure *in_header;\n\n"; + + body += " out_header->next = NULL;\n\n" + + body += " for (in_header = next; in_header; in_header = in_header->next)\n" + body += " {\n" + body += " switch (in_header->type)\n" + body += " {\n" + + # Ignore to not confuse host loader. + body += " case XR_TYPE_INSTANCE_CREATE_INFO:\n" + body += " break;\n\n" + + for e in self.struct.struct_extensions: + if not e.required: + continue + + stype = next(x for x in e.members if x.name == "type") + + body += " case {0}:\n".format(stype.values) + body += " {\n" + + body += " const {0} *in = (const {0} *)in_header;\n".format(e.name) + body += " {0} *out;\n\n".format(e.name) + + body += " if (!(out = HeapAlloc(GetProcessHeap(), 0, sizeof(*out)))) goto out_of_memory;\n\n" + + for m in e: + if m.name == "next": + body += " out->next = NULL;\n" + else: + body += " " + m.copy("in->", "out->", self.direction) + + body += "\n out_header->next = (XrBaseOutStructure *)out;\n" + body += " out_header = out_header->next;\n" + body += " break;\n" + body += " }\n\n" + + body += " default:\n" + body += " WINE_FIXME(\"Application requested a linked structure of type %u.\\n\", in_header->type);\n" + + body += " }\n" + body += " }\n\n" + + body += " return XR_SUCCESS;\n" + + if any(x for x in self.struct.struct_extensions if x.required): + body += "\nout_of_memory:\n" + body += " free_{0}_struct_chain(out_struct);\n".format(self.type) + body += " return XR_ERROR_OUT_OF_HOST_MEMORY;\n" + + body += "}\n\n" + return body + +class FreeStructChainFunction(object): + def __init__(self, struct): + self.struct = struct + self.type = struct.name + + self.name = "free_{0}_struct_chain".format(self.type) + + def __eq__(self, other): + return self.name == other.name + + def prototype(self, postfix=""): + return "void {0}({1} *s) {2}".format(self.name, self.type, postfix).strip() + + def definition(self): + body = self.prototype() + body += "\n{\n" + + body += " XrBaseOutStructure *header = (void *)s->next;\n\n"; + + body += " while (header)\n" + body += " {\n" + body += " void *prev = header;\n" + body += " header = header->next;\n" + body += " HeapFree(GetProcessHeap(), 0, prev);\n" + body += " }\n\n" + + body += " s->next = NULL;\n" + + body += "}\n\n" + return body + + +class XrGenerator(object): + def __init__(self, registry): + self.registry = registry + + # Build a list conversion functions for struct conversion. + self.conversions = [] + self.struct_chain_conversions = [] + self.host_structs = [] + for func in self.registry.funcs.values(): + if not func.is_required(): + continue + + if not func.needs_conversion(): + continue + + conversions = func.get_conversions() + for conv in conversions: + # Pull in any conversions for openxr_thunks.c. + if func.needs_thunk(): + # Append if we don't already have this conversion. + if not any(c == conv for c in self.conversions): + self.conversions.append(conv) + + # Structs can be used in different ways by different conversions + # e.g. array vs non-array. Just make sure we pull in each struct once. + if not any(s.name == conv.struct.name for s in self.host_structs): + self.host_structs.append(conv.struct) + + for struct in self.registry.structs: + if struct.name in STRUCT_CHAIN_CONVERSIONS: + self.struct_chain_conversions.append(StructChainConversionFunction(Direction.INPUT, struct)) + self.struct_chain_conversions.append(FreeStructChainFunction(struct)) + + def _generate_copyright(self, f, spec_file=False): + f.write("# " if spec_file else "/* ") + f.write("Automatically generated from OpenXR xr.xml; DO NOT EDIT!\n") + lines = ["", "This file is generated from OpenXR xr.xml file covered", + "by the following copyright and permission notice:"] + lines.extend([l.rstrip(" ") for l in self.registry.copyright.splitlines()]) + for line in lines: + f.write("{0}{1}".format("# " if spec_file else " * ", line).rstrip(" ") + "\n") + f.write("\n" if spec_file else " */\n\n") + + def generate_thunks_c(self, f, prefix): + self._generate_copyright(f) + + f.write("#include \"wine/debug.h\"\n") + f.write("#include \"wine/vulkan.h\"\n") + f.write("#include \"d3d11.h\"\n") + f.write("#include \"d3d12.h\"\n") + f.write("#define WINE_XR_HOST\n") + f.write("#include \"wineopenxr.h\"\n") + f.write("#include \"openxr_private.h\"\n\n") + + f.write("WINE_DEFAULT_DEBUG_CHANNEL(openxr);\n\n") + + # Generate any conversion helper functions. + f.write("#if defined(USE_STRUCT_CONVERSION)\n") + for conv in self.conversions: + f.write(conv.definition()) + f.write("#endif /* USE_STRUCT_CONVERSION */\n\n") + + for conv in self.struct_chain_conversions: + f.write(conv.definition()) + + # Create thunks for instance and device functions. + # Global functions don't go through the thunks. + for xr_func in self.registry.funcs.values(): + if not xr_func.is_required(): + continue + + #if xr_func.is_global_func(): + # continue + + if not xr_func.needs_thunk(): + continue + + # Exports symbols for Core functions. + if not xr_func.is_core_func() and not xr_func.needs_private_thunk(): + f.write("static ") + + if xr_func.needs_private_thunk(): + f.write(xr_func.thunk(prefix="thunk_")) + else: + f.write(xr_func.thunk(prefix=prefix, call_conv="WINAPI")) + + f.write("static const struct openxr_func xr_dispatch_table[] =\n{\n") + for xr_func in self.registry.instance_funcs: + if not xr_func.is_required(): + continue + f.write(" {{\"{0}\", &{1}{0}}},\n".format(xr_func.name, prefix)) + f.write("};\n\n") + + f.write("void *wine_xr_proc_addr(const char *name)\n") + f.write("{\n") + f.write(" unsigned int i;\n") + f.write(" for (i = 0; i < ARRAY_SIZE(xr_dispatch_table); i++)\n") + f.write(" {\n") + f.write(" if (strcmp(xr_dispatch_table[i].name, name) == 0)\n") + f.write(" {\n") + f.write(" WINE_TRACE(\"Found name=%s in instance table\\n\", wine_dbgstr_a(name));\n") + f.write(" return xr_dispatch_table[i].func;\n") + f.write(" }\n") + f.write(" }\n") + f.write(" return NULL;\n") + f.write("}\n\n") + + # Create array of instance extensions. + f.write("static const char * const xr_extensions[] =\n{\n") + for ext in self.registry.extensions: + f.write(" \"{0}\",\n".format(ext["name"])) + f.write("};\n\n") + + f.write("BOOL wine_xr_extension_supported(const char *name)\n") + f.write("{\n") + f.write(" unsigned int i;\n") + f.write(" for (i = 0; i < ARRAY_SIZE(xr_extensions); i++)\n") + f.write(" {\n") + f.write(" if (strcmp(xr_extensions[i], name) == 0)\n") + f.write(" return TRUE;\n") + f.write(" }\n") + f.write(" return FALSE;\n") + f.write("}\n") + + def generate_thunks_h(self, f, prefix): + self._generate_copyright(f) + + f.write("#ifndef __WINE_OPENXR_THUNKS_H\n") + f.write("#define __WINE_OPENXR_THUNKS_H\n\n") + + f.write("#define WINE_XR_VERSION XR_API_VERSION_{0}_{1}\n\n".format(WINE_XR_VERSION[0], WINE_XR_VERSION[1])) + + # Generate prototypes for device and instance functions requiring a custom implementation. + f.write("/* Functions for which we have custom implementations outside of the thunks. */\n") + for xr_func in self.registry.funcs.values(): + if not xr_func.is_required():# or xr_func.is_global_func(): + continue + if xr_func.needs_thunk() and not xr_func.needs_private_thunk(): + continue + + if xr_func.is_core_func(): + f.write("{0};\n".format(xr_func.prototype("WINAPI", prefix="wine_"))) + else: + f.write("{0};\n".format(xr_func.prototype("WINAPI", prefix="wine_", postfix="DECLSPEC_HIDDEN"))) + f.write("\n") + + f.write("/* Private thunks */\n") + for xr_func in self.registry.funcs.values(): + if xr_func.needs_private_thunk(): + f.write("{0};\n".format(xr_func.prototype(prefix="thunk_", postfix="DECLSPEC_HIDDEN"))) + f.write("\n") + + for struct in self.host_structs: + f.write(struct.definition(align=False, conv=True, postfix="_host")) + f.write("\n") + + for func in self.struct_chain_conversions: + f.write(func.prototype(postfix="DECLSPEC_HIDDEN") + ";\n") + f.write("\n") + + f.write("/* For use by xrInstance and children */\n") + f.write("struct openxr_instance_funcs\n{\n") + for xr_func in self.registry.instance_funcs: + if not xr_func.is_required(): + continue + + if not xr_func.needs_dispatch(): + LOGGER.debug("skipping {0} in openxr_instance_funcs".format(xr_func.name)) + continue + + if xr_func.needs_conversion(): + f.write("#if defined(USE_STRUCT_CONVERSION)\n") + f.write(" {0};\n".format(xr_func.pfn(conv=True))) + f.write("#else\n") + f.write(" {0};\n".format(xr_func.pfn(conv=False))) + f.write("#endif\n") + else: + f.write(" {0};\n".format(xr_func.pfn(conv=False))) + f.write("};\n\n") + + f.write("#define ALL_XR_INSTANCE_FUNCS() \\\n") + first = True + for xr_func in self.registry.instance_funcs: + if not xr_func.is_required(): + continue + + if not xr_func.needs_dispatch(): + LOGGER.debug("skipping {0} in ALL_XR_INSTANCE_FUNCS".format(xr_func.name)) + continue + + if first: + f.write(" USE_XR_FUNC({0})".format(xr_func.name)) + first = False + else: + f.write(" \\\n USE_XR_FUNC({0})".format(xr_func.name)) + f.write("\n\n") + + f.write("#endif /* __WINE_OPENXR_THUNKS_H */\n") + + def generate_openxr_h(self, f): + self._generate_copyright(f) + f.write("#ifndef __WINE_OPENXR_H\n") + f.write("#define __WINE_OPENXR_H\n\n") + + f.write("#include \n") + f.write("#include \n\n") + + f.write("/* Define WINE_XR_HOST to get 'host' headers. */\n") + f.write("#ifdef WINE_XR_HOST\n") + f.write("#define XRAPI_CALL\n") + f.write('#define WINE_XR_ALIGN(x)\n') + f.write("#endif\n\n") + + f.write("#ifndef XRAPI_CALL\n") + f.write("#define XRAPI_CALL __stdcall\n") + f.write("#endif\n\n") + + f.write("#ifndef XRAPI_PTR\n") + f.write("#define XRAPI_PTR XRAPI_CALL\n") + f.write("#endif\n\n") + + f.write("#ifndef WINE_XR_ALIGN\n") + f.write("#define WINE_XR_ALIGN DECLSPEC_ALIGN\n") + f.write("#endif\n\n") + + # The overall strategy is to define independent constants and datatypes, + # prior to complex structures and function calls to avoid forward declarations. + for const in self.registry.consts: + # For now just generate things we may not need. The amount of parsing needed + # to get some of the info is tricky as you need to figure out which structure + # references a certain constant. + f.write(const.definition()) + f.write("\n") + + for define in self.registry.defines: + f.write(define.definition()) + + for handle in self.registry.handles: + # For backward compatibility also create definitions for aliases. + # These types normally don't get pulled in as we use the new types + # even in legacy functions if they are aliases. + if handle.is_required() or handle.is_alias(): + f.write(handle.definition()) + f.write("\n") + + for base_type in self.registry.base_types: + f.write(base_type.definition()) + f.write("\n") + + for bitmask in self.registry.bitmasks: + f.write(bitmask.definition()) + f.write("\n") + + # Define enums, this includes values for some of the bitmask types as well. + for enum in self.registry.enums.values(): + if enum.required: + f.write(enum.definition()) + + # This generates both structures and unions. Since structures + # may depend on other structures/unions, we need a list of + # decoupled structs. + # Note: unions are stored in structs for dependency reasons, + # see comment in parsing section. + structs = XrStruct.decouple_structs(self.registry.structs) + + for struct in structs: + f.write(struct.typedef()) + + for fp in self.registry.funcpointers: + if fp.required: + f.write(fp.definition()) + f.write("\n") + + for struct in structs: + LOGGER.debug("Generating struct: {0}".format(struct.name)) + f.write(struct.definition(align=True)) + + for func in self.registry.funcs.values(): + if not func.is_required(): + LOGGER.debug("Skipping PFN definition for: {0}".format(func.name)) + continue + + f.write("typedef {0};\n".format(func.pfn(prefix="PFN", call_conv="XRAPI_PTR"))) + f.write("\n") + + f.write("#ifndef XR_NO_PROTOTYPES\n") + for func in self.registry.funcs.values(): + if not func.is_required(): + LOGGER.debug("Skipping API definition for: {0}".format(func.name)) + continue + + LOGGER.debug("Generating API definition for: {0}".format(func.name)) + f.write("{0};\n".format(func.prototype(call_conv="XRAPI_CALL"))) + f.write("#endif /* XR_NO_PROTOTYPES */\n\n") + + f.write("#endif /* __WINE_OPENXR_H */\n") + + +class XrRegistry(object): + def __init__(self, reg_filename): + # Used for storage of type information. + self.base_types = None + self.bitmasks = None + self.consts = None + self.defines = None + self.enums = None + self.funcpointers = None + self.handles = None + self.structs = None + + # We aggregate all types in here for cross-referencing. + self.funcs = {} + self.types = {} + + self.version_regex = re.compile( + r'^' + r'XR_VERSION_' + r'(?P[0-9])' + r'_' + r'(?P[0-9])' + r'$' + ) + + # Overall strategy for parsing the registry is to first + # parse all type / function definitions. Then parse + # features and extensions to decide which types / functions + # to actually 'pull in' for code generation. For each type or + # function call we want we set a member 'required' to True. + tree = ET.parse(reg_filename) + root = tree.getroot() + self._parse_enums(root) + self._parse_types(root) + self._parse_commands(root) + + # Pull in any required types and functions. + self._parse_features(root) + self._parse_extensions(root) + + self.copyright = root.find('./comment').text + + def _is_feature_supported(self, feature): + version = self.version_regex.match(feature) + if not version: + return True + + version = tuple(map(int, version.group('major', 'minor'))) + return version <= WINE_XR_VERSION + + def _is_extension_supported(self, extension): + # We disable some extensions as either we haven't implemented + # support yet or because they are for platforms other than win32. + return extension not in UNSUPPORTED_EXTENSIONS + + def mark_bitmask_dependencies(self, bitmask): + if bitmask.requires is not None: + self.types[bitmask.requires]["data"].required = True + + def mark_funcpointer_dependencies(self, fp): + for m in fp.members: + type_info = self.types[m.type] + + # Complex types have a matching definition e.g. XrStruct. + # Not needed for base types such as uint32_t. + if "data" in type_info: + self.types[m.type]["data"].required = True + + def mark_struct_dependencies(self, struct): + for m in struct: + type_info = self.types[m.type] + + + # Complex types have a matching definition e.g. XrStruct. + # Not needed for base types such as uint32_t. + if "data" in type_info: + if self.types[m.type]["data"].required: + continue + self.types[m.type]["data"].required = True + + if type_info["category"] == "struct": + # Yay, recurse + self.mark_struct_dependencies(type_info["data"]) + elif type_info["category"] == "funcpointer": + self.mark_funcpointer_dependencies(type_info["data"]) + elif type_info["category"] == "bitmask": + self.mark_bitmask_dependencies(type_info["data"]) + + def _mark_command_required(self, command): + """ Helper function to mark a certain command and the datatypes it needs as required.""" + LOGGER.debug("marking " + command + " as required") + func = self.funcs[command] + func.required = True + + # Pull in return type + if func.type != "void": + self.types[func.type]["data"].required = True + + # Analyze parameter dependencies and pull in any type needed. + for p in func.params: + type_info = self.types[p.type] + + # Check if we are dealing with a complex type e.g. XrEnum, XrStruct and others. + if "data" not in type_info: + continue + + # Mark the complex type as required. + type_info["data"].required = True + if type_info["category"] == "struct": + struct = type_info["data"] + self.mark_struct_dependencies(struct) + elif type_info["category"] == "bitmask": + self.mark_bitmask_dependencies(type_info["data"]) + + def _parse_commands(self, root): + """ Parse command section containing the OpenXR function calls. """ + funcs = {} + commands = root.findall("./commands/") + + # As of Vulkan 1.1, various extensions got promoted to Core. + # The old commands (e.g. KHR) are available for backwards compatibility + # and are marked in xr.xml as 'alias' to the non-extension type. + # The registry likes to avoid data duplication, so parameters and other + # metadata need to be looked up from the Core command. + # We parse the alias commands in a second pass. + alias_commands = [] + for command in commands: + alias_name = command.attrib.get("alias") + if alias_name: + alias_commands.append(command) + continue + + func = XrFunction.from_xml(command, self.types) + funcs[func.name] = func + + for command in alias_commands: + alias_name = command.attrib.get("alias") + alias = funcs[alias_name] + func = XrFunction.from_alias(command, alias) + funcs[func.name] = func + + # To make life easy for the code generation, separate all function + # calls out in the 3 types of functions: device, global and instance. + instance_funcs = [] + for func in funcs.values(): + instance_funcs.append(func) + + # Sort function lists by name and store them. + self.instance_funcs = sorted(instance_funcs, key=lambda func: func.name) + + # The funcs dictionary is used as a convenient way to lookup function + # calls when needed e.g. to adjust member variables. + self.funcs = OrderedDict(sorted(funcs.items())) + + def _parse_enums(self, root): + """ Parse enums section or better described as constants section. """ + enums = {} + self.consts = [] + for enum in root.findall("./enums"): + name = enum.attrib.get("name") + _type = enum.attrib.get("type") + + if _type in ("enum", "bitmask"): + enums[name] = XrEnum.from_xml(enum) + else: + # If no type is set, we are dealing with API constants. + for value in enum.findall("enum"): + # If enum is an alias, set the value to the alias name. + # E.g. XR_LUID_SIZE_KHR is an alias to XR_LUID_SIZE. + alias = value.attrib.get("alias") + if alias: + self.consts.append(XrConstant(value.attrib.get("name"), alias)) + else: + self.consts.append(XrConstant(value.attrib.get("name"), value.attrib.get("value"))) + + self.enums = OrderedDict(sorted(enums.items())) + + def _process_require_enum(self, enum_elem, ext=None, only_aliased=False): + if "extends" in enum_elem.keys(): + enum = self.types[enum_elem.attrib["extends"]]["data"] + + # Need to define XrEnumValues which were aliased to by another value. This is necessary + # from XR spec version 1.2.135 where the provisional XR_KHR_ray_tracing extension was + # added which altered XR_NV_ray_tracing's XrEnumValues to alias to the provisional + # extension. + aliased = False + for _, t in self.types.items(): + if t["category"] != "enum": + continue + if not t["data"]: + continue + for value in t["data"].values: + if value.alias == enum_elem.attrib["name"]: + aliased = True + + if only_aliased and not aliased: + return + + if "bitpos" in enum_elem.keys(): + # We need to add an extra value to an existing enum type. + # E.g. XR_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG to XrFormatFeatureFlagBits. + enum.add(XrEnumValue(enum_elem.attrib["name"], value=(1 << int(enum_elem.attrib["bitpos"])), hex=True)) + + elif "offset" in enum_elem.keys(): + # Extensions promoted to Core, have the extension number as part + # of the enum value. Else retrieve from the extension tag. + if enum_elem.attrib.get("extnumber"): + ext_number = int(enum_elem.attrib.get("extnumber")) + else: + ext_number = int(ext.attrib["number"]) + offset = int(enum_elem.attrib["offset"]) + value = EXT_BASE + (ext_number - 1) * EXT_BLOCK_SIZE + offset + + # Deal with negative values. + direction = enum_elem.attrib.get("dir") + if direction is not None: + value = -value + + enum.add(XrEnumValue(enum_elem.attrib["name"], value=value)) + + elif "value" in enum_elem.keys(): + enum.add(XrEnumValue(enum_elem.attrib["name"], value=int(enum_elem.attrib["value"]))) + elif "alias" in enum_elem.keys(): + enum.add(XrEnumValue(enum_elem.attrib["name"], alias=enum_elem.attrib["alias"])) + + elif "value" in enum_elem.keys(): + # Constants are not aliased, no need to add them here, they'll get added later on. + if only_aliased: + return + + self.consts.append(XrConstant(enum_elem.attrib["name"], enum_elem.attrib["value"])) + + @staticmethod + def _require_type(type_info): + if type_info.is_alias(): + type_info = type_info.alias + type_info.required = True + if type(type_info) == XrStruct: + for member in type_info.members: + if "data" in member.type_info: + XrRegistry._require_type(member.type_info["data"]) + + def _parse_extensions(self, root): + """ Parse extensions section and pull in any types and commands for this extension. """ + extensions = [] + exts = root.findall("./extensions/extension") + deferred_exts = [] + + def process_ext(ext, deferred=False): + ext_name = ext.attrib["name"] + + # Set extension name on any functions calls part of this extension as we + # were not aware of the name during initial parsing. + commands = ext.findall("require/command") + for command in commands: + cmd_name = command.attrib["name"] + self.funcs[cmd_name].extensions.append(ext_name) + + # Some extensions are not ready or have numbers reserved as a place holder. + if ext.attrib["supported"] == "disabled": + LOGGER.debug("Skipping disabled extension: {0}".format(ext_name)) + return + + protect = ext.attrib.get("protect", None) + if not protect is None and \ + not protect in ALLOWED_PROTECTS: + return + + # Defer extensions with 'sortorder' as they are order-dependent for spec-parsing. + if not deferred and "sortorder" in ext.attrib: + deferred_exts.append(ext) + return + + # Disable highly experimental extensions as the APIs are unstable and can + # change between minor revisions until API is final and becomes KHR + # or NV. + if "KHX" in ext_name or "NVX" in ext_name: + LOGGER.debug("Skipping experimental extension: {0}".format(ext_name)) + return + + # Extensions can define XrEnumValues which alias to provisional extensions. Pre-process + # extensions to define any required XrEnumValues before the platform check below. + for require in ext.findall("require"): + # Extensions can add enum values to Core / extension enums, so add these. + for enum_elem in require.findall("enum"): + self._process_require_enum(enum_elem, ext, only_aliased=True) + + platform = ext.attrib.get("platform") + if platform and platform != "win32": + LOGGER.debug("Skipping extensions {0} for platform {1}".format(ext_name, platform)) + return + + if not self._is_extension_supported(ext_name): + LOGGER.debug("Skipping unsupported extension: {0}".format(ext_name)) + return + elif "requires" in ext.attrib: + # Check if this extension builds on top of another unsupported extension. + requires = ext.attrib["requires"].split(",") + if len(set(requires).intersection(UNSUPPORTED_EXTENSIONS)) > 0: + return + + LOGGER.debug("Loading extension: {0}".format(ext_name)) + + # Extensions can define one or more require sections each requiring + # different features (e.g. Vulkan 1.1). Parse each require section + # separately, so we can skip sections we don't want. + for require in ext.findall("require"): + # Extensions can add enum values to Core / extension enums, so add these. + for enum_elem in require.findall("enum"): + self._process_require_enum(enum_elem, ext) + + for t in require.findall("type"): + if t.attrib["name"] in self.types: + type_info = self.types[t.attrib["name"]]["data"] + self._require_type(type_info) + feature = require.attrib.get("feature") + if feature and not self._is_feature_supported(feature): + continue + + required_extension = require.attrib.get("extension") + if required_extension and not self._is_extension_supported(required_extension): + continue + + # Pull in any commands we need. We infer types to pull in from the command + # as well. + for command in require.findall("command"): + cmd_name = command.attrib["name"] + self._mark_command_required(cmd_name) + + + # Store a list with extensions. + ext_info = {"name" : ext_name, "type" : ext.attrib["type"]} + extensions.append(ext_info) + + + # Process extensions, allowing for sortorder to defer extension processing + for ext in exts: + process_ext(ext) + + deferred_exts.sort(key=lambda ext: ext.attrib["sortorder"]) + + # Respect sortorder + for ext in deferred_exts: + process_ext(ext, deferred=True) + + # Sort in alphabetical order. + self.extensions = sorted(extensions, key=lambda ext: ext["name"]) + + def _parse_features(self, root): + """ Parse the feature section, which describes Core commands and types needed. """ + + for feature in root.findall("./feature"): + feature_name = feature.attrib["name"] + for require in feature.findall("require"): + LOGGER.info("Including features for {0}".format(require.attrib.get("comment"))) + for tag in require: + if tag.tag == "comment": + continue + elif tag.tag == "command": + if not self._is_feature_supported(feature_name): + continue + name = tag.attrib["name"] + LOGGER.debug("found command: " + name) + self._mark_command_required(name) + elif tag.tag == "enum": + self._process_require_enum(tag) + elif tag.tag == "type": + name = tag.attrib["name"] + + # Skip pull in for openxr_platform_defines.h for now. + if name == "openxr_platform_defines": + continue + + type_info = self.types[name] + type_info["data"].required = True + + def _parse_types(self, root): + """ Parse types section, which contains all data types e.g. structs, typedefs etcetera. """ + types = root.findall("./types/type") + + base_types = [] + bitmasks = [] + defines = [] + funcpointers = [] + handles = [] + structs = [] + + alias_types = [] + for t in types: + type_info = {} + type_info["category"] = t.attrib.get("category", None) + type_info["requires"] = t.attrib.get("requires", None) + + # We parse aliases in a second pass when we know more. + alias = t.attrib.get("alias") + if alias: + LOGGER.debug("Alias found: {0}".format(alias)) + alias_types.append(t) + continue + + protect = t.attrib.get("protect", None) + if not protect is None and \ + not protect in ALLOWED_PROTECTS: + continue + + if type_info["category"] in ["include"]: + continue + + if type_info["category"] == "basetype": + name = t.find("name").text + _type = None + if not t.find("type") is None: + _type = t.find("type").text + basetype = XrBaseType(name, _type, collect_element_text(t)) + base_types.append(basetype) + type_info["data"] = basetype + + # Basic C types don't need us to define them, but we do need data for them + if type_info["requires"] == "xr_platform": + requires = type_info["requires"] + basic_c = XrBaseType(name, _type, collect_element_text(t), requires=requires) + type_info["data"] = basic_c + + if type_info["category"] == "bitmask": + name = t.find("name").text + _type = t.find("type").text + + # Most bitmasks have a requires attribute used to pull in + # required '*FlagBits" enum. + requires = type_info["requires"] + bitmask = XrBaseType(name, _type, collect_element_text(t), requires=requires) + bitmasks.append(bitmask) + type_info["data"] = bitmask + + if type_info["category"] == "define": + define = XrDefine.from_xml(t) + defines.append(define) + type_info["data"] = define + + if type_info["category"] == "enum": + name = t.attrib.get("name") + # The type section only contains enum names, not the actual definition. + # Since we already parsed the enum before, just link it in. + try: + type_info["data"] = self.enums[name] + except KeyError as e: + # Not all enums seem to be defined yet, typically that's for + # ones ending in 'FlagBits' where future extensions may add + # definitions. + type_info["data"] = None + + if type_info["category"] == "funcpointer": + funcpointer = XrFunctionPointer.from_xml(t) + funcpointers.append(funcpointer) + type_info["data"] = funcpointer + + if type_info["category"] == "handle": + handle = XrHandle.from_xml(t) + handles.append(handle) + type_info["data"] = handle + + if type_info["category"] in ["struct", "union"]: + # We store unions among structs as some structs depend + # on unions. The types are very similar in parsing and + # generation anyway. The official Vulkan scripts use + # a similar kind of hack. + struct = XrStruct.from_xml(t) + structs.append(struct) + type_info["data"] = struct + + # Name is in general within a name tag else it is an optional + # attribute on the type tag. + name_elem = t.find("name") + if name_elem is not None: + type_info["name"] = name_elem.text + else: + type_info["name"] = t.attrib.get("name", None) + + # Store all type data in a shared dictionary, so we can easily + # look up information for a given type. There are no duplicate + # names. + self.types[type_info["name"]] = type_info + + # Second pass for alias types, so we can retrieve all data from + # the aliased object. + for t in alias_types: + type_info = {} + type_info["category"] = t.attrib.get("category") + type_info["name"] = t.attrib.get("name") + + alias = t.attrib.get("alias") + + if type_info["category"] == "bitmask": + bitmask = XrBaseType(type_info["name"], alias, collect_element_text(t), alias=self.types[alias]["data"]) + bitmasks.append(bitmask) + type_info["data"] = bitmask + + if type_info["category"] == "enum": + enum = XrEnum.from_alias(t, self.types[alias]["data"]) + type_info["data"] = enum + self.enums[enum.name] = enum + + if type_info["category"] == "handle": + handle = XrHandle.from_alias(t, self.types[alias]["data"]) + handles.append(handle) + type_info["data"] = handle + + if type_info["category"] == "struct": + struct = XrStruct.from_alias(t, self.types[alias]["data"]) + structs.append(struct) + type_info["data"] = struct + + self.types[type_info["name"]] = type_info + + # We need detailed type information during code generation + # on structs for alignment reasons. Unfortunately structs + # are parsed among other types, so there is no guarantee + # that any types needed have been parsed already, so set + # the data now. + for struct in structs: + struct.set_type_info(self.types) + + # Alias structures have enum values equivalent to those of the + # structure which they are aliased against. we need to ignore alias + # structs when populating the struct extensions list, otherwise we + # will create duplicate case entries. + if struct.alias: + continue + + for structextend in struct.structextends: + s = self.types[structextend]["data"] + s.struct_extensions.append(struct) + + self.mark_struct_dependencies(struct) + + # Guarantee everything is sorted, so code generation doesn't have + # to deal with this. + self.base_types = sorted(base_types, key=lambda base_type: base_type.name) + self.bitmasks = sorted(bitmasks, key=lambda bitmask: bitmask.name) + self.defines = defines + self.enums = OrderedDict(sorted(self.enums.items())) + self.funcpointers = sorted(funcpointers, key=lambda fp: fp.name) + self.handles = sorted(handles, key=lambda handle: handle.name) + self.structs = sorted(structs, key=lambda struct: struct.name) + +def collect_element_text(e): + return "".join(e.itertext()) + +def set_working_directory(): + path = os.path.abspath(__file__) + path = os.path.dirname(path) + os.chdir(path) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", action="count", default=0, help="increase output verbosity") + + args = parser.parse_args() + if args.verbose == 0: + LOGGER.setLevel(logging.WARNING) + elif args.verbose == 1: + LOGGER.setLevel(logging.INFO) + else: # > 1 + LOGGER.setLevel(logging.DEBUG) + + set_working_directory() + + xr_xml = "xr.xml".format(XR_XML_VERSION) + registry = XrRegistry(xr_xml) + generator = XrGenerator(registry) + + with open(WINE_OPENXR_H, "w") as f: + generator.generate_openxr_h(f) + + with open(WINE_OPENXR_THUNKS_H, "w") as f: + generator.generate_thunks_h(f, "wine_") + + with open(WINE_OPENXR_THUNKS_C, "w") as f: + generator.generate_thunks_c(f, "wine_") + +if __name__ == "__main__": + main() diff --git a/wineopenxr/openxr.c b/wineopenxr/openxr.c new file mode 100644 index 00000000..00468d1f --- /dev/null +++ b/wineopenxr/openxr.c @@ -0,0 +1,1441 @@ +#include +#include + +#define COBJMACROS +#include "initguid.h" +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "windows.h" +#include "wine/debug.h" +#include "dxgi.h" +#include "d3d11.h" +#include "d3d11_3.h" +#include "d3d12.h" + +/* we want to use the native linux header */ +#pragma push_macro("_WIN32") +#pragma push_macro("__cdecl") +#undef _WIN32 +#undef __cdecl +#define XR_USE_GRAPHICS_API_OPENGL 1 +#define XR_USE_GRAPHICS_API_VULKAN 1 +#define WINE_VK_HOST +#include "wine/vulkan.h" +#define VULKAN_H_ 1// tell dxvk-interop not to include vulkan.h +#include "dxvk-interop.h" +#undef WINE_VK_HOST +#define XR_USE_GRAPHICS_API_D3D11 1 +#define XR_USE_GRAPHICS_API_D3D12 1 +#include +#pragma pop_macro("_WIN32") +#pragma pop_macro("__cdecl") + +#include "openxr_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(openxr); + +union CompositionLayer { + XrCompositionLayerProjection projection; + XrCompositionLayerQuad quad; + XrCompositionLayerCubeKHR cube; + XrCompositionLayerDepthInfoKHR depth_info; + XrCompositionLayerCylinderKHR cylinder; + XrCompositionLayerEquirectKHR equirect; + XrCompositionLayerColorScaleBiasKHR color_scale_bias; + XrCompositionLayerEquirect2KHR equirect2; +}; + +#define heap_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) +#define heap_alloc_zero(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, s) +#define heap_free(p) HeapFree(GetProcessHeap(), 0, p) + +static void *heap_realloc(void *p, size_t s) +{ + if(!p) return heap_alloc(s); + return HeapReAlloc(GetProcessHeap(), 0, p, s); +} + +static const char WINE_VULKAN_DEVICE_EXTENSION_NAME[] = "VK_WINE_openxr_device_extensions"; +static const char WINE_VULKAN_DEVICE_VARIABLE[] = "__WINE_OPENXR_VK_DEVICE_EXTENSIONS"; + +static char *wineopenxr_strdup(const char *src) +{ + const size_t l = strlen(src) + 1; + char *r = heap_alloc(l); + strcpy(r, src); + return r; +} + +VkDevice(WINAPI *get_native_VkDevice)(VkDevice); +VkInstance(WINAPI *get_native_VkInstance)(VkInstance); +VkPhysicalDevice(WINAPI *get_native_VkPhysicalDevice)(VkPhysicalDevice); +VkPhysicalDevice(WINAPI *get_wrapped_VkPhysicalDevice)(VkInstance, VkPhysicalDevice); +VkQueue(WINAPI *get_native_VkQueue)(VkQueue); + +static void load_vk_unwrappers(void) +{ + static HMODULE h = NULL; + + if(h) + /* already loaded */ + return; + + h = LoadLibraryA("winevulkan"); + if(!h){ + WINE_ERR("unable to load winevulkan\n"); + return; + } + + get_native_VkDevice = (void*)GetProcAddress(h, "__wine_get_native_VkDevice"); + get_native_VkInstance = (void*)GetProcAddress(h, "__wine_get_native_VkInstance"); + get_native_VkPhysicalDevice = (void*)GetProcAddress(h, "__wine_get_native_VkPhysicalDevice"); + get_wrapped_VkPhysicalDevice = (void*)GetProcAddress(h, "__wine_get_wrapped_VkPhysicalDevice"); + get_native_VkQueue = (void*)GetProcAddress(h, "__wine_get_native_VkQueue"); +} + +#define XR_CURRENT_LOADER_API_LAYER_VERSION 1 +#define XR_CURRENT_LOADER_RUNTIME_VERSION 1 +#define XR_LOADER_INFO_STRUCT_VERSION 1 +#define XR_RUNTIME_INFO_STRUCT_VERSION 1 + +typedef enum XrLoaderInterfaceStructs { + XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0, + XR_LOADER_INTERFACE_STRUCT_LOADER_INFO, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST, + XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO, + XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO, +} XrLoaderInterfaceStructs; + +typedef struct XrApiLayerNextInfo XrApiLayerNextInfo; + +#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512 +#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1 +typedef struct XrApiLayerCreateInfo { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + void *loaderInstance; + char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; + XrApiLayerNextInfo *nextInfo; +} XrApiLayerCreateInfo; + +typedef XrResult(__stdcall *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info, + const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance); + +#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1 +struct XrApiLayerNextInfo { + XrLoaderInterfaceStructs structType; + uint32_t structVersion; + size_t structSize; + char layerName[XR_MAX_API_LAYER_NAME_SIZE]; + PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; + PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; + XrApiLayerNextInfo *next; +}; + +#define WINE_XR_STRUCT_NAME(x) x##_win +#define WINE_XR_STRUCT_ATTR __attribute__((ms_struct)) +#include "loader_structs.h" +#undef WINE_XR_STRUCT_ATTR +#undef WINE_XR_STRUCT_NAME + +#define WINE_XR_STRUCT_NAME(x) x##_host +#define WINE_XR_STRUCT_ATTR +#include "loader_structs.h" +#undef WINE_XR_STRUCT_ATTR +#undef WINE_XR_STRUCT_NAME + +static char *g_instance_extensions, *g_device_extensions; +static uint32_t g_physdev_vid, g_physdev_pid; + +static char *strdupA(const char *s) +{ + size_t l = strlen(s) + 1; + char *r = heap_alloc(l); + memcpy(r, s, l); + return r; +} + +static CRITICAL_SECTION session_list_lock = { NULL, -1, 0, 0, 0, 0 }; +static struct list session_list = LIST_INIT(session_list); + +static wine_XrSession *get_wrapped_XrSession(XrSession native) +{ + wine_XrSession *cursor; + + EnterCriticalSection(&session_list_lock); + + LIST_FOR_EACH_ENTRY(cursor, &session_list, wine_XrSession, entry){ + if(cursor->session == native) + break; + } + + LeaveCriticalSection(&session_list_lock); + + if(&cursor->entry == &session_list) + return NULL; + + return cursor; +} + +static void parse_extensions(const char *in, uint32_t *out_count, + char ***out_strs) +{ + char *iter, *start; + char **list, *str = strdupA(in); + uint32_t extension_count = 0, o = 0; + + iter = str; + while(*iter){ + if(*iter++ == ' ') + extension_count++; + } + /* count the one ending in NUL */ + if(iter != str) + extension_count++; + if(!extension_count){ + *out_count = 0; + *out_strs = NULL; + return; + } + + list = heap_alloc(extension_count * sizeof(char *)); + + start = iter = str; + do{ + if(*iter == ' '){ + *iter = 0; + list[o++] = strdupA(start); + WINE_TRACE("added %s to list\n", list[o-1]); + iter++; + start = iter; + }else if(*iter == 0){ + list[o++] = strdupA(start); + WINE_TRACE("added %s to list\n", list[o-1]); + break; + }else{ + iter++; + } + }while(1); + + *out_count = extension_count; + *out_strs = list; +} + +XrResult load_host_openxr_loader(void) +{ + PFN_xrGetVulkanInstanceExtensionsKHR pxrGetVulkanInstanceExtensionsKHR; + PFN_xrGetSystem pxrGetSystem; + PFN_xrGetVulkanDeviceExtensionsKHR pxrGetVulkanDeviceExtensionsKHR; + PFN_xrGetVulkanGraphicsDeviceKHR pxrGetVulkanGraphicsDeviceKHR; + PFN_xrGetVulkanGraphicsRequirementsKHR pxrGetVulkanGraphicsRequirementsKHR; + PFN_xrGetInstanceProperties pxrGetInstanceProperties; + PFN_xrEnumerateViewConfigurations pxrEnumerateViewConfigurations; + uint32_t len, i; + XrInstance instance; + XrSystemId system; + XrResult res; + VkInstance vk_instance; + VkResult vk_res; + VkPhysicalDevice vk_physdev; + VkPhysicalDeviceProperties vk_dev_props; + + static const char *xr_extensions[] = { + "XR_KHR_vulkan_enable", + }; + + if(g_instance_extensions || g_device_extensions) + /* already done */ + return XR_SUCCESS; + + load_vk_unwrappers(); + + XrInstanceCreateInfo xrCreateInfo = { + .type = XR_TYPE_INSTANCE_CREATE_INFO, + .next = NULL, + .createFlags = 0, + .applicationInfo = { + .applicationVersion = 0, + .engineVersion = 0, + .apiVersion = XR_CURRENT_API_VERSION, + }, + .enabledApiLayerCount = 0, + .enabledApiLayerNames = NULL, + .enabledExtensionCount = ARRAY_SIZE(xr_extensions), + .enabledExtensionNames = xr_extensions, + }; + + strcpy(xrCreateInfo.applicationInfo.applicationName, "wineopenxr test instance"); + strcpy(xrCreateInfo.applicationInfo.engineName, "wineopenxr test instance"); + + res = xrCreateInstance(&xrCreateInfo, &instance); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateInstance failed: %d\n", res); + return res; + } + + xrGetInstanceProcAddr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanInstanceExtensionsKHR); + xrGetInstanceProcAddr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanDeviceExtensionsKHR); + xrGetInstanceProcAddr(instance, "xrGetSystem", (PFN_xrVoidFunction *)&pxrGetSystem); + xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction *)&pxrGetVulkanGraphicsDeviceKHR); + xrGetInstanceProcAddr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction *)&pxrGetVulkanGraphicsRequirementsKHR); + xrGetInstanceProcAddr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction *)&pxrGetInstanceProperties); + xrGetInstanceProcAddr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction *)&pxrEnumerateViewConfigurations); + + XrInstanceProperties inst_props = { + .type = XR_TYPE_INSTANCE_PROPERTIES, + }; + res = pxrGetInstanceProperties(instance, &inst_props); + if(res != XR_SUCCESS) + WINE_WARN("xrGetInstanceProperties failed: %d\n", res); + + XrSystemGetInfo system_info = { + .type = XR_TYPE_SYSTEM_GET_INFO, + .formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, + }; + res = pxrGetSystem(instance, &system_info, &system); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetSystem failed: %d\n", res); + xrDestroyInstance(instance); + return res; + } + + res = pxrEnumerateViewConfigurations(instance, system, 0, &len, NULL); + if(res != XR_SUCCESS) + WINE_WARN("xrEnumerateViewConfigurations failed: %d\n", res); + XrViewConfigurationType *configs = heap_alloc(len * sizeof(*configs)); + res = pxrEnumerateViewConfigurations(instance, system, len, &len, configs); + if(res != XR_SUCCESS) + WINE_WARN("xrEnumerateViewConfigurations failed: %d\n", res); + heap_free(configs); + + XrGraphicsRequirementsVulkanKHR reqs = { + .type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, + }; + res = pxrGetVulkanGraphicsRequirementsKHR(instance, system, &reqs); + if(res != XR_SUCCESS) + WINE_WARN("xrGetVulkanGraphicsRequirementsKHR failed: %d\n", res); + + res = pxrGetVulkanInstanceExtensionsKHR(instance, system, 0, &len, NULL); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanInstanceExtensionsKHR failed: %d\n", res); + xrDestroyInstance(instance); + return res; + } + g_instance_extensions = heap_alloc(len); + res = pxrGetVulkanInstanceExtensionsKHR(instance, system, len, &len, g_instance_extensions); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanInstanceExtensionsKHR failed: %d\n", res); + xrDestroyInstance(instance); + heap_free(g_instance_extensions); + g_instance_extensions = NULL; + return res; + } + + VkApplicationInfo vk_appinfo = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pNext = NULL, + .pApplicationName = "wineopenxr test instance", + .applicationVersion = 0, + .pEngineName = "wineopenxr test instance", + .engineVersion = VK_MAKE_VERSION(1, 0, 0), + .apiVersion = VK_MAKE_VERSION(1, 1, 0), + }; + + VkInstanceCreateInfo vk_createinfo = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .pApplicationInfo = &vk_appinfo, + .enabledLayerCount = 0, + .ppEnabledLayerNames = NULL, + .enabledExtensionCount = 0, + .ppEnabledExtensionNames = NULL, + }; + + parse_extensions(g_instance_extensions, + &vk_createinfo.enabledExtensionCount, + (char ***)&vk_createinfo.ppEnabledExtensionNames); + + vk_res = vkCreateInstance(&vk_createinfo, NULL, &vk_instance); + if(vk_res != VK_SUCCESS){ + WINE_WARN("vkCreateInstance failed: %d\n", vk_res); + for(i = 0; i < vk_createinfo.enabledExtensionCount; ++i) + heap_free((void*)vk_createinfo.ppEnabledExtensionNames[i]); + heap_free((void*)vk_createinfo.ppEnabledExtensionNames); + xrDestroyInstance(instance); + heap_free(g_instance_extensions); + g_instance_extensions = NULL; + return XR_ERROR_INITIALIZATION_FAILED; + } + + for(i = 0; i < vk_createinfo.enabledExtensionCount; ++i) + heap_free((void*)vk_createinfo.ppEnabledExtensionNames[i]); + heap_free((void*)vk_createinfo.ppEnabledExtensionNames); + + res = pxrGetVulkanGraphicsDeviceKHR(instance, system, vk_instance, &vk_physdev); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanGraphicsDeviceKHR failed: %d\n", res); + xrDestroyInstance(instance); + heap_free(g_instance_extensions); + g_instance_extensions = NULL; + return res; + } + + vkGetPhysicalDeviceProperties(vk_physdev, &vk_dev_props); + g_physdev_vid = vk_dev_props.vendorID; + g_physdev_pid = vk_dev_props.deviceID; + + res = pxrGetVulkanDeviceExtensionsKHR(instance, system, 0, &len, NULL); + if(res != XR_SUCCESS){ + WINE_WARN("pxrGetVulkanDeviceExtensionsKHR fail: %d\n", res); + xrDestroyInstance(instance); + heap_free(g_instance_extensions); + g_instance_extensions = NULL; + return res; + } + g_device_extensions = heap_alloc(len); + res = pxrGetVulkanDeviceExtensionsKHR(instance, system, len, &len, g_device_extensions); + if(res != XR_SUCCESS){ + WINE_WARN("pxrGetVulkanDeviceExtensionsKHR fail: %d\n", res); + xrDestroyInstance(instance); + heap_free(g_instance_extensions); + g_instance_extensions = NULL; + heap_free(g_device_extensions); + g_device_extensions = NULL; + return res; + } + + vkDestroyInstance(vk_instance, NULL); + xrDestroyInstance(instance); + + WINE_TRACE("Got required instance extensions: %s\n", g_instance_extensions); + WINE_TRACE("Got required device extensions: %s\n", g_device_extensions); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName, + uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties) +{ + XrResult res; + uint32_t i; + + static const char *extra_extensions[] = { + "XR_KHR_D3D11_enable", + }; + + WINE_TRACE("\n"); + + res = xrEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties); + + if(res == XR_SUCCESS){ + if(properties){ + for(i = 0; i < ARRAY_SIZE(extra_extensions); ++i){ + strcpy(properties[*propertyCountOutput + i].extensionName, extra_extensions[i]); + } + *propertyCountOutput += ARRAY_SIZE(extra_extensions); + WINE_TRACE("Returning extensions:\n"); + for(i = 0; i < *propertyCountOutput; ++i){ + WINE_TRACE("\t-%s\n", properties[i].extensionName); + } + }else{ + *propertyCountOutput += ARRAY_SIZE(extra_extensions); + } + } + + return res; +} + +XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, + XrTime time, LARGE_INTEGER *performanceCounter) +{ + WINE_FIXME("unimplemented\n"); + /* FIXME */ + return XR_ERROR_INITIALIZATION_FAILED; +} + +XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, + const LARGE_INTEGER *performanceCounter, XrTime *time) +{ + WINE_FIXME("unimplemented\n"); + /* FIXME */ + return XR_ERROR_INITIALIZATION_FAILED; +} + +XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements) +{ + IDXGIFactory1 *factory; + IDXGIAdapter *adapter; + DXGI_ADAPTER_DESC adapter_desc; + HRESULT hr; + DWORD i; + + WINE_TRACE("\n"); + + hr = CreateDXGIFactory1(&IID_IDXGIFactory1, (void**)&factory); + if(FAILED(hr)){ + WINE_WARN("CreateDXGIFactory1 failed: %08x\n", hr); + return XR_ERROR_INITIALIZATION_FAILED; + } + + i = 0; + while((hr = IDXGIFactory1_EnumAdapters(factory, i++, &adapter)) == S_OK){ + hr = IDXGIAdapter_GetDesc(adapter, &adapter_desc); + if(FAILED(hr)){ + WINE_WARN("GetDesc failed: %08x\n", hr); + IDXGIAdapter_Release(adapter); + continue; + } + + IDXGIAdapter_Release(adapter); + + /* FIXME: what if we have two of the same adapters? */ + if(adapter_desc.VendorId == g_physdev_vid && + adapter_desc.DeviceId == g_physdev_pid){ + break; + } + } + + if(hr == S_OK){ + graphicsRequirements->adapterLuid = adapter_desc.AdapterLuid; + }else{ + WINE_WARN("Couldn't find matching DXGI adapter for given VkPhysicalDevice! Choosing first one...\n"); + + hr = IDXGIFactory1_EnumAdapters(factory, 0, &adapter); + if(FAILED(hr)){ + WINE_WARN("EnumAdapters(0) failed: %08x\n", hr); + IDXGIFactory1_Release(factory); + return XR_ERROR_INITIALIZATION_FAILED; + } + + hr = IDXGIAdapter_GetDesc(adapter, &adapter_desc); + if(FAILED(hr)){ + WINE_WARN("GetDesc(0) failed: %08x\n", hr); + IDXGIAdapter_Release(adapter); + IDXGIFactory1_Release(factory); + return XR_ERROR_INITIALIZATION_FAILED; + } + + IDXGIAdapter_Release(adapter); + + graphicsRequirements->adapterLuid = adapter_desc.AdapterLuid; + } + + IDXGIFactory1_Release(factory); + + /* XXX */ + graphicsRequirements->minFeatureLevel = D3D_FEATURE_LEVEL_10_0; + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements) +{ + WINE_FIXME("unimplemented\n"); + /* FIXME */ + return XR_ERROR_INITIALIZATION_FAILED; +} + +XrResult WINAPI wine_xrGetInstanceProcAddr(XrInstance instance, const char *fn_name, PFN_xrVoidFunction *out_fn) +{ + WINE_TRACE("%s\n", fn_name); + + *out_fn = wine_xr_proc_addr(fn_name); + if(!*out_fn){ + WINE_WARN("Unable to find requested function: %s\n", fn_name); + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance) +{ + XrResult res; + struct wine_XrInstance *wine_instance; + uint32_t i, j, type = 0; + XrInstanceCreateInfo our_createInfo; + uint32_t dst = 0; + char **new_list = NULL; + + WINE_TRACE("%p, %p\n", createInfo, instance); + + WINE_TRACE("Incoming extensions:\n"); + for(i = 0; i < createInfo->enabledExtensionCount; ++i){ + WINE_TRACE(" -%s\n", createInfo->enabledExtensionNames[i]); + if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D11_enable")){ + type = INSTANCE_TYPE_D3D11; + }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D12_enable")){ + type = INSTANCE_TYPE_D3D12; + }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_vulkan_enable")){ + type = INSTANCE_TYPE_VULKAN; + }else if(!strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_opengl_enable")){ + type = INSTANCE_TYPE_OPENGL; + } + } + + /* remove win32 extensions */ + for(i = 0; i < createInfo->enabledExtensionCount; ++i){ + if(strcmp(createInfo->enabledExtensionNames[i], "XR_KHR_D3D11_enable") != 0){ + if(i != dst){ + new_list[dst] = wineopenxr_strdup(createInfo->enabledExtensionNames[i]); + } + dst++; + }else{ + /* skip this one */ + if(!new_list){ + new_list = heap_alloc(createInfo->enabledExtensionCount * sizeof(char *)); + for(j = 0; j < i; ++j){ + new_list[j] = wineopenxr_strdup(createInfo->enabledExtensionNames[j]); + } + } + } + } + if(new_list){ + /* we must have removed a d3d thing, so put vulkan here */ + new_list[dst] = wineopenxr_strdup("XR_KHR_vulkan_enable"); + dst++; + + our_createInfo = *createInfo; + our_createInfo.enabledExtensionNames = (const char * const*)new_list; + our_createInfo.enabledExtensionCount = dst; + createInfo = &our_createInfo; + } + + WINE_TRACE("Enabled extensions:\n"); + for(i = 0; i < createInfo->enabledExtensionCount; ++i){ + WINE_TRACE(" -%s\n", createInfo->enabledExtensionNames[i]); + } + + wine_instance = heap_alloc_zero(sizeof(wine_XrInstance)); + + res = xrCreateInstance(createInfo, &wine_instance->instance); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateInstance failed: %d\n", res); + heap_free(wine_instance); + goto cleanup; + } + + WINE_TRACE("allocated wine instance %p for native instance %p\n", + wine_instance, wine_instance->instance); + +#define USE_XR_FUNC(x) \ + xrGetInstanceProcAddr(wine_instance->instance, #x, (PFN_xrVoidFunction *)&wine_instance->funcs.p_##x); + ALL_XR_INSTANCE_FUNCS() +#undef USE_XR_FUNC + + wine_instance->instance_type = type; + *instance = (XrInstance)wine_instance; + +cleanup: + if(createInfo == &our_createInfo){ + for(i = 0; i < our_createInfo.enabledExtensionCount; ++i){ + heap_free((void*)our_createInfo.enabledExtensionNames[i]); + } + heap_free((void*)our_createInfo.enabledExtensionNames); + } + return res; +} + +XrResult WINAPI wine_xrDestroyInstance(XrInstance instance) +{ + wine_XrInstance *wine_instance = (wine_XrInstance *)instance; + XrResult res; + + WINE_TRACE("\n"); + + res = xrDestroyInstance(wine_instance->instance); + if(res != XR_SUCCESS){ + WINE_WARN("xrDestroyInstance failed: %d\n", res); + return res; + } + + if(wine_instance->dxvk_device) + wine_instance->dxvk_device->lpVtbl->Release(wine_instance->dxvk_device); + + heap_free(wine_instance); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session) +{ + wine_XrInstance *wine_instance = (wine_XrInstance *)instance; + wine_XrSession *wine_session; + XrResult res; + XrSessionCreateInfo our_create_info; + XrGraphicsBindingVulkanKHR our_vk_binding; + + WINE_TRACE("%p, %p, %p\n", instance, createInfo, session); + + if(createInfo->next){ + switch(((XrBaseInStructure *)createInfo->next)->type){ + case XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR /* == XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR */: + { + const XrGraphicsBindingVulkanKHR *their_vk_binding = (const XrGraphicsBindingVulkanKHR *)createInfo->next; + + our_vk_binding = *their_vk_binding; + our_vk_binding.instance = get_native_VkInstance(their_vk_binding->instance); + our_vk_binding.physicalDevice = get_native_VkPhysicalDevice(their_vk_binding->physicalDevice); + our_vk_binding.device = get_native_VkDevice(their_vk_binding->device); + + our_create_info = *createInfo; + our_create_info.next = &our_vk_binding; + createInfo = &our_create_info; + + break; + } + case XR_TYPE_GRAPHICS_BINDING_D3D11_KHR: + { + const XrGraphicsBindingD3D11KHR *their_d3d11_binding = (const XrGraphicsBindingD3D11KHR *)createInfo->next; + HRESULT hr; + + hr = ID3D11Device_QueryInterface(their_d3d11_binding->device, &IID_IDXGIVkInteropDevice2, (void **)&wine_instance->dxvk_device); + if(FAILED(hr)){ + WINE_WARN("Given ID3D11Device doesn't support IDXGIVkInteropDevice. Only DXVK is supported.\n"); + return XR_ERROR_VALIDATION_FAILURE; + } + + our_vk_binding.type = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR; + our_vk_binding.next = NULL; + + wine_instance->dxvk_device->lpVtbl->GetVulkanHandles(wine_instance->dxvk_device, + &our_vk_binding.instance, &our_vk_binding.physicalDevice, &our_vk_binding.device); + + wine_instance->dxvk_device->lpVtbl->GetSubmissionQueue2(wine_instance->dxvk_device, + NULL, &our_vk_binding.queueIndex, &our_vk_binding.queueFamilyIndex); + + our_vk_binding.instance = get_native_VkInstance(our_vk_binding.instance); + our_vk_binding.physicalDevice = get_native_VkPhysicalDevice(our_vk_binding.physicalDevice); + our_vk_binding.device = get_native_VkDevice(our_vk_binding.device); + + our_create_info = *createInfo; + our_create_info.next = &our_vk_binding; + createInfo = &our_create_info; + + break; + } + default: + WINE_WARN("Unhandled graphics binding type: %d\n", ((XrBaseInStructure *)createInfo->next)->type); + break; + } + } + + wine_session = heap_alloc_zero(sizeof(*wine_session)); + + res = xrCreateSession(wine_instance->instance, createInfo, &wine_session->session); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateSession failed: %d\n", res); + heap_free(wine_session); + return res; + } + + wine_session->wine_instance = wine_instance; + + EnterCriticalSection(&session_list_lock); + + list_add_tail(&session_list, &wine_session->entry); + + LeaveCriticalSection(&session_list_lock); + + *session = (XrSession)wine_session; + + WINE_TRACE("allocated wine session %p for native session %p\n", + wine_session, wine_session->session); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrDestroySession(XrSession session) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + XrResult res; + + WINE_TRACE("%p\n", session); + + res = xrDestroySession(wine_session->session); + if(res != XR_SUCCESS){ + WINE_WARN("xrDestroySession failed: %d\n", res); + return res; + } + + heap_free(wine_session->projection_views); + heap_free(wine_session->composition_layers); + heap_free(wine_session); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo, + XrHandTrackerEXT *handTracker) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + wine_XrHandTrackerEXT *wine_handTracker; + XrResult res; + + WINE_TRACE("%p, %p, %p\n", session, createInfo, handTracker); + + wine_handTracker = heap_alloc_zero(sizeof(*wine_handTracker)); + + res = wine_session->wine_instance->funcs.p_xrCreateHandTrackerEXT(wine_session->session, createInfo, &wine_handTracker->hand_tracker); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateHandTrackerEXT failed: %d\n", res); + heap_free(wine_handTracker); + return res; + } + + wine_handTracker->wine_session = wine_session; + + *handTracker = (XrHandTrackerEXT)wine_handTracker; + + WINE_TRACE("allocated wine handTracker %p for native handTracker %p\n", + wine_handTracker, wine_handTracker->hand_tracker); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker) +{ + wine_XrHandTrackerEXT *wine_handTracker = (wine_XrHandTrackerEXT *)handTracker; + XrResult res; + + WINE_TRACE("%p\n", handTracker); + + res = wine_handTracker->wine_session->wine_instance->funcs.p_xrDestroyHandTrackerEXT(wine_handTracker->hand_tracker); + if(res != XR_SUCCESS){ + WINE_WARN("xrDestroyHandTrackerEXT failed: %d\n", res); + return res; + } + + heap_free(wine_handTracker); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrCreateSpatialAnchorMSFT(XrSession session, + const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + wine_XrSpatialAnchorMSFT *wine_anchor; + XrResult res; + + WINE_TRACE("%p, %p, %p\n", session, createInfo, anchor); + + wine_anchor = heap_alloc_zero(sizeof(*wine_anchor)); + + res = wine_session->wine_instance->funcs.p_xrCreateSpatialAnchorMSFT(wine_session->session, createInfo, &wine_anchor->spatial_anchor); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateSpatialAnchorMSFT failed: %d\n", res); + heap_free(wine_anchor); + return res; + } + + wine_anchor->wine_session = wine_session; + + *anchor = (XrSpatialAnchorMSFT)wine_anchor; + + WINE_TRACE("allocated wine spatialAnchor %p for native spatialAnchor %p\n", + wine_anchor, wine_anchor->spatial_anchor); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor) +{ + wine_XrSpatialAnchorMSFT *wine_anchor = (wine_XrSpatialAnchorMSFT *)anchor; + XrResult res; + + WINE_TRACE("%p\n", anchor); + + res = wine_anchor->wine_session->wine_instance->funcs.p_xrDestroySpatialAnchorMSFT(wine_anchor->spatial_anchor); + if(res != XR_SUCCESS){ + WINE_WARN("xrDestroySpatialAnchorMSFT failed: %d\n", res); + return res; + } + + heap_free(wine_anchor); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrNegotiateLoaderRuntimeInterface( + const XrNegotiateLoaderInfo_win *loaderInfo, + XrNegotiateRuntimeRequest_win *runtimeRequest) +{ + XrResult res; + + if(!loaderInfo || !runtimeRequest) + return XR_ERROR_INITIALIZATION_FAILED; + + if((res = load_host_openxr_loader()) != XR_SUCCESS){ + WINE_TRACE("host openxr loader failed to load runtime: %d\n", res); + return res; + } + + if(loaderInfo->structType != XR_LOADER_INTERFACE_STRUCT_LOADER_INFO || + loaderInfo->structVersion != XR_LOADER_INFO_STRUCT_VERSION || + loaderInfo->structSize != sizeof(XrNegotiateLoaderInfo_win)){ + return XR_ERROR_VALIDATION_FAILURE; + } + + if(loaderInfo->minInterfaceVersion > XR_CURRENT_LOADER_RUNTIME_VERSION || + loaderInfo->maxInterfaceVersion < XR_CURRENT_LOADER_RUNTIME_VERSION){ + return XR_ERROR_VALIDATION_FAILURE; + } + + if(runtimeRequest->structType != XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST || + runtimeRequest->structVersion != XR_RUNTIME_INFO_STRUCT_VERSION || + runtimeRequest->structSize != sizeof(XrNegotiateRuntimeRequest_win)){ + return XR_ERROR_VALIDATION_FAILURE; + } + + runtimeRequest->runtimeInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION; + runtimeRequest->getInstanceProcAddr = (PFN_xrGetInstanceProcAddr)&wine_xrGetInstanceProcAddr; + runtimeRequest->runtimeApiVersion = XR_CURRENT_API_VERSION; + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrGetVulkanGraphicsDeviceKHR(XrInstance instance, + XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice) +{ + XrResult res; + WINE_TRACE("%p, 0x%s, %p, %p\n", instance, wine_dbgstr_longlong(systemId), vkInstance, vkPhysicalDevice); + res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanGraphicsDeviceKHR(((wine_XrInstance *)instance)->instance, systemId, get_native_VkInstance(vkInstance), vkPhysicalDevice); + *vkPhysicalDevice = get_wrapped_VkPhysicalDevice(vkInstance, *vkPhysicalDevice); + return res; +} + +XrResult WINAPI wine_xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) +{ + XrResult res; + uint32_t buf_len = 0; + char *buf; + + WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), bufferCapacityInput, bufferCountOutput, buffer); + + if(bufferCapacityInput == 0){ + *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME); + return XR_SUCCESS; + } + + if(bufferCapacityInput < sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME)){ + *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME); + return XR_ERROR_SIZE_INSUFFICIENT; + } + + res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanDeviceExtensionsKHR( + ((wine_XrInstance *)instance)->instance, systemId, + 0, &buf_len, NULL); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanDeviceExtensionsKHR failed: %d\n", res); + return res; + } + + buf = heap_alloc(buf_len); + + res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanDeviceExtensionsKHR( + ((wine_XrInstance *)instance)->instance, systemId, + buf_len, &buf_len, buf); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanDeviceExtensionsKHR failed: %d\n", res); + heap_free(buf); + return res; + } + + WINE_TRACE("got device extensions: %s\n", buf); + SetEnvironmentVariableA(WINE_VULKAN_DEVICE_VARIABLE, buf); + + heap_free(buf); + + memcpy(buffer, WINE_VULKAN_DEVICE_EXTENSION_NAME, sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME)); + *bufferCountOutput = sizeof(WINE_VULKAN_DEVICE_EXTENSION_NAME); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrGetVulkanInstanceExtensionsKHR(XrInstance instance, + XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, + char *buffer) +{ + static const char win32_surface[] = "VK_KHR_surface VK_KHR_win32_surface"; + + XrResult res; + uint32_t lin_len; + + WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), bufferCapacityInput, bufferCountOutput, buffer); + + /* Linux SteamVR does not return xlib_surface, but Windows SteamVR _does_ + * return win32_surface. Some games (including hello_xr) depend on that, so + * add it here. */ + + res = ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanInstanceExtensionsKHR( + ((wine_XrInstance *)instance)->instance, systemId, + bufferCapacityInput, bufferCountOutput, buffer); + if(res == XR_SUCCESS){ + + if(bufferCapacityInput > 0){ + /* *bufferCountOutput is not required to (and sometimes does not) contain the offset to the NUL byte */ + lin_len = strlen(buffer) + 1; + + if(bufferCapacityInput < lin_len + sizeof(win32_surface)) + return XR_ERROR_SIZE_INSUFFICIENT; + + buffer[lin_len - 1] = ' '; + memcpy(&buffer[lin_len], win32_surface, sizeof(win32_surface)); + + WINE_TRACE("returning: %s\n", buffer); + *bufferCountOutput = lin_len + sizeof(win32_surface); + }else{ + *bufferCountOutput += sizeof(win32_surface) /* NUL byte included for required ' ' */; + } + } + + return res; +} + +XrResult WINAPI wine_xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData) +{ + XrResult res; + + WINE_TRACE("%p, %p\n", instance, eventData); + + res = xrPollEvent(((wine_XrInstance *)instance)->instance, eventData); + + if(res == XR_SUCCESS){ + switch(eventData->type){ + case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: + { + XrEventDataInteractionProfileChanged *evt = (XrEventDataInteractionProfileChanged *)eventData; + evt->session = (XrSession)get_wrapped_XrSession(evt->session); + break; + } + case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: + { + XrEventDataSessionStateChanged *evt = (XrEventDataSessionStateChanged *)eventData; + evt->session = (XrSession)get_wrapped_XrSession(evt->session); + break; + } + case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR: + { + XrEventDataVisibilityMaskChangedKHR *evt = (XrEventDataVisibilityMaskChangedKHR *)eventData; + evt->session = (XrSession)get_wrapped_XrSession(evt->session); + break; + } + case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: + { + XrEventDataReferenceSpaceChangePending *evt = (XrEventDataReferenceSpaceChangePending *)eventData; + evt->session = (XrSession)get_wrapped_XrSession(evt->session); + break; + } + default: + break; + } + } + + return res; +} + +XrResult WINAPI wine_xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId) +{ + wine_XrInstance *wine_instance = (wine_XrInstance *)instance; + XrResult res; + + WINE_TRACE("%p, %p, %p\n", instance, getInfo, systemId); + + res = wine_instance->funcs.p_xrGetSystem(wine_instance->instance, getInfo, systemId); + if(res == XR_SUCCESS){ + XrGraphicsRequirementsVulkanKHR vk_reqs; + + wine_instance->systemId = *systemId; + + /* required to call before graphics init stuff happens, so i stuck it here. */ + vk_reqs.type = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR; + res = wine_instance->funcs.p_xrGetVulkanGraphicsRequirementsKHR(wine_instance->instance, *systemId, &vk_reqs); + if(res != XR_SUCCESS){ + WINE_WARN("xrGetVulkanGraphicsRequirementsKHR failed: %d\n", res); + return res; + } + } + + return res; +} + +int64_t map_format_dxgi_to_vulkan(int64_t format) +{ + switch(format){ + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return VK_FORMAT_B8G8R8A8_SRGB; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + return VK_FORMAT_B8G8R8A8_UNORM; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return VK_FORMAT_R8G8B8A8_SRGB; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + return VK_FORMAT_R8G8B8A8_UNORM; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return VK_FORMAT_R32G32B32A32_SFLOAT; + + case DXGI_FORMAT_R32G32B32_FLOAT: + return VK_FORMAT_R32G32B32_SFLOAT; + + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return VK_FORMAT_R16G16B16A16_SFLOAT; + + case DXGI_FORMAT_D32_FLOAT: + return VK_FORMAT_D32_SFLOAT; + + case DXGI_FORMAT_D16_UNORM: + return VK_FORMAT_D16_UNORM; + + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return VK_FORMAT_D24_UNORM_S8_UINT; + + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return VK_FORMAT_D32_SFLOAT_S8_UINT; + + default: + WINE_WARN("Unable to map DXGI format (%lu) to Vulkan format\n", format); + return VK_FORMAT_UNDEFINED; + } +} + +int64_t map_format_vulkan_to_dxgi(int64_t format) +{ + switch(format){ + case VK_FORMAT_B8G8R8A8_SRGB: + return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; + + case VK_FORMAT_B8G8R8A8_UNORM: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case VK_FORMAT_R8G8B8A8_SRGB: + return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; + + case VK_FORMAT_R8G8B8A8_UNORM: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case VK_FORMAT_R32G32B32A32_SFLOAT: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + case VK_FORMAT_R32G32B32_SFLOAT: + return DXGI_FORMAT_R32G32B32_FLOAT; + + case VK_FORMAT_R16G16B16A16_SFLOAT: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + case VK_FORMAT_D32_SFLOAT: + return DXGI_FORMAT_D32_FLOAT; + + case VK_FORMAT_D16_UNORM: + return DXGI_FORMAT_D16_UNORM; + + case VK_FORMAT_D24_UNORM_S8_UINT: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + + default: + WINE_WARN("Unable to map Vulkan format (%lu) to DXGI format\n", format); + return DXGI_FORMAT_UNKNOWN; + } +} + +XrResult WINAPI wine_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + XrResult res; + uint32_t i, o; + + WINE_TRACE("%p, %u, %p, %p\n", session, formatCapacityInput, formatCountOutput, formats); + + res = xrEnumerateSwapchainFormats(wine_session->session, formatCapacityInput, formatCountOutput, formats); + + if(wine_session->wine_instance->instance_type == INSTANCE_TYPE_D3D11){ + if(res == XR_SUCCESS && formatCapacityInput && formats){ + o = 0; + for(i = 0; i < *formatCountOutput; ++i){ + int64_t mapped = map_format_vulkan_to_dxgi(formats[i]); + if(mapped != DXGI_FORMAT_UNKNOWN){ + formats[o++] = mapped; + } + } + *formatCountOutput = o; + } + } + + return res; +} + +XrResult WINAPI wine_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + wine_XrSwapchain *wine_swapchain; + XrSwapchainCreateInfo our_createInfo; + XrResult res; + + WINE_TRACE("%p, %p, %p\n", session, createInfo, swapchain); + + wine_swapchain = heap_alloc_zero(sizeof(*wine_swapchain)); + wine_swapchain->create_info = *createInfo; + + if(wine_session->wine_instance->instance_type == INSTANCE_TYPE_D3D11){ + our_createInfo = *createInfo; + our_createInfo.format = map_format_dxgi_to_vulkan(createInfo->format); + if(our_createInfo.format == VK_FORMAT_UNDEFINED){ + WINE_ERR("unable to set Vulkan format\n"); + heap_free(wine_swapchain); + return XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED; + } + createInfo = &our_createInfo; + } + + res = xrCreateSwapchain(((wine_XrSession *)session)->session, createInfo, &wine_swapchain->swapchain); + if(res != XR_SUCCESS){ + WINE_WARN("xrCreateSwapchain failed: %d\n", res); + heap_free(wine_swapchain); + return res; + } + + wine_swapchain->wine_session = wine_session; + *swapchain = (XrSwapchain)wine_swapchain; + + WINE_TRACE("allocated wine swapchain %p for native swapchain %p\n", + wine_swapchain, wine_swapchain->swapchain); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrDestroySwapchain(XrSwapchain swapchain) +{ + wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain; + XrResult res; + + WINE_TRACE("%p\n", swapchain); + + res = xrDestroySwapchain(wine_swapchain->swapchain); + if(res != XR_SUCCESS){ + WINE_WARN("xrDestroySwapchain failed: %d\n", res); + return res; + } + + heap_free(wine_swapchain); + + return XR_SUCCESS; +} + +XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images) +{ + wine_XrSwapchain *wine_swapchain = (wine_XrSwapchain *)swapchain; + wine_XrInstance *wine_instance = wine_swapchain->wine_session->wine_instance; + XrResult res; + XrSwapchainImageVulkanKHR *our_images; + XrSwapchainImageBaseHeader *their_images = images; + HRESULT hr; + uint32_t i; + + WINE_TRACE("%p, %u, %p, %p\n", swapchain, imageCapacityInput, imageCountOutput, images); + + if(images){ + if(wine_instance->instance_type == INSTANCE_TYPE_D3D11){ + our_images = heap_alloc(sizeof(*our_images) * imageCapacityInput); + for(i = 0; i < imageCapacityInput; ++i){ + our_images[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; + } + images = (XrSwapchainImageBaseHeader *)our_images; + } + } + + res = xrEnumerateSwapchainImages(wine_swapchain->swapchain, imageCapacityInput, imageCountOutput, images); + + if(images && res == XR_SUCCESS){ + if(wine_instance->instance_type == INSTANCE_TYPE_D3D11){ + D3D11_TEXTURE2D_DESC1 desc; + + desc.Width = wine_swapchain->create_info.width; + desc.Height = wine_swapchain->create_info.height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = wine_swapchain->create_info.format; + WINE_TRACE("creating dxvk texture with dxgi format %d (%x)\n", + desc.Format, desc.Format); + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + desc.TextureLayout = D3D11_TEXTURE_LAYOUT_UNDEFINED; + + XrSwapchainImageD3D11KHR *their_d3d11 = (XrSwapchainImageD3D11KHR *)their_images; + for(i = 0; i < *imageCountOutput; ++i){ + hr = wine_instance->dxvk_device->lpVtbl->CreateTexture2DFromVkImage(wine_instance->dxvk_device, + &desc, our_images[i].image, &their_d3d11[i].texture); + if(FAILED(hr)){ + WINE_WARN("Failed to create DXVK texture from VkImage: %08x\n", hr); + return XR_ERROR_INSTANCE_LOST; + } + WINE_TRACE("Successfully allocated texture %p\n", their_d3d11[i].texture); + } + + heap_free(our_images); + } + } + + return res; +} + +static XrCompositionLayerBaseHeader *convert_XrCompositionLayer(wine_XrSession *wine_session, + const XrCompositionLayerBaseHeader *in_layer, CompositionLayer *out_layer, + uint32_t *view_idx) +{ + uint32_t i; + + switch(in_layer->type){ + case XR_TYPE_COMPOSITION_LAYER_CUBE_KHR: { + out_layer->cube = *(const XrCompositionLayerCubeKHR *)in_layer; + out_layer->cube.swapchain = ((wine_XrSwapchain *)out_layer->cube.swapchain)->swapchain; + break; + } + + case XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR: + out_layer->cylinder = *(const XrCompositionLayerCylinderKHR *)in_layer; + out_layer->cylinder.subImage.swapchain = ((wine_XrSwapchain *)out_layer->cylinder.subImage.swapchain)->swapchain; + break; + + case XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR: + out_layer->depth_info = *(const XrCompositionLayerDepthInfoKHR *)in_layer; + out_layer->depth_info.subImage.swapchain = ((wine_XrSwapchain *)out_layer->depth_info.subImage.swapchain)->swapchain; + break; + + case XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR: + out_layer->equirect = *(const XrCompositionLayerEquirectKHR *)in_layer; + out_layer->equirect.subImage.swapchain = ((wine_XrSwapchain *)out_layer->equirect.subImage.swapchain)->swapchain; + break; + + case XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR: + out_layer->equirect2 = *(const XrCompositionLayerEquirect2KHR *)in_layer; + out_layer->equirect2.subImage.swapchain = ((wine_XrSwapchain *)out_layer->equirect2.subImage.swapchain)->swapchain; + break; + + case XR_TYPE_COMPOSITION_LAYER_PROJECTION: + out_layer->projection = *(const XrCompositionLayerProjection *)in_layer; + + if(out_layer->projection.viewCount + *view_idx > wine_session->projection_view_count){ + wine_session->projection_view_count = out_layer->projection.viewCount + *view_idx; + wine_session->projection_views = heap_realloc(wine_session->projection_views, + sizeof(XrCompositionLayerProjectionView) * wine_session->projection_view_count); + } + + out_layer->projection.views = &wine_session->projection_views[*view_idx]; + memcpy((void*)out_layer->projection.views, ((const XrCompositionLayerProjection *)in_layer)->views, + sizeof(XrCompositionLayerProjectionView) * out_layer->projection.viewCount); + for(i = 0; i < out_layer->projection.viewCount; ++i){ + ((XrCompositionLayerProjectionView *)&out_layer->projection.views[i])->subImage.swapchain = + ((wine_XrSwapchain *)out_layer->projection.views[i].subImage.swapchain)->swapchain; + } + + *view_idx += out_layer->projection.viewCount; + break; + + case XR_TYPE_COMPOSITION_LAYER_QUAD: + out_layer->quad = *(const XrCompositionLayerQuad *)in_layer; + out_layer->quad.subImage.swapchain = ((wine_XrSwapchain *)out_layer->quad.subImage.swapchain)->swapchain; + break; + + case XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR: + /* no conversion needed */ + return (XrCompositionLayerBaseHeader *)in_layer; + + default: + WINE_WARN("Unknown composition in_layer type: %d\n", in_layer->type); + return (XrCompositionLayerBaseHeader *)in_layer; + } + + return (XrCompositionLayerBaseHeader *)out_layer; +} + +XrResult WINAPI wine_xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo) +{ + wine_XrSession *wine_session = (wine_XrSession *)session; + XrFrameEndInfo our_frameEndInfo; + uint32_t i, view_idx = 0; + + WINE_TRACE("%p, %p\n", session, frameEndInfo); + + if(frameEndInfo->layerCount > wine_session->composition_layer_count){ + heap_free(wine_session->composition_layers); + wine_session->composition_layers = heap_alloc(frameEndInfo->layerCount * sizeof(*wine_session->composition_layers)); + heap_free(wine_session->composition_layer_ptrs); + wine_session->composition_layer_ptrs = heap_alloc(frameEndInfo->layerCount * sizeof(*wine_session->composition_layer_ptrs)); + wine_session->composition_layer_count = frameEndInfo->layerCount; + } + + for(i = 0; i < frameEndInfo->layerCount; ++i){ + wine_session->composition_layer_ptrs[i] = + convert_XrCompositionLayer(wine_session, + frameEndInfo->layers[i], &wine_session->composition_layers[i], + &view_idx); + } + + our_frameEndInfo = *frameEndInfo; + our_frameEndInfo.layers = (const XrCompositionLayerBaseHeader *const *)wine_session->composition_layer_ptrs; + + return xrEndFrame(((wine_XrSession *)session)->session, &our_frameEndInfo); +} + +/* wineopenxr API */ +XrResult WINAPI __wineopenxr_GetVulkanInstanceExtensions(uint32_t buflen, uint32_t *outlen, char *buf) +{ + XrResult res; + + WINE_TRACE("\n"); + + if((res = load_host_openxr_loader()) != XR_SUCCESS){ + WINE_TRACE("host openxr loader failed to load runtime: %d\n", res); + return res; + } + + if(buflen < strlen(g_instance_extensions) + 1 || !buf){ + *outlen = strlen(g_instance_extensions) + 1; + return XR_SUCCESS; + } + + *outlen = strlen(g_instance_extensions) + 1; + strcpy(buf, g_instance_extensions); + + return XR_SUCCESS; +} + +/* wineopenxr API */ +XrResult WINAPI __wineopenxr_GetVulkanDeviceExtensions(uint32_t buflen, uint32_t *outlen, char *buf) +{ + XrResult res; + + WINE_TRACE("\n"); + + if((res = load_host_openxr_loader()) != XR_SUCCESS){ + WINE_TRACE("host openxr loader failed to load runtime: %d\n", res); + return res; + } + + if(buflen < strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1 || !buf){ + *outlen = strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1; + return XR_SUCCESS; + } + + SetEnvironmentVariableA(WINE_VULKAN_DEVICE_VARIABLE, g_device_extensions); + *outlen = strlen(WINE_VULKAN_DEVICE_EXTENSION_NAME) + 1; + strcpy(buf, WINE_VULKAN_DEVICE_EXTENSION_NAME); + + return XR_SUCCESS; +} diff --git a/wineopenxr/openxr_private.h b/wineopenxr/openxr_private.h new file mode 100644 index 00000000..6d937444 --- /dev/null +++ b/wineopenxr/openxr_private.h @@ -0,0 +1,85 @@ +#include "openxr_thunks.h" + +#include "wine/list.h" + +#define INSTANCE_TYPE_VULKAN 1 +#define INSTANCE_TYPE_OPENGL 2 +#define INSTANCE_TYPE_D3D11 3 +#define INSTANCE_TYPE_D3D12 4 + +struct IDXGIVkInteropDevice2; +typedef struct IDXGIVkInteropDevice2 IDXGIVkInteropDevice2; + +typedef struct wine_XrInstance { + XrInstance instance; + struct openxr_instance_funcs funcs; + + VkInstance vk_instance; + VkPhysicalDevice vk_phys_dev; + + uint32_t instance_type; + XrSystemId systemId; + + IDXGIVkInteropDevice2 *dxvk_device; +} wine_XrInstance; + +union CompositionLayer; +typedef union CompositionLayer CompositionLayer; + +typedef struct wine_XrSession { + XrSession session; + struct wine_XrInstance *wine_instance; + + struct list entry; + + uint32_t composition_layer_count; + CompositionLayer *composition_layers; + XrCompositionLayerBaseHeader **composition_layer_ptrs; + + uint32_t projection_view_count; + XrCompositionLayerProjectionView *projection_views; +} wine_XrSession; + +typedef struct wine_XrHandTrackerEXT { + XrHandTrackerEXT hand_tracker; + struct wine_XrSession *wine_session; +} wine_XrHandTrackerEXT; + +typedef struct wine_XrSpatialAnchorMSFT { + XrSpatialAnchorMSFT spatial_anchor; + struct wine_XrSession *wine_session; +} wine_XrSpatialAnchorMSFT; + +typedef struct wine_XrSwapchain{ + XrSwapchain swapchain; + struct wine_XrSession *wine_session; + + XrSwapchainCreateInfo create_info; +} wine_XrSwapchain; + +struct openxr_func { + const char *name; + void *func; +}; + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) + +extern void *wine_xr_proc_addr(const char *name); + +extern XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName, + uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties); +extern XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, + XrTime time, LARGE_INTEGER *performanceCounter); +extern XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, + const LARGE_INTEGER *performanceCounter, XrTime *time); +extern XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements); +extern XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, + XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements); + +extern VkDevice (WINAPI *get_native_VkDevice)(VkDevice); +extern VkInstance (WINAPI *get_native_VkInstance)(VkInstance); +extern VkPhysicalDevice (WINAPI *get_native_VkPhysicalDevice)(VkPhysicalDevice); +extern VkPhysicalDevice (WINAPI *get_wrapped_VkPhysicalDevice)(VkInstance, VkPhysicalDevice); +extern VkQueue (WINAPI *get_native_VkQueue)(VkQueue); +extern XrResult load_host_openxr_loader(void); diff --git a/wineopenxr/openxr_thunks.c b/wineopenxr/openxr_thunks.c new file mode 100644 index 00000000..d2c2627c --- /dev/null +++ b/wineopenxr/openxr_thunks.c @@ -0,0 +1,561 @@ +/* Automatically generated from OpenXR xr.xml; DO NOT EDIT! + * + * This file is generated from OpenXR xr.xml file covered + * by the following copyright and permission notice: + * + * Copyright (c) 2017-2020 The Khronos Group Inc. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + * ------------------------------------------------------------------------ + * + * This file, xr.xml, is the OpenXR API Registry. It is a critically important + * and normative part of the OpenXR Specification, including a canonical + * machine-readable definition of the API, parameter and member validation + * language incorporated into the Specification and reference pages, and other + * material which is registered by Khronos, such as tags used by extension and + * layer authors. The only authoritative version of xr.xml is the one + * maintained in the master branch of the Khronos OpenXR GitHub project. + * + */ + +#include "wine/debug.h" +#include "wine/vulkan.h" +#include "d3d11.h" +#include "d3d12.h" +#define WINE_XR_HOST +#include "wineopenxr.h" +#include "openxr_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(openxr); + +#if defined(USE_STRUCT_CONVERSION) +#endif /* USE_STRUCT_CONVERSION */ + +XrResult convert_XrInstanceCreateInfo_struct_chain(const void *next, XrInstanceCreateInfo *out_struct) +{ + XrBaseOutStructure *out_header = (XrBaseOutStructure *)out_struct; + const XrBaseInStructure *in_header; + + out_header->next = NULL; + + for (in_header = next; in_header; in_header = in_header->next) + { + switch (in_header->type) + { + case XR_TYPE_INSTANCE_CREATE_INFO: + break; + + default: + WINE_FIXME("Application requested a linked structure of type %u.\n", in_header->type); + } + } + + return XR_SUCCESS; +} + +void free_XrInstanceCreateInfo_struct_chain(XrInstanceCreateInfo *s) +{ + XrBaseOutStructure *header = (void *)s->next; + + while (header) + { + void *prev = header; + header = header->next; + HeapFree(GetProcessHeap(), 0, prev); + } + + s->next = NULL; +} + +XrResult WINAPI wine_xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo *acquireInfo, uint32_t *index) +{ + WINE_TRACE("%p, %p, %p\n", swapchain, acquireInfo, index); + return xrAcquireSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, acquireInfo, index); +} + +XrResult WINAPI wine_xrApplyHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo, const XrHapticBaseHeader *hapticFeedback) +{ + WINE_TRACE("%p, %p, %p\n", session, hapticActionInfo, hapticFeedback); + return xrApplyHapticFeedback(((wine_XrSession *)session)->session, hapticActionInfo, hapticFeedback); +} + +XrResult WINAPI wine_xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttachInfo *attachInfo) +{ + WINE_TRACE("%p, %p\n", session, attachInfo); + return xrAttachSessionActionSets(((wine_XrSession *)session)->session, attachInfo); +} + +XrResult WINAPI wine_xrBeginFrame(XrSession session, const XrFrameBeginInfo *frameBeginInfo) +{ + WINE_TRACE("%p, %p\n", session, frameBeginInfo); + return xrBeginFrame(((wine_XrSession *)session)->session, frameBeginInfo); +} + +XrResult WINAPI wine_xrBeginSession(XrSession session, const XrSessionBeginInfo *beginInfo) +{ + WINE_TRACE("%p, %p\n", session, beginInfo); + return xrBeginSession(((wine_XrSession *)session)->session, beginInfo); +} + +XrResult WINAPI wine_xrCreateAction(XrActionSet actionSet, const XrActionCreateInfo *createInfo, XrAction *action) +{ + WINE_TRACE("%p, %p, %p\n", actionSet, createInfo, action); + return xrCreateAction(actionSet, createInfo, action); +} + +XrResult WINAPI wine_xrCreateActionSet(XrInstance instance, const XrActionSetCreateInfo *createInfo, XrActionSet *actionSet) +{ + WINE_TRACE("%p, %p, %p\n", instance, createInfo, actionSet); + return xrCreateActionSet(((wine_XrInstance *)instance)->instance, createInfo, actionSet); +} + +XrResult WINAPI wine_xrCreateActionSpace(XrSession session, const XrActionSpaceCreateInfo *createInfo, XrSpace *space) +{ + WINE_TRACE("%p, %p, %p\n", session, createInfo, space); + return xrCreateActionSpace(((wine_XrSession *)session)->session, createInfo, space); +} + +static XrResult WINAPI wine_xrCreateHandMeshSpaceMSFT(XrHandTrackerEXT handTracker, const XrHandMeshSpaceCreateInfoMSFT *createInfo, XrSpace *space) +{ + WINE_TRACE("%p, %p, %p\n", handTracker, createInfo, space); + return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrCreateHandMeshSpaceMSFT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, createInfo, space); +} + +XrResult WINAPI wine_xrCreateReferenceSpace(XrSession session, const XrReferenceSpaceCreateInfo *createInfo, XrSpace *space) +{ + WINE_TRACE("%p, %p, %p\n", session, createInfo, space); + return xrCreateReferenceSpace(((wine_XrSession *)session)->session, createInfo, space); +} + +static XrResult WINAPI wine_xrCreateSpatialAnchorSpaceMSFT(XrSession session, const XrSpatialAnchorSpaceCreateInfoMSFT *createInfo, XrSpace *space) +{ + WINE_TRACE("%p, %p, %p\n", session, createInfo, space); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrCreateSpatialAnchorSpaceMSFT(((wine_XrSession *)session)->session, createInfo, space); +} + +static XrResult WINAPI wine_xrCreateSpatialGraphNodeSpaceMSFT(XrSession session, const XrSpatialGraphNodeSpaceCreateInfoMSFT *createInfo, XrSpace *space) +{ + WINE_TRACE("%p, %p, %p\n", session, createInfo, space); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrCreateSpatialGraphNodeSpaceMSFT(((wine_XrSession *)session)->session, createInfo, space); +} + +XrResult WINAPI wine_xrDestroyAction(XrAction action) +{ + WINE_TRACE("%p\n", action); + return xrDestroyAction(action); +} + +XrResult WINAPI wine_xrDestroyActionSet(XrActionSet actionSet) +{ + WINE_TRACE("%p\n", actionSet); + return xrDestroyActionSet(actionSet); +} + +XrResult WINAPI wine_xrDestroySpace(XrSpace space) +{ + WINE_TRACE("%p\n", space); + return xrDestroySpace(space); +} + +XrResult WINAPI wine_xrEndSession(XrSession session) +{ + WINE_TRACE("%p\n", session); + return xrEndSession(((wine_XrSession *)session)->session); +} + +XrResult WINAPI wine_xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrApiLayerProperties *properties) +{ + WINE_TRACE("%u, %p, %p\n", propertyCapacityInput, propertyCountOutput, properties); + return xrEnumerateApiLayerProperties(propertyCapacityInput, propertyCountOutput, properties); +} + +XrResult WINAPI wine_xrEnumerateBoundSourcesForAction(XrSession session, const XrBoundSourcesForActionEnumerateInfo *enumerateInfo, uint32_t sourceCapacityInput, uint32_t *sourceCountOutput, XrPath *sources) +{ + WINE_TRACE("%p, %p, %u, %p, %p\n", session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources); + return xrEnumerateBoundSourcesForAction(((wine_XrSession *)session)->session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources); +} + +XrResult WINAPI wine_xrEnumerateEnvironmentBlendModes(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t *environmentBlendModeCountOutput, XrEnvironmentBlendMode *environmentBlendModes) +{ + WINE_TRACE("%p, 0x%s, %#x, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes); + return xrEnumerateEnvironmentBlendModes(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes); +} + +XrResult WINAPI wine_xrEnumerateReferenceSpaces(XrSession session, uint32_t spaceCapacityInput, uint32_t *spaceCountOutput, XrReferenceSpaceType *spaces) +{ + WINE_TRACE("%p, %u, %p, %p\n", session, spaceCapacityInput, spaceCountOutput, spaces); + return xrEnumerateReferenceSpaces(((wine_XrSession *)session)->session, spaceCapacityInput, spaceCountOutput, spaces); +} + +XrResult WINAPI wine_xrEnumerateViewConfigurationViews(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrViewConfigurationView *views) +{ + WINE_TRACE("%p, 0x%s, %#x, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, viewCapacityInput, viewCountOutput, views); + return xrEnumerateViewConfigurationViews(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views); +} + +XrResult WINAPI wine_xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t *viewConfigurationTypeCountOutput, XrViewConfigurationType *viewConfigurationTypes) +{ + WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes); + return xrEnumerateViewConfigurations(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes); +} + +XrResult WINAPI wine_xrGetActionStateBoolean(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateBoolean *state) +{ + WINE_TRACE("%p, %p, %p\n", session, getInfo, state); + return xrGetActionStateBoolean(((wine_XrSession *)session)->session, getInfo, state); +} + +XrResult WINAPI wine_xrGetActionStateFloat(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateFloat *state) +{ + WINE_TRACE("%p, %p, %p\n", session, getInfo, state); + return xrGetActionStateFloat(((wine_XrSession *)session)->session, getInfo, state); +} + +XrResult WINAPI wine_xrGetActionStatePose(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStatePose *state) +{ + WINE_TRACE("%p, %p, %p\n", session, getInfo, state); + return xrGetActionStatePose(((wine_XrSession *)session)->session, getInfo, state); +} + +XrResult WINAPI wine_xrGetActionStateVector2f(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateVector2f *state) +{ + WINE_TRACE("%p, %p, %p\n", session, getInfo, state); + return xrGetActionStateVector2f(((wine_XrSession *)session)->session, getInfo, state); +} + +XrResult WINAPI wine_xrGetCurrentInteractionProfile(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState *interactionProfile) +{ + WINE_TRACE("%p, 0x%s, %p\n", session, wine_dbgstr_longlong(topLevelUserPath), interactionProfile); + return xrGetCurrentInteractionProfile(((wine_XrSession *)session)->session, topLevelUserPath, interactionProfile); +} + +XrResult WINAPI wine_xrGetInputSourceLocalizedName(XrSession session, const XrInputSourceLocalizedNameGetInfo *getInfo, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) +{ + WINE_TRACE("%p, %p, %u, %p, %p\n", session, getInfo, bufferCapacityInput, bufferCountOutput, buffer); + return xrGetInputSourceLocalizedName(((wine_XrSession *)session)->session, getInfo, bufferCapacityInput, bufferCountOutput, buffer); +} + +XrResult WINAPI wine_xrGetInstanceProperties(XrInstance instance, XrInstanceProperties *instanceProperties) +{ + WINE_TRACE("%p, %p\n", instance, instanceProperties); + return xrGetInstanceProperties(((wine_XrInstance *)instance)->instance, instanceProperties); +} + +static XrResult WINAPI wine_xrGetOpenGLGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR *graphicsRequirements) +{ + WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), graphicsRequirements); + return ((wine_XrInstance *)instance)->funcs.p_xrGetOpenGLGraphicsRequirementsKHR(((wine_XrInstance *)instance)->instance, systemId, graphicsRequirements); +} + +XrResult WINAPI wine_xrGetReferenceSpaceBoundsRect(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df *bounds) +{ + WINE_TRACE("%p, %#x, %p\n", session, referenceSpaceType, bounds); + return xrGetReferenceSpaceBoundsRect(((wine_XrSession *)session)->session, referenceSpaceType, bounds); +} + +XrResult WINAPI wine_xrGetSystemProperties(XrInstance instance, XrSystemId systemId, XrSystemProperties *properties) +{ + WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), properties); + return xrGetSystemProperties(((wine_XrInstance *)instance)->instance, systemId, properties); +} + +XrResult WINAPI wine_xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties *configurationProperties) +{ + WINE_TRACE("%p, 0x%s, %#x, %p\n", instance, wine_dbgstr_longlong(systemId), viewConfigurationType, configurationProperties); + return xrGetViewConfigurationProperties(((wine_XrInstance *)instance)->instance, systemId, viewConfigurationType, configurationProperties); +} + +static XrResult WINAPI wine_xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR *visibilityMask) +{ + WINE_TRACE("%p, %#x, %u, %#x, %p\n", session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrGetVisibilityMaskKHR(((wine_XrSession *)session)->session, viewConfigurationType, viewIndex, visibilityMaskType, visibilityMask); +} + +static XrResult WINAPI wine_xrGetVulkanGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR *graphicsRequirements) +{ + WINE_TRACE("%p, 0x%s, %p\n", instance, wine_dbgstr_longlong(systemId), graphicsRequirements); + return ((wine_XrInstance *)instance)->funcs.p_xrGetVulkanGraphicsRequirementsKHR(((wine_XrInstance *)instance)->instance, systemId, graphicsRequirements); +} + +static XrResult WINAPI wine_xrLocateHandJointsEXT(XrHandTrackerEXT handTracker, const XrHandJointsLocateInfoEXT *locateInfo, XrHandJointLocationsEXT *locations) +{ + WINE_TRACE("%p, %p, %p\n", handTracker, locateInfo, locations); + return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrLocateHandJointsEXT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, locateInfo, locations); +} + +XrResult WINAPI wine_xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation *location) +{ + WINE_TRACE("%p, %p, 0x%s, %p\n", space, baseSpace, wine_dbgstr_longlong(time), location); + return xrLocateSpace(space, baseSpace, time, location); +} + +XrResult WINAPI wine_xrLocateViews(XrSession session, const XrViewLocateInfo *viewLocateInfo, XrViewState *viewState, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrView *views) +{ + WINE_TRACE("%p, %p, %p, %u, %p, %p\n", session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views); + return xrLocateViews(((wine_XrSession *)session)->session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views); +} + +XrResult WINAPI wine_xrPathToString(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) +{ + WINE_TRACE("%p, 0x%s, %u, %p, %p\n", instance, wine_dbgstr_longlong(path), bufferCapacityInput, bufferCountOutput, buffer); + return xrPathToString(((wine_XrInstance *)instance)->instance, path, bufferCapacityInput, bufferCountOutput, buffer); +} + +static XrResult WINAPI wine_xrPerfSettingsSetPerformanceLevelEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level) +{ + WINE_TRACE("%p, %#x, %#x\n", session, domain, level); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrPerfSettingsSetPerformanceLevelEXT(((wine_XrSession *)session)->session, domain, level); +} + +XrResult WINAPI wine_xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo *releaseInfo) +{ + WINE_TRACE("%p, %p\n", swapchain, releaseInfo); + return xrReleaseSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, releaseInfo); +} + +XrResult WINAPI wine_xrRequestExitSession(XrSession session) +{ + WINE_TRACE("%p\n", session); + return xrRequestExitSession(((wine_XrSession *)session)->session); +} + +XrResult WINAPI wine_xrResultToString(XrInstance instance, XrResult value, char buffer[]) +{ + WINE_TRACE("%p, %#x, %p\n", instance, value, buffer); + return xrResultToString(((wine_XrInstance *)instance)->instance, value, buffer); +} + +static XrResult WINAPI wine_xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive) +{ + WINE_TRACE("%p, 0x%s, 0x%s, %u\n", session, wine_dbgstr_longlong(interactionProfile), wine_dbgstr_longlong(topLevelPath), isActive); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceActiveEXT(((wine_XrSession *)session)->session, interactionProfile, topLevelPath, isActive); +} + +static XrResult WINAPI wine_xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose) +{ + WINE_TRACE("%p, 0x%s, 0x%s, %p, \n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), space, pose); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceLocationEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, space, pose); +} + +static XrResult WINAPI wine_xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state) +{ + WINE_TRACE("%p, 0x%s, 0x%s, %u\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateBoolEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state); +} + +static XrResult WINAPI wine_xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state) +{ + WINE_TRACE("%p, 0x%s, 0x%s, %f\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateFloatEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state); +} + +static XrResult WINAPI wine_xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state) +{ + WINE_TRACE("%p, 0x%s, 0x%s, %f, %f\n", session, wine_dbgstr_longlong(topLevelPath), wine_dbgstr_longlong(inputSourcePath), state.x, state.y); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrSetInputDeviceStateVector2fEXT(((wine_XrSession *)session)->session, topLevelPath, inputSourcePath, state); +} + +XrResult WINAPI wine_xrStopHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo) +{ + WINE_TRACE("%p, %p\n", session, hapticActionInfo); + return xrStopHapticFeedback(((wine_XrSession *)session)->session, hapticActionInfo); +} + +XrResult WINAPI wine_xrStringToPath(XrInstance instance, const char *pathString, XrPath *path) +{ + WINE_TRACE("%p, %p, %p\n", instance, pathString, path); + return xrStringToPath(((wine_XrInstance *)instance)->instance, pathString, path); +} + +XrResult WINAPI wine_xrStructureTypeToString(XrInstance instance, XrStructureType value, char buffer[]) +{ + WINE_TRACE("%p, %#x, %p\n", instance, value, buffer); + return xrStructureTypeToString(((wine_XrInstance *)instance)->instance, value, buffer); +} + +XrResult WINAPI wine_xrSuggestInteractionProfileBindings(XrInstance instance, const XrInteractionProfileSuggestedBinding *suggestedBindings) +{ + WINE_TRACE("%p, %p\n", instance, suggestedBindings); + return xrSuggestInteractionProfileBindings(((wine_XrInstance *)instance)->instance, suggestedBindings); +} + +XrResult WINAPI wine_xrSyncActions(XrSession session, const XrActionsSyncInfo *syncInfo) +{ + WINE_TRACE("%p, %p\n", session, syncInfo); + return xrSyncActions(((wine_XrSession *)session)->session, syncInfo); +} + +static XrResult WINAPI wine_xrThermalGetTemperatureTrendEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT *notificationLevel, float *tempHeadroom, float *tempSlope) +{ + WINE_TRACE("%p, %#x, %p, %p, %p\n", session, domain, notificationLevel, tempHeadroom, tempSlope); + return ((wine_XrSession *)session)->wine_instance->funcs.p_xrThermalGetTemperatureTrendEXT(((wine_XrSession *)session)->session, domain, notificationLevel, tempHeadroom, tempSlope); +} + +static XrResult WINAPI wine_xrUpdateHandMeshMSFT(XrHandTrackerEXT handTracker, const XrHandMeshUpdateInfoMSFT *updateInfo, XrHandMeshMSFT *handMesh) +{ + WINE_TRACE("%p, %p, %p\n", handTracker, updateInfo, handMesh); + return ((wine_XrHandTrackerEXT *)handTracker)->wine_session->wine_instance->funcs.p_xrUpdateHandMeshMSFT(((wine_XrHandTrackerEXT *)handTracker)->hand_tracker, updateInfo, handMesh); +} + +XrResult WINAPI wine_xrWaitFrame(XrSession session, const XrFrameWaitInfo *frameWaitInfo, XrFrameState *frameState) +{ + WINE_TRACE("%p, %p, %p\n", session, frameWaitInfo, frameState); + return xrWaitFrame(((wine_XrSession *)session)->session, frameWaitInfo, frameState); +} + +XrResult WINAPI wine_xrWaitSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageWaitInfo *waitInfo) +{ + WINE_TRACE("%p, %p\n", swapchain, waitInfo); + return xrWaitSwapchainImage(((wine_XrSwapchain *)swapchain)->swapchain, waitInfo); +} + +static const struct openxr_func xr_dispatch_table[] = +{ + {"xrAcquireSwapchainImage", &wine_xrAcquireSwapchainImage}, + {"xrApplyHapticFeedback", &wine_xrApplyHapticFeedback}, + {"xrAttachSessionActionSets", &wine_xrAttachSessionActionSets}, + {"xrBeginFrame", &wine_xrBeginFrame}, + {"xrBeginSession", &wine_xrBeginSession}, + {"xrConvertTimeToWin32PerformanceCounterKHR", &wine_xrConvertTimeToWin32PerformanceCounterKHR}, + {"xrConvertWin32PerformanceCounterToTimeKHR", &wine_xrConvertWin32PerformanceCounterToTimeKHR}, + {"xrCreateAction", &wine_xrCreateAction}, + {"xrCreateActionSet", &wine_xrCreateActionSet}, + {"xrCreateActionSpace", &wine_xrCreateActionSpace}, + {"xrCreateHandMeshSpaceMSFT", &wine_xrCreateHandMeshSpaceMSFT}, + {"xrCreateHandTrackerEXT", &wine_xrCreateHandTrackerEXT}, + {"xrCreateInstance", &wine_xrCreateInstance}, + {"xrCreateReferenceSpace", &wine_xrCreateReferenceSpace}, + {"xrCreateSession", &wine_xrCreateSession}, + {"xrCreateSpatialAnchorMSFT", &wine_xrCreateSpatialAnchorMSFT}, + {"xrCreateSpatialAnchorSpaceMSFT", &wine_xrCreateSpatialAnchorSpaceMSFT}, + {"xrCreateSpatialGraphNodeSpaceMSFT", &wine_xrCreateSpatialGraphNodeSpaceMSFT}, + {"xrCreateSwapchain", &wine_xrCreateSwapchain}, + {"xrDestroyAction", &wine_xrDestroyAction}, + {"xrDestroyActionSet", &wine_xrDestroyActionSet}, + {"xrDestroyHandTrackerEXT", &wine_xrDestroyHandTrackerEXT}, + {"xrDestroyInstance", &wine_xrDestroyInstance}, + {"xrDestroySession", &wine_xrDestroySession}, + {"xrDestroySpace", &wine_xrDestroySpace}, + {"xrDestroySpatialAnchorMSFT", &wine_xrDestroySpatialAnchorMSFT}, + {"xrDestroySwapchain", &wine_xrDestroySwapchain}, + {"xrEndFrame", &wine_xrEndFrame}, + {"xrEndSession", &wine_xrEndSession}, + {"xrEnumerateApiLayerProperties", &wine_xrEnumerateApiLayerProperties}, + {"xrEnumerateBoundSourcesForAction", &wine_xrEnumerateBoundSourcesForAction}, + {"xrEnumerateEnvironmentBlendModes", &wine_xrEnumerateEnvironmentBlendModes}, + {"xrEnumerateInstanceExtensionProperties", &wine_xrEnumerateInstanceExtensionProperties}, + {"xrEnumerateReferenceSpaces", &wine_xrEnumerateReferenceSpaces}, + {"xrEnumerateSwapchainFormats", &wine_xrEnumerateSwapchainFormats}, + {"xrEnumerateSwapchainImages", &wine_xrEnumerateSwapchainImages}, + {"xrEnumerateViewConfigurationViews", &wine_xrEnumerateViewConfigurationViews}, + {"xrEnumerateViewConfigurations", &wine_xrEnumerateViewConfigurations}, + {"xrGetActionStateBoolean", &wine_xrGetActionStateBoolean}, + {"xrGetActionStateFloat", &wine_xrGetActionStateFloat}, + {"xrGetActionStatePose", &wine_xrGetActionStatePose}, + {"xrGetActionStateVector2f", &wine_xrGetActionStateVector2f}, + {"xrGetCurrentInteractionProfile", &wine_xrGetCurrentInteractionProfile}, + {"xrGetD3D11GraphicsRequirementsKHR", &wine_xrGetD3D11GraphicsRequirementsKHR}, + {"xrGetD3D12GraphicsRequirementsKHR", &wine_xrGetD3D12GraphicsRequirementsKHR}, + {"xrGetInputSourceLocalizedName", &wine_xrGetInputSourceLocalizedName}, + {"xrGetInstanceProcAddr", &wine_xrGetInstanceProcAddr}, + {"xrGetInstanceProperties", &wine_xrGetInstanceProperties}, + {"xrGetOpenGLGraphicsRequirementsKHR", &wine_xrGetOpenGLGraphicsRequirementsKHR}, + {"xrGetReferenceSpaceBoundsRect", &wine_xrGetReferenceSpaceBoundsRect}, + {"xrGetSystem", &wine_xrGetSystem}, + {"xrGetSystemProperties", &wine_xrGetSystemProperties}, + {"xrGetViewConfigurationProperties", &wine_xrGetViewConfigurationProperties}, + {"xrGetVisibilityMaskKHR", &wine_xrGetVisibilityMaskKHR}, + {"xrGetVulkanDeviceExtensionsKHR", &wine_xrGetVulkanDeviceExtensionsKHR}, + {"xrGetVulkanGraphicsDeviceKHR", &wine_xrGetVulkanGraphicsDeviceKHR}, + {"xrGetVulkanGraphicsRequirementsKHR", &wine_xrGetVulkanGraphicsRequirementsKHR}, + {"xrGetVulkanInstanceExtensionsKHR", &wine_xrGetVulkanInstanceExtensionsKHR}, + {"xrLocateHandJointsEXT", &wine_xrLocateHandJointsEXT}, + {"xrLocateSpace", &wine_xrLocateSpace}, + {"xrLocateViews", &wine_xrLocateViews}, + {"xrPathToString", &wine_xrPathToString}, + {"xrPerfSettingsSetPerformanceLevelEXT", &wine_xrPerfSettingsSetPerformanceLevelEXT}, + {"xrPollEvent", &wine_xrPollEvent}, + {"xrReleaseSwapchainImage", &wine_xrReleaseSwapchainImage}, + {"xrRequestExitSession", &wine_xrRequestExitSession}, + {"xrResultToString", &wine_xrResultToString}, + {"xrSetInputDeviceActiveEXT", &wine_xrSetInputDeviceActiveEXT}, + {"xrSetInputDeviceLocationEXT", &wine_xrSetInputDeviceLocationEXT}, + {"xrSetInputDeviceStateBoolEXT", &wine_xrSetInputDeviceStateBoolEXT}, + {"xrSetInputDeviceStateFloatEXT", &wine_xrSetInputDeviceStateFloatEXT}, + {"xrSetInputDeviceStateVector2fEXT", &wine_xrSetInputDeviceStateVector2fEXT}, + {"xrStopHapticFeedback", &wine_xrStopHapticFeedback}, + {"xrStringToPath", &wine_xrStringToPath}, + {"xrStructureTypeToString", &wine_xrStructureTypeToString}, + {"xrSuggestInteractionProfileBindings", &wine_xrSuggestInteractionProfileBindings}, + {"xrSyncActions", &wine_xrSyncActions}, + {"xrThermalGetTemperatureTrendEXT", &wine_xrThermalGetTemperatureTrendEXT}, + {"xrUpdateHandMeshMSFT", &wine_xrUpdateHandMeshMSFT}, + {"xrWaitFrame", &wine_xrWaitFrame}, + {"xrWaitSwapchainImage", &wine_xrWaitSwapchainImage}, +}; + +void *wine_xr_proc_addr(const char *name) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(xr_dispatch_table); i++) + { + if (strcmp(xr_dispatch_table[i].name, name) == 0) + { + WINE_TRACE("Found name=%s in instance table\n", wine_dbgstr_a(name)); + return xr_dispatch_table[i].func; + } + } + return NULL; +} + +static const char * const xr_extensions[] = +{ + "XR_EPIC_view_configuration_fov", + "XR_EXTX_overlay", + "XR_EXT_conformance_automation", + "XR_EXT_eye_gaze_interaction", + "XR_EXT_hand_tracking", + "XR_EXT_hp_mixed_reality_controller", + "XR_EXT_performance_settings", + "XR_EXT_samsung_odyssey_controller", + "XR_EXT_thermal_query", + "XR_EXT_view_configuration_depth_range", + "XR_EXT_win32_appcontainer_compatible", + "XR_HUAWEI_controller_interaction", + "XR_KHR_D3D11_enable", + "XR_KHR_D3D12_enable", + "XR_KHR_composition_layer_cube", + "XR_KHR_composition_layer_cylinder", + "XR_KHR_composition_layer_depth", + "XR_KHR_composition_layer_equirect", + "XR_KHR_opengl_enable", + "XR_KHR_visibility_mask", + "XR_KHR_vulkan_enable", + "XR_KHR_vulkan_swapchain_format_list", + "XR_KHR_win32_convert_performance_counter_time", + "XR_MND_headless", + "XR_MND_swapchain_usage_input_attachment_bit", + "XR_MSFT_first_person_observer", + "XR_MSFT_hand_interaction", + "XR_MSFT_hand_tracking_mesh", + "XR_MSFT_holographic_window_attachment", + "XR_MSFT_secondary_view_configuration", + "XR_MSFT_spatial_anchor", + "XR_MSFT_spatial_graph_bridge", + "XR_MSFT_unbounded_reference_space", + "XR_OCULUS_android_session_state_enable", + "XR_VALVE_analog_threshold", + "XR_VARJO_quad_views", +}; + +BOOL wine_xr_extension_supported(const char *name) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(xr_extensions); i++) + { + if (strcmp(xr_extensions[i], name) == 0) + return TRUE; + } + return FALSE; +} diff --git a/wineopenxr/openxr_thunks.h b/wineopenxr/openxr_thunks.h new file mode 100644 index 00000000..eb3a8340 --- /dev/null +++ b/wineopenxr/openxr_thunks.h @@ -0,0 +1,212 @@ +/* Automatically generated from OpenXR xr.xml; DO NOT EDIT! + * + * This file is generated from OpenXR xr.xml file covered + * by the following copyright and permission notice: + * + * Copyright (c) 2017-2020 The Khronos Group Inc. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + * ------------------------------------------------------------------------ + * + * This file, xr.xml, is the OpenXR API Registry. It is a critically important + * and normative part of the OpenXR Specification, including a canonical + * machine-readable definition of the API, parameter and member validation + * language incorporated into the Specification and reference pages, and other + * material which is registered by Khronos, such as tags used by extension and + * layer authors. The only authoritative version of xr.xml is the one + * maintained in the master branch of the Khronos OpenXR GitHub project. + * + */ + +#ifndef __WINE_OPENXR_THUNKS_H +#define __WINE_OPENXR_THUNKS_H + +#define WINE_XR_VERSION XR_API_VERSION_1_0 + +/* Functions for which we have custom implementations outside of the thunks. */ +XrResult WINAPI wine_xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, XrTime time, LARGE_INTEGER *performanceCounter) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, const LARGE_INTEGER *performanceCounter, XrTime *time) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo, XrHandTrackerEXT *handTracker) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance); +XrResult WINAPI wine_xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session); +XrResult WINAPI wine_xrCreateSpatialAnchorMSFT(XrSession session, const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain); +XrResult WINAPI wine_xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrDestroyInstance(XrInstance instance); +XrResult WINAPI wine_xrDestroySession(XrSession session); +XrResult WINAPI wine_xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrDestroySwapchain(XrSwapchain swapchain); +XrResult WINAPI wine_xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo); +XrResult WINAPI wine_xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties); +XrResult WINAPI wine_xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats); +XrResult WINAPI wine_xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images); +XrResult WINAPI wine_xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrGetInstanceProcAddr(XrInstance instance, const char *name, PFN_xrVoidFunction *function); +XrResult WINAPI wine_xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId); +XrResult WINAPI wine_xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer) DECLSPEC_HIDDEN; +XrResult WINAPI wine_xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData); + +/* Private thunks */ + + +XrResult convert_XrInstanceCreateInfo_struct_chain(const void *next, XrInstanceCreateInfo *out_struct) DECLSPEC_HIDDEN; +void free_XrInstanceCreateInfo_struct_chain(XrInstanceCreateInfo *s) DECLSPEC_HIDDEN; + +/* For use by xrInstance and children */ +struct openxr_instance_funcs +{ + XrResult (*p_xrAcquireSwapchainImage)(XrSwapchain, const XrSwapchainImageAcquireInfo *, uint32_t *); + XrResult (*p_xrApplyHapticFeedback)(XrSession, const XrHapticActionInfo *, const XrHapticBaseHeader *); + XrResult (*p_xrAttachSessionActionSets)(XrSession, const XrSessionActionSetsAttachInfo *); + XrResult (*p_xrBeginFrame)(XrSession, const XrFrameBeginInfo *); + XrResult (*p_xrBeginSession)(XrSession, const XrSessionBeginInfo *); + XrResult (*p_xrCreateAction)(XrActionSet, const XrActionCreateInfo *, XrAction *); + XrResult (*p_xrCreateActionSet)(XrInstance, const XrActionSetCreateInfo *, XrActionSet *); + XrResult (*p_xrCreateActionSpace)(XrSession, const XrActionSpaceCreateInfo *, XrSpace *); + XrResult (*p_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT, const XrHandMeshSpaceCreateInfoMSFT *, XrSpace *); + XrResult (*p_xrCreateHandTrackerEXT)(XrSession, const XrHandTrackerCreateInfoEXT *, XrHandTrackerEXT *); + XrResult (*p_xrCreateReferenceSpace)(XrSession, const XrReferenceSpaceCreateInfo *, XrSpace *); + XrResult (*p_xrCreateSession)(XrInstance, const XrSessionCreateInfo *, XrSession *); + XrResult (*p_xrCreateSpatialAnchorMSFT)(XrSession, const XrSpatialAnchorCreateInfoMSFT *, XrSpatialAnchorMSFT *); + XrResult (*p_xrCreateSpatialAnchorSpaceMSFT)(XrSession, const XrSpatialAnchorSpaceCreateInfoMSFT *, XrSpace *); + XrResult (*p_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession, const XrSpatialGraphNodeSpaceCreateInfoMSFT *, XrSpace *); + XrResult (*p_xrCreateSwapchain)(XrSession, const XrSwapchainCreateInfo *, XrSwapchain *); + XrResult (*p_xrDestroyAction)(XrAction); + XrResult (*p_xrDestroyActionSet)(XrActionSet); + XrResult (*p_xrDestroyHandTrackerEXT)(XrHandTrackerEXT); + XrResult (*p_xrDestroySession)(XrSession); + XrResult (*p_xrDestroySpace)(XrSpace); + XrResult (*p_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT); + XrResult (*p_xrDestroySwapchain)(XrSwapchain); + XrResult (*p_xrEndFrame)(XrSession, const XrFrameEndInfo *); + XrResult (*p_xrEndSession)(XrSession); + XrResult (*p_xrEnumerateApiLayerProperties)(uint32_t, uint32_t *, XrApiLayerProperties *); + XrResult (*p_xrEnumerateBoundSourcesForAction)(XrSession, const XrBoundSourcesForActionEnumerateInfo *, uint32_t, uint32_t *, XrPath *); + XrResult (*p_xrEnumerateEnvironmentBlendModes)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrEnvironmentBlendMode *); + XrResult (*p_xrEnumerateReferenceSpaces)(XrSession, uint32_t, uint32_t *, XrReferenceSpaceType *); + XrResult (*p_xrEnumerateSwapchainFormats)(XrSession, uint32_t, uint32_t *, int64_t *); + XrResult (*p_xrEnumerateSwapchainImages)(XrSwapchain, uint32_t, uint32_t *, XrSwapchainImageBaseHeader *); + XrResult (*p_xrEnumerateViewConfigurationViews)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrViewConfigurationView *); + XrResult (*p_xrEnumerateViewConfigurations)(XrInstance, XrSystemId, uint32_t, uint32_t *, XrViewConfigurationType *); + XrResult (*p_xrGetActionStateBoolean)(XrSession, const XrActionStateGetInfo *, XrActionStateBoolean *); + XrResult (*p_xrGetActionStateFloat)(XrSession, const XrActionStateGetInfo *, XrActionStateFloat *); + XrResult (*p_xrGetActionStatePose)(XrSession, const XrActionStateGetInfo *, XrActionStatePose *); + XrResult (*p_xrGetActionStateVector2f)(XrSession, const XrActionStateGetInfo *, XrActionStateVector2f *); + XrResult (*p_xrGetCurrentInteractionProfile)(XrSession, XrPath, XrInteractionProfileState *); + XrResult (*p_xrGetInputSourceLocalizedName)(XrSession, const XrInputSourceLocalizedNameGetInfo *, uint32_t, uint32_t *, char *); + XrResult (*p_xrGetInstanceProperties)(XrInstance, XrInstanceProperties *); + XrResult (*p_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsOpenGLKHR *); + XrResult (*p_xrGetReferenceSpaceBoundsRect)(XrSession, XrReferenceSpaceType, XrExtent2Df *); + XrResult (*p_xrGetSystem)(XrInstance, const XrSystemGetInfo *, XrSystemId *); + XrResult (*p_xrGetSystemProperties)(XrInstance, XrSystemId, XrSystemProperties *); + XrResult (*p_xrGetViewConfigurationProperties)(XrInstance, XrSystemId, XrViewConfigurationType, XrViewConfigurationProperties *); + XrResult (*p_xrGetVisibilityMaskKHR)(XrSession, XrViewConfigurationType, uint32_t, XrVisibilityMaskTypeKHR, XrVisibilityMaskKHR *); + XrResult (*p_xrGetVulkanDeviceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *); + XrResult (*p_xrGetVulkanGraphicsDeviceKHR)(XrInstance, XrSystemId, VkInstance, VkPhysicalDevice *); + XrResult (*p_xrGetVulkanGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsVulkanKHR *); + XrResult (*p_xrGetVulkanInstanceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *); + XrResult (*p_xrLocateHandJointsEXT)(XrHandTrackerEXT, const XrHandJointsLocateInfoEXT *, XrHandJointLocationsEXT *); + XrResult (*p_xrLocateSpace)(XrSpace, XrSpace, XrTime, XrSpaceLocation *); + XrResult (*p_xrLocateViews)(XrSession, const XrViewLocateInfo *, XrViewState *, uint32_t, uint32_t *, XrView *); + XrResult (*p_xrPathToString)(XrInstance, XrPath, uint32_t, uint32_t *, char *); + XrResult (*p_xrPerfSettingsSetPerformanceLevelEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT); + XrResult (*p_xrPollEvent)(XrInstance, XrEventDataBuffer *); + XrResult (*p_xrReleaseSwapchainImage)(XrSwapchain, const XrSwapchainImageReleaseInfo *); + XrResult (*p_xrRequestExitSession)(XrSession); + XrResult (*p_xrResultToString)(XrInstance, XrResult, char[]); + XrResult (*p_xrSetInputDeviceActiveEXT)(XrSession, XrPath, XrPath, XrBool32); + XrResult (*p_xrSetInputDeviceLocationEXT)(XrSession, XrPath, XrPath, XrSpace, XrPosef); + XrResult (*p_xrSetInputDeviceStateBoolEXT)(XrSession, XrPath, XrPath, XrBool32); + XrResult (*p_xrSetInputDeviceStateFloatEXT)(XrSession, XrPath, XrPath, float); + XrResult (*p_xrSetInputDeviceStateVector2fEXT)(XrSession, XrPath, XrPath, XrVector2f); + XrResult (*p_xrStopHapticFeedback)(XrSession, const XrHapticActionInfo *); + XrResult (*p_xrStringToPath)(XrInstance, const char *, XrPath *); + XrResult (*p_xrStructureTypeToString)(XrInstance, XrStructureType, char[]); + XrResult (*p_xrSuggestInteractionProfileBindings)(XrInstance, const XrInteractionProfileSuggestedBinding *); + XrResult (*p_xrSyncActions)(XrSession, const XrActionsSyncInfo *); + XrResult (*p_xrThermalGetTemperatureTrendEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsNotificationLevelEXT *, float *, float *); + XrResult (*p_xrUpdateHandMeshMSFT)(XrHandTrackerEXT, const XrHandMeshUpdateInfoMSFT *, XrHandMeshMSFT *); + XrResult (*p_xrWaitFrame)(XrSession, const XrFrameWaitInfo *, XrFrameState *); + XrResult (*p_xrWaitSwapchainImage)(XrSwapchain, const XrSwapchainImageWaitInfo *); +}; + +#define ALL_XR_INSTANCE_FUNCS() \ + USE_XR_FUNC(xrAcquireSwapchainImage) \ + USE_XR_FUNC(xrApplyHapticFeedback) \ + USE_XR_FUNC(xrAttachSessionActionSets) \ + USE_XR_FUNC(xrBeginFrame) \ + USE_XR_FUNC(xrBeginSession) \ + USE_XR_FUNC(xrCreateAction) \ + USE_XR_FUNC(xrCreateActionSet) \ + USE_XR_FUNC(xrCreateActionSpace) \ + USE_XR_FUNC(xrCreateHandMeshSpaceMSFT) \ + USE_XR_FUNC(xrCreateHandTrackerEXT) \ + USE_XR_FUNC(xrCreateReferenceSpace) \ + USE_XR_FUNC(xrCreateSession) \ + USE_XR_FUNC(xrCreateSpatialAnchorMSFT) \ + USE_XR_FUNC(xrCreateSpatialAnchorSpaceMSFT) \ + USE_XR_FUNC(xrCreateSpatialGraphNodeSpaceMSFT) \ + USE_XR_FUNC(xrCreateSwapchain) \ + USE_XR_FUNC(xrDestroyAction) \ + USE_XR_FUNC(xrDestroyActionSet) \ + USE_XR_FUNC(xrDestroyHandTrackerEXT) \ + USE_XR_FUNC(xrDestroySession) \ + USE_XR_FUNC(xrDestroySpace) \ + USE_XR_FUNC(xrDestroySpatialAnchorMSFT) \ + USE_XR_FUNC(xrDestroySwapchain) \ + USE_XR_FUNC(xrEndFrame) \ + USE_XR_FUNC(xrEndSession) \ + USE_XR_FUNC(xrEnumerateApiLayerProperties) \ + USE_XR_FUNC(xrEnumerateBoundSourcesForAction) \ + USE_XR_FUNC(xrEnumerateEnvironmentBlendModes) \ + USE_XR_FUNC(xrEnumerateReferenceSpaces) \ + USE_XR_FUNC(xrEnumerateSwapchainFormats) \ + USE_XR_FUNC(xrEnumerateSwapchainImages) \ + USE_XR_FUNC(xrEnumerateViewConfigurationViews) \ + USE_XR_FUNC(xrEnumerateViewConfigurations) \ + USE_XR_FUNC(xrGetActionStateBoolean) \ + USE_XR_FUNC(xrGetActionStateFloat) \ + USE_XR_FUNC(xrGetActionStatePose) \ + USE_XR_FUNC(xrGetActionStateVector2f) \ + USE_XR_FUNC(xrGetCurrentInteractionProfile) \ + USE_XR_FUNC(xrGetInputSourceLocalizedName) \ + USE_XR_FUNC(xrGetInstanceProperties) \ + USE_XR_FUNC(xrGetOpenGLGraphicsRequirementsKHR) \ + USE_XR_FUNC(xrGetReferenceSpaceBoundsRect) \ + USE_XR_FUNC(xrGetSystem) \ + USE_XR_FUNC(xrGetSystemProperties) \ + USE_XR_FUNC(xrGetViewConfigurationProperties) \ + USE_XR_FUNC(xrGetVisibilityMaskKHR) \ + USE_XR_FUNC(xrGetVulkanDeviceExtensionsKHR) \ + USE_XR_FUNC(xrGetVulkanGraphicsDeviceKHR) \ + USE_XR_FUNC(xrGetVulkanGraphicsRequirementsKHR) \ + USE_XR_FUNC(xrGetVulkanInstanceExtensionsKHR) \ + USE_XR_FUNC(xrLocateHandJointsEXT) \ + USE_XR_FUNC(xrLocateSpace) \ + USE_XR_FUNC(xrLocateViews) \ + USE_XR_FUNC(xrPathToString) \ + USE_XR_FUNC(xrPerfSettingsSetPerformanceLevelEXT) \ + USE_XR_FUNC(xrPollEvent) \ + USE_XR_FUNC(xrReleaseSwapchainImage) \ + USE_XR_FUNC(xrRequestExitSession) \ + USE_XR_FUNC(xrResultToString) \ + USE_XR_FUNC(xrSetInputDeviceActiveEXT) \ + USE_XR_FUNC(xrSetInputDeviceLocationEXT) \ + USE_XR_FUNC(xrSetInputDeviceStateBoolEXT) \ + USE_XR_FUNC(xrSetInputDeviceStateFloatEXT) \ + USE_XR_FUNC(xrSetInputDeviceStateVector2fEXT) \ + USE_XR_FUNC(xrStopHapticFeedback) \ + USE_XR_FUNC(xrStringToPath) \ + USE_XR_FUNC(xrStructureTypeToString) \ + USE_XR_FUNC(xrSuggestInteractionProfileBindings) \ + USE_XR_FUNC(xrSyncActions) \ + USE_XR_FUNC(xrThermalGetTemperatureTrendEXT) \ + USE_XR_FUNC(xrUpdateHandMeshMSFT) \ + USE_XR_FUNC(xrWaitFrame) \ + USE_XR_FUNC(xrWaitSwapchainImage) + +#endif /* __WINE_OPENXR_THUNKS_H */ diff --git a/wineopenxr/wineopenxr.h b/wineopenxr/wineopenxr.h new file mode 100644 index 00000000..9f11c5ab --- /dev/null +++ b/wineopenxr/wineopenxr.h @@ -0,0 +1,1957 @@ +/* Automatically generated from OpenXR xr.xml; DO NOT EDIT! + * + * This file is generated from OpenXR xr.xml file covered + * by the following copyright and permission notice: + * + * Copyright (c) 2017-2020 The Khronos Group Inc. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + * ------------------------------------------------------------------------ + * + * This file, xr.xml, is the OpenXR API Registry. It is a critically important + * and normative part of the OpenXR Specification, including a canonical + * machine-readable definition of the API, parameter and member validation + * language incorporated into the Specification and reference pages, and other + * material which is registered by Khronos, such as tags used by extension and + * layer authors. The only authoritative version of xr.xml is the one + * maintained in the master branch of the Khronos OpenXR GitHub project. + * + */ + +#ifndef __WINE_OPENXR_H +#define __WINE_OPENXR_H + +#include +#include + +/* Define WINE_XR_HOST to get 'host' headers. */ +#ifdef WINE_XR_HOST +#define XRAPI_CALL +#define WINE_XR_ALIGN(x) +#endif + +#ifndef XRAPI_CALL +#define XRAPI_CALL __stdcall +#endif + +#ifndef XRAPI_PTR +#define XRAPI_PTR XRAPI_CALL +#endif + +#ifndef WINE_XR_ALIGN +#define WINE_XR_ALIGN DECLSPEC_ALIGN +#endif + +#define XR_TRUE 1 +#define XR_FALSE 0 +#define XR_MAX_EXTENSION_NAME_SIZE 128 +#define XR_MAX_API_LAYER_NAME_SIZE 256 +#define XR_MAX_API_LAYER_DESCRIPTION_SIZE 256 +#define XR_MAX_SYSTEM_NAME_SIZE 256 +#define XR_MAX_APPLICATION_NAME_SIZE 128 +#define XR_MAX_ENGINE_NAME_SIZE 128 +#define XR_MAX_RUNTIME_NAME_SIZE 128 +#define XR_MAX_PATH_LENGTH 256 +#define XR_MAX_STRUCTURE_NAME_SIZE 64 +#define XR_MAX_RESULT_STRING_SIZE 64 +#define XR_MAX_GRAPHICS_APIS_SUPPORTED 32 +#define XR_MAX_ACTION_SET_NAME_SIZE 64 +#define XR_MAX_ACTION_NAME_SIZE 64 +#define XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE 128 +#define XR_MAX_LOCALIZED_ACTION_NAME_SIZE 128 +#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16 +#define XR_KHR_composition_layer_cube_SPEC_VERSION 8 +#define XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME "XR_KHR_composition_layer_cube" +#define XR_KHR_composition_layer_depth_SPEC_VERSION 5 +#define XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME "XR_KHR_composition_layer_depth" +#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 2 +#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list" +#define XR_EXT_performance_settings_SPEC_VERSION 1 +#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME "XR_EXT_performance_settings" +#define XR_EXT_thermal_query_SPEC_VERSION 1 +#define XR_EXT_THERMAL_QUERY_EXTENSION_NAME "XR_EXT_thermal_query" +#define XR_KHR_composition_layer_cylinder_SPEC_VERSION 4 +#define XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME "XR_KHR_composition_layer_cylinder" +#define XR_KHR_composition_layer_equirect_SPEC_VERSION 3 +#define XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME "XR_KHR_composition_layer_equirect" +#define XR_KHR_opengl_enable_SPEC_VERSION 9 +#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable" +#define XR_KHR_vulkan_enable_SPEC_VERSION 7 +#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable" +#define XR_KHR_D3D11_enable_SPEC_VERSION 5 +#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable" +#define XR_KHR_D3D12_enable_SPEC_VERSION 7 +#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable" +#define XR_EXT_eye_gaze_interaction_SPEC_VERSION 1 +#define XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME "XR_EXT_eye_gaze_interaction" +#define XR_KHR_visibility_mask_SPEC_VERSION 2 +#define XR_KHR_VISIBILITY_MASK_EXTENSION_NAME "XR_KHR_visibility_mask" +#define XR_EXTX_overlay_SPEC_VERSION 4 +#define XR_EXTX_OVERLAY_EXTENSION_NAME "XR_EXTX_overlay" +#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1 +#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time" +#define XR_VARJO_quad_views_SPEC_VERSION 1 +#define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME "XR_VARJO_quad_views" +#define XR_MSFT_unbounded_reference_space_SPEC_VERSION 1 +#define XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME "XR_MSFT_unbounded_reference_space" +#define XR_MSFT_spatial_anchor_SPEC_VERSION 1 +#define XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME "XR_MSFT_spatial_anchor" +#define XR_MND_headless_SPEC_VERSION 2 +#define XR_MND_HEADLESS_EXTENSION_NAME "XR_MND_headless" +#define XR_OCULUS_android_session_state_enable_SPEC_VERSION 1 +#define XR_OCULUS_ANDROID_SESSION_STATE_ENABLE_EXTENSION_NAME "XR_OCULUS_android_session_state_enable" +#define XR_EXT_view_configuration_depth_range_SPEC_VERSION 1 +#define XR_EXT_VIEW_CONFIGURATION_DEPTH_RANGE_EXTENSION_NAME "XR_EXT_view_configuration_depth_range" +#define XR_EXT_conformance_automation_SPEC_VERSION 1 +#define XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME "XR_EXT_conformance_automation" +#define XR_MSFT_spatial_graph_bridge_SPEC_VERSION 1 +#define XR_MSFT_SPATIAL_GRAPH_BRIDGE_EXTENSION_NAME "XR_MSFT_spatial_graph_bridge" +#define XR_MSFT_hand_interaction_SPEC_VERSION 1 +#define XR_MSFT_HAND_INTERACTION_EXTENSION_NAME "XR_MSFT_hand_interaction" +#define XR_EXT_hand_tracking_SPEC_VERSION 2 +#define XR_EXT_HAND_TRACKING_EXTENSION_NAME "XR_EXT_hand_tracking" +#define XR_MSFT_hand_tracking_mesh_SPEC_VERSION 2 +#define XR_MSFT_HAND_TRACKING_MESH_EXTENSION_NAME "XR_MSFT_hand_tracking_mesh" +#define XR_MSFT_secondary_view_configuration_SPEC_VERSION 1 +#define XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME "XR_MSFT_secondary_view_configuration" +#define XR_MSFT_first_person_observer_SPEC_VERSION 1 +#define XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME "XR_MSFT_first_person_observer" +#define XR_EXT_win32_appcontainer_compatible_SPEC_VERSION 1 +#define XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME "XR_EXT_win32_appcontainer_compatible" +#define XR_EPIC_view_configuration_fov_SPEC_VERSION 2 +#define XR_EPIC_VIEW_CONFIGURATION_FOV_EXTENSION_NAME "XR_EPIC_view_configuration_fov" +#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1 +#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment" +#define XR_HUAWEI_controller_interaction_SPEC_VERSION 1 +#define XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_HUAWEI_controller_interaction" +#define XR_VALVE_analog_threshold_SPEC_VERSION 1 +#define XR_VALVE_ANALOG_THRESHOLD_EXTENSION_NAME "XR_VALVE_analog_threshold" +#define XR_EXT_samsung_odyssey_controller_SPEC_VERSION 1 +#define XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME "XR_EXT_samsung_odyssey_controller" +#define XR_EXT_hp_mixed_reality_controller_SPEC_VERSION 1 +#define XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME "XR_EXT_hp_mixed_reality_controller" +#define XR_MND_swapchain_usage_input_attachment_bit_SPEC_VERSION 2 +#define XR_MND_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME "XR_MND_swapchain_usage_input_attachment_bit" + + +#define XR_MAKE_VERSION(major, minor, patch) \ + ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL)) + +#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL) + +#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL) + +#define XR_VERSION_PATCH(version) (uint32_t)((uint64_t)(version) & 0xffffffffULL) + + +#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 11) + + +#if !defined(XR_MAY_ALIAS) +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4)) +#define XR_MAY_ALIAS __attribute__((__may_alias__)) +#else +#define XR_MAY_ALIAS +#endif +#endif + + +#if !defined(XR_DEFINE_HANDLE) +#if (XR_PTR_SIZE == 8) + #define XR_DEFINE_HANDLE(object) typedef struct object##_T* object; +#else + #define XR_DEFINE_HANDLE(object) typedef uint64_t object; +#endif +#endif + + + +#if !defined(XR_NULL_HANDLE) +#if (XR_PTR_SIZE == 8) && XR_CPP_NULLPTR_SUPPORTED + #define XR_NULL_HANDLE nullptr +#else + #define XR_NULL_HANDLE 0 +#endif +#endif + + + +#if !defined(XR_DEFINE_ATOM) + #define XR_DEFINE_ATOM(object) typedef uint64_t object; +#endif + + + +#define XR_NULL_PATH 0 + + +#define XR_NULL_SYSTEM_ID 0 + + +#define XR_SUCCEEDED(result) ((result) >= 0) + + +#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0) + + +#define XR_FAILED(result) ((result) < 0) + + +#define XR_NO_DURATION 0 + + +#define XR_INFINITE_DURATION 0x7fffffffffffffffLL + + +#define XR_MIN_HAPTIC_DURATION -1 + + +#define XR_FREQUENCY_UNSPECIFIED 0 + + +#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer) + + +#define XR_HAND_JOINT_COUNT_EXT 26 +XR_DEFINE_HANDLE(XrAction) +XR_DEFINE_HANDLE(XrActionSet) +XR_DEFINE_HANDLE(XrHandTrackerEXT) +XR_DEFINE_HANDLE(XrInstance) +XR_DEFINE_HANDLE(XrSession) +XR_DEFINE_HANDLE(XrSpace) +XR_DEFINE_HANDLE(XrSpatialAnchorMSFT) +XR_DEFINE_HANDLE(XrSwapchain) + +typedef uint32_t XrBool32; +typedef int64_t XrDuration; +typedef uint64_t XrFlags64; +XR_DEFINE_ATOM(XrPath) +XR_DEFINE_ATOM(XrSystemId) +typedef int64_t XrTime; +typedef uint64_t XrVersion; + +typedef XrFlags64 XrCompositionLayerFlags; +typedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT; +typedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT; +typedef XrFlags64 XrInputSourceLocalizedNameFlags; +typedef XrFlags64 XrInstanceCreateFlags; +typedef XrFlags64 XrOverlayMainSessionFlagsEXTX; +typedef XrFlags64 XrOverlaySessionCreateFlagsEXTX; +typedef XrFlags64 XrSessionCreateFlags; +typedef XrFlags64 XrSpaceLocationFlags; +typedef XrFlags64 XrSpaceVelocityFlags; +typedef XrFlags64 XrSwapchainCreateFlags; +typedef XrFlags64 XrSwapchainUsageFlags; +typedef XrFlags64 XrViewStateFlags; + +typedef enum XrActionType +{ + XR_ACTION_TYPE_BOOLEAN_INPUT = 1, + XR_ACTION_TYPE_FLOAT_INPUT = 2, + XR_ACTION_TYPE_VECTOR2F_INPUT = 3, + XR_ACTION_TYPE_POSE_INPUT = 4, + XR_ACTION_TYPE_VIBRATION_OUTPUT = 100, + XR_ACTION_TYPE_MAX_ENUM = 0x7fffffff, +} XrActionType; + +typedef enum XrEnvironmentBlendMode +{ + XR_ENVIRONMENT_BLEND_MODE_OPAQUE = 1, + XR_ENVIRONMENT_BLEND_MODE_ADDITIVE = 2, + XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND = 3, + XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM = 0x7fffffff, +} XrEnvironmentBlendMode; + +typedef enum XrEyeVisibility +{ + XR_EYE_VISIBILITY_BOTH = 0, + XR_EYE_VISIBILITY_LEFT = 1, + XR_EYE_VISIBILITY_RIGHT = 2, + XR_EYE_VISIBILITY_MAX_ENUM = 0x7fffffff, +} XrEyeVisibility; + +typedef enum XrFormFactor +{ + XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1, + XR_FORM_FACTOR_HANDHELD_DISPLAY = 2, + XR_FORM_FACTOR_MAX_ENUM = 0x7fffffff, +} XrFormFactor; + +typedef enum XrHandEXT +{ + XR_HAND_LEFT_EXT = 1, + XR_HAND_RIGHT_EXT = 2, + XR_HAND_EXT_MAX_ENUM = 0x7fffffff, +} XrHandEXT; + +typedef enum XrHandJointEXT +{ + XR_HAND_JOINT_PALM_EXT = 0, + XR_HAND_JOINT_WRIST_EXT = 1, + XR_HAND_JOINT_THUMB_METACARPAL_EXT = 2, + XR_HAND_JOINT_THUMB_PROXIMAL_EXT = 3, + XR_HAND_JOINT_THUMB_DISTAL_EXT = 4, + XR_HAND_JOINT_THUMB_TIP_EXT = 5, + XR_HAND_JOINT_INDEX_METACARPAL_EXT = 6, + XR_HAND_JOINT_INDEX_PROXIMAL_EXT = 7, + XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT = 8, + XR_HAND_JOINT_INDEX_DISTAL_EXT = 9, + XR_HAND_JOINT_INDEX_TIP_EXT = 10, + XR_HAND_JOINT_MIDDLE_METACARPAL_EXT = 11, + XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT = 12, + XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT = 13, + XR_HAND_JOINT_MIDDLE_DISTAL_EXT = 14, + XR_HAND_JOINT_MIDDLE_TIP_EXT = 15, + XR_HAND_JOINT_RING_METACARPAL_EXT = 16, + XR_HAND_JOINT_RING_PROXIMAL_EXT = 17, + XR_HAND_JOINT_RING_INTERMEDIATE_EXT = 18, + XR_HAND_JOINT_RING_DISTAL_EXT = 19, + XR_HAND_JOINT_RING_TIP_EXT = 20, + XR_HAND_JOINT_LITTLE_METACARPAL_EXT = 21, + XR_HAND_JOINT_LITTLE_PROXIMAL_EXT = 22, + XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT = 23, + XR_HAND_JOINT_LITTLE_DISTAL_EXT = 24, + XR_HAND_JOINT_LITTLE_TIP_EXT = 25, + XR_HAND_JOINT_EXT_MAX_ENUM = 0x7fffffff, +} XrHandJointEXT; + +typedef enum XrHandJointSetEXT +{ + XR_HAND_JOINT_SET_DEFAULT_EXT = 0, + XR_HAND_JOINT_SET_EXT_MAX_ENUM = 0x7fffffff, +} XrHandJointSetEXT; + +typedef enum XrHandPoseTypeMSFT +{ + XR_HAND_POSE_TYPE_TRACKED_MSFT = 0, + XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT = 1, + XR_HAND_POSE_TYPE_MSFT_MAX_ENUM = 0x7fffffff, +} XrHandPoseTypeMSFT; + +typedef enum XrObjectType +{ + XR_OBJECT_TYPE_UNKNOWN = 0, + XR_OBJECT_TYPE_INSTANCE = 1, + XR_OBJECT_TYPE_SESSION = 2, + XR_OBJECT_TYPE_SWAPCHAIN = 3, + XR_OBJECT_TYPE_SPACE = 4, + XR_OBJECT_TYPE_ACTION_SET = 5, + XR_OBJECT_TYPE_ACTION = 6, + XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT = 1000039000, + XR_OBJECT_TYPE_HAND_TRACKER_EXT = 1000051000, + XR_OBJECT_TYPE_MAX_ENUM = 0x7fffffff, +} XrObjectType; + +typedef enum XrPerfSettingsDomainEXT +{ + XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1, + XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2, + XR_PERF_SETTINGS_DOMAIN_EXT_MAX_ENUM = 0x7fffffff, +} XrPerfSettingsDomainEXT; + +typedef enum XrPerfSettingsLevelEXT +{ + XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT = 0, + XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT = 25, + XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT = 50, + XR_PERF_SETTINGS_LEVEL_BOOST_EXT = 75, + XR_PERF_SETTINGS_LEVEL_EXT_MAX_ENUM = 0x7fffffff, +} XrPerfSettingsLevelEXT; + +typedef enum XrPerfSettingsNotificationLevelEXT +{ + XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0, + XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25, + XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75, + XR_PERF_SETTINGS_NOTIFICATION_LEVEL_EXT_MAX_ENUM = 0x7fffffff, +} XrPerfSettingsNotificationLevelEXT; + +typedef enum XrPerfSettingsSubDomainEXT +{ + XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1, + XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2, + XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3, + XR_PERF_SETTINGS_SUB_DOMAIN_EXT_MAX_ENUM = 0x7fffffff, +} XrPerfSettingsSubDomainEXT; + +typedef enum XrReferenceSpaceType +{ + XR_REFERENCE_SPACE_TYPE_VIEW = 1, + XR_REFERENCE_SPACE_TYPE_LOCAL = 2, + XR_REFERENCE_SPACE_TYPE_STAGE = 3, + XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT = 1000038000, + XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7fffffff, +} XrReferenceSpaceType; + +typedef enum XrResult +{ + XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT = -1000053000, + XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT = -1000039001, + XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50, + XR_ERROR_LOCALIZED_NAME_INVALID = -49, + XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48, + XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47, + XR_ERROR_ACTIONSET_NOT_ATTACHED = -46, + XR_ERROR_NAME_INVALID = -45, + XR_ERROR_NAME_DUPLICATED = -44, + XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42, + XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41, + XR_ERROR_INDEX_OUT_OF_RANGE = -40, + XR_ERROR_POSE_INVALID = -39, + XR_ERROR_GRAPHICS_DEVICE_INVALID = -38, + XR_ERROR_CALL_ORDER_INVALID = -37, + XR_ERROR_API_LAYER_NOT_PRESENT = -36, + XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35, + XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34, + XR_ERROR_FILE_CONTENTS_INVALID = -33, + XR_ERROR_FILE_ACCESS_ERROR = -32, + XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31, + XR_ERROR_TIME_INVALID = -30, + XR_ERROR_SESSION_NOT_STOPPING = -29, + XR_ERROR_SESSION_NOT_READY = -28, + XR_ERROR_ACTION_TYPE_MISMATCH = -27, + XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26, + XR_ERROR_SWAPCHAIN_RECT_INVALID = -25, + XR_ERROR_LAYER_LIMIT_EXCEEDED = -24, + XR_ERROR_LAYER_INVALID = -23, + XR_ERROR_PATH_UNSUPPORTED = -22, + XR_ERROR_PATH_FORMAT_INVALID = -21, + XR_ERROR_PATH_COUNT_EXCEEDED = -20, + XR_ERROR_PATH_INVALID = -19, + XR_ERROR_SYSTEM_INVALID = -18, + XR_ERROR_SESSION_LOST = -17, + XR_ERROR_SESSION_NOT_RUNNING = -16, + XR_ERROR_SESSION_RUNNING = -14, + XR_ERROR_INSTANCE_LOST = -13, + XR_ERROR_HANDLE_INVALID = -12, + XR_ERROR_SIZE_INSUFFICIENT = -11, + XR_ERROR_LIMIT_REACHED = -10, + XR_ERROR_EXTENSION_NOT_PRESENT = -9, + XR_ERROR_FEATURE_UNSUPPORTED = -8, + XR_ERROR_FUNCTION_UNSUPPORTED = -7, + XR_ERROR_INITIALIZATION_FAILED = -6, + XR_ERROR_API_VERSION_UNSUPPORTED = -4, + XR_ERROR_OUT_OF_MEMORY = -3, + XR_ERROR_RUNTIME_FAILURE = -2, + XR_ERROR_VALIDATION_FAILURE = -1, + XR_SUCCESS = 0, + XR_TIMEOUT_EXPIRED = 1, + XR_SESSION_LOSS_PENDING = 3, + XR_EVENT_UNAVAILABLE = 4, + XR_SPACE_BOUNDS_UNAVAILABLE = 7, + XR_SESSION_NOT_FOCUSED = 8, + XR_FRAME_DISCARDED = 9, + XR_RESULT_MAX_ENUM = 0x7fffffff, +} XrResult; + +typedef enum XrSessionState +{ + XR_SESSION_STATE_UNKNOWN = 0, + XR_SESSION_STATE_IDLE = 1, + XR_SESSION_STATE_READY = 2, + XR_SESSION_STATE_SYNCHRONIZED = 3, + XR_SESSION_STATE_VISIBLE = 4, + XR_SESSION_STATE_FOCUSED = 5, + XR_SESSION_STATE_STOPPING = 6, + XR_SESSION_STATE_LOSS_PENDING = 7, + XR_SESSION_STATE_EXITING = 8, + XR_SESSION_STATE_MAX_ENUM = 0x7fffffff, +} XrSessionState; + +typedef enum XrSpatialGraphNodeTypeMSFT +{ + XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT = 1, + XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT = 2, + XR_SPATIAL_GRAPH_NODE_TYPE_MSFT_MAX_ENUM = 0x7fffffff, +} XrSpatialGraphNodeTypeMSFT; + +typedef enum XrStructureType +{ + XR_TYPE_UNKNOWN = 0, + XR_TYPE_API_LAYER_PROPERTIES = 1, + XR_TYPE_EXTENSION_PROPERTIES = 2, + XR_TYPE_INSTANCE_CREATE_INFO = 3, + XR_TYPE_SYSTEM_GET_INFO = 4, + XR_TYPE_SYSTEM_PROPERTIES = 5, + XR_TYPE_VIEW_LOCATE_INFO = 6, + XR_TYPE_VIEW = 7, + XR_TYPE_SESSION_CREATE_INFO = 8, + XR_TYPE_SWAPCHAIN_CREATE_INFO = 9, + XR_TYPE_SESSION_BEGIN_INFO = 10, + XR_TYPE_VIEW_STATE = 11, + XR_TYPE_FRAME_END_INFO = 12, + XR_TYPE_HAPTIC_VIBRATION = 13, + XR_TYPE_EVENT_DATA_BUFFER = 16, + XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING = 17, + XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED = 18, + XR_TYPE_ACTION_STATE_BOOLEAN = 23, + XR_TYPE_ACTION_STATE_FLOAT = 24, + XR_TYPE_ACTION_STATE_VECTOR2F = 25, + XR_TYPE_ACTION_STATE_POSE = 27, + XR_TYPE_ACTION_SET_CREATE_INFO = 28, + XR_TYPE_ACTION_CREATE_INFO = 29, + XR_TYPE_INSTANCE_PROPERTIES = 32, + XR_TYPE_FRAME_WAIT_INFO = 33, + XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35, + XR_TYPE_COMPOSITION_LAYER_QUAD = 36, + XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37, + XR_TYPE_ACTION_SPACE_CREATE_INFO = 38, + XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40, + XR_TYPE_VIEW_CONFIGURATION_VIEW = 41, + XR_TYPE_SPACE_LOCATION = 42, + XR_TYPE_SPACE_VELOCITY = 43, + XR_TYPE_FRAME_STATE = 44, + XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45, + XR_TYPE_FRAME_BEGIN_INFO = 46, + XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48, + XR_TYPE_EVENT_DATA_EVENTS_LOST = 49, + XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51, + XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52, + XR_TYPE_INTERACTION_PROFILE_STATE = 53, + XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55, + XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56, + XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57, + XR_TYPE_ACTION_STATE_GET_INFO = 58, + XR_TYPE_HAPTIC_ACTION_INFO = 59, + XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO = 60, + XR_TYPE_ACTIONS_SYNC_INFO = 61, + XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO = 62, + XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO = 63, + XR_TYPE_COMPOSITION_LAYER_CUBE_KHR = 1000006000, + XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR = 1000010000, + XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR = 1000014000, + XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT = 1000015000, + XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR = 1000017000, + XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR = 1000018000, + XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR = 1000023000, + XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR = 1000023001, + XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR = 1000023002, + XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR = 1000023003, + XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR = 1000023004, + XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR = 1000023005, + XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR = 1000025000, + XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR = 1000025001, + XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR = 1000025002, + XR_TYPE_GRAPHICS_BINDING_D3D11_KHR = 1000027000, + XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR = 1000027001, + XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR = 1000027002, + XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000, + XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001, + XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002, + XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT = 1000030000, + XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT = 1000030001, + XR_TYPE_VISIBILITY_MASK_KHR = 1000031000, + XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001, + XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX = 1000033000, + XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX = 1000033003, + XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000, + XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001, + XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT = 1000046000, + XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT = 1000049000, + XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT = 1000051000, + XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT = 1000051001, + XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT = 1000051002, + XR_TYPE_HAND_JOINT_LOCATIONS_EXT = 1000051003, + XR_TYPE_HAND_JOINT_VELOCITIES_EXT = 1000051004, + XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT = 1000052000, + XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT = 1000052001, + XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT = 1000052002, + XR_TYPE_HAND_MESH_MSFT = 1000052003, + XR_TYPE_HAND_POSE_TYPE_INFO_MSFT = 1000052004, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT = 1000053000, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT = 1000053001, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT = 1000053002, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT = 1000053003, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT = 1000053004, + XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT = 1000053005, + XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC = 1000059000, + XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT = 1000063000, + XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE = 1000079000, + XR_STRUCTURE_TYPE_MAX_ENUM = 0x7fffffff, +} XrStructureType; + +typedef enum XrViewConfigurationType +{ + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO = 1, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO = 2, + XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO = 1000037000, + XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT = 1000054000, + XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM = 0x7fffffff, +} XrViewConfigurationType; + +typedef enum XrVisibilityMaskTypeKHR +{ + XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR = 1, + XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR = 2, + XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR = 3, + XR_VISIBILITY_MASK_TYPE_KHR_MAX_ENUM = 0x7fffffff, +} XrVisibilityMaskTypeKHR; + +typedef struct XrActionCreateInfo XrActionCreateInfo; +typedef struct XrActionStateBoolean XrActionStateBoolean; +typedef struct XrActionStateGetInfo XrActionStateGetInfo; +typedef struct XrActionSuggestedBinding XrActionSuggestedBinding; +typedef struct XrActiveActionSet XrActiveActionSet; +typedef struct XrApplicationInfo XrApplicationInfo; +typedef struct XrBaseOutStructure XrBaseOutStructure; +typedef struct XrColor4f XrColor4f; +typedef struct XrDebugUtilsLabelEXT XrDebugUtilsLabelEXT; +typedef struct XrEventDataBaseHeader XrEventDataBaseHeader; +typedef struct XrEventDataEventsLost XrEventDataEventsLost; +typedef struct XrEventDataInteractionProfileChanged XrEventDataInteractionProfileChanged; +typedef struct XrEventDataPerfSettingsEXT XrEventDataPerfSettingsEXT; +typedef struct XrEventDataSessionStateChanged XrEventDataSessionStateChanged; +typedef struct XrExtensionProperties XrExtensionProperties; +typedef struct XrExtent2Di XrExtent2Di; +typedef struct XrFovf XrFovf; +typedef struct XrFrameState XrFrameState; +typedef struct XrGraphicsBindingD3D11KHR XrGraphicsBindingD3D11KHR; +typedef struct XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkanKHR; +typedef struct XrGraphicsRequirementsD3D12KHR XrGraphicsRequirementsD3D12KHR; +typedef struct XrGraphicsRequirementsOpenGLKHR XrGraphicsRequirementsOpenGLKHR; +typedef struct XrHandJointsLocateInfoEXT XrHandJointsLocateInfoEXT; +typedef struct XrHandMeshUpdateInfoMSFT XrHandMeshUpdateInfoMSFT; +typedef struct XrHandPoseTypeInfoMSFT XrHandPoseTypeInfoMSFT; +typedef struct XrHapticActionInfo XrHapticActionInfo; +typedef struct XrHapticVibration XrHapticVibration; +typedef struct XrInputSourceLocalizedNameGetInfo XrInputSourceLocalizedNameGetInfo; +typedef struct XrInteractionProfileState XrInteractionProfileState; +typedef struct XrOffset2Df XrOffset2Df; +typedef struct XrQuaternionf XrQuaternionf; +typedef struct XrSecondaryViewConfigurationSessionBeginInfoMSFT XrSecondaryViewConfigurationSessionBeginInfoMSFT; +typedef struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT XrSecondaryViewConfigurationSwapchainCreateInfoMSFT; +typedef struct XrSessionBeginInfo XrSessionBeginInfo; +typedef struct XrSessionCreateInfoOverlayEXTX XrSessionCreateInfoOverlayEXTX; +typedef struct XrSwapchainCreateInfo XrSwapchainCreateInfo; +typedef struct XrSwapchainImageBaseHeader XrSwapchainImageBaseHeader; +typedef struct XrSwapchainImageD3D12KHR XrSwapchainImageD3D12KHR; +typedef struct XrSwapchainImageOpenGLKHR XrSwapchainImageOpenGLKHR; +typedef struct XrSwapchainImageVulkanKHR XrSwapchainImageVulkanKHR; +typedef struct XrSystemEyeGazeInteractionPropertiesEXT XrSystemEyeGazeInteractionPropertiesEXT; +typedef struct XrSystemGraphicsProperties XrSystemGraphicsProperties; +typedef struct XrSystemHandTrackingPropertiesEXT XrSystemHandTrackingPropertiesEXT; +typedef struct XrSystemTrackingProperties XrSystemTrackingProperties; +typedef struct XrVector3f XrVector3f; +typedef struct XrViewConfigurationDepthRangeEXT XrViewConfigurationDepthRangeEXT; +typedef struct XrViewConfigurationView XrViewConfigurationView; +typedef struct XrViewLocateInfo XrViewLocateInfo; +typedef struct XrVulkanSwapchainFormatListCreateInfoKHR XrVulkanSwapchainFormatListCreateInfoKHR; +typedef struct XrActionSetCreateInfo XrActionSetCreateInfo; +typedef struct XrActionStateFloat XrActionStateFloat; +typedef struct XrActionsSyncInfo XrActionsSyncInfo; +typedef struct XrBaseInStructure XrBaseInStructure; +typedef struct XrCompositionLayerBaseHeader XrCompositionLayerBaseHeader; +typedef struct XrDebugUtilsObjectNameInfoEXT XrDebugUtilsObjectNameInfoEXT; +typedef struct XrEventDataInstanceLossPending XrEventDataInstanceLossPending; +typedef struct XrEventDataVisibilityMaskChangedKHR XrEventDataVisibilityMaskChangedKHR; +typedef struct XrEyeGazeSampleTimeEXT XrEyeGazeSampleTimeEXT; +typedef struct XrFrameEndInfo XrFrameEndInfo; +typedef struct XrGraphicsBindingD3D12KHR XrGraphicsBindingD3D12KHR; +typedef struct XrGraphicsRequirementsD3D11KHR XrGraphicsRequirementsD3D11KHR; +typedef struct XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkanKHR; +typedef struct XrHandJointVelocityEXT XrHandJointVelocityEXT; +typedef struct XrHandMeshVertexMSFT XrHandMeshVertexMSFT; +typedef struct XrHapticBaseHeader XrHapticBaseHeader; +typedef struct XrInstanceCreateInfo XrInstanceCreateInfo; +typedef struct XrInteractionProfileAnalogThresholdVALVE XrInteractionProfileAnalogThresholdVALVE; +typedef struct XrOffset2Di XrOffset2Di; +typedef struct XrRect2Di XrRect2Di; +typedef struct XrSecondaryViewConfigurationLayerInfoMSFT XrSecondaryViewConfigurationLayerInfoMSFT; +typedef struct XrSessionActionSetsAttachInfo XrSessionActionSetsAttachInfo; +typedef struct XrSpaceVelocity XrSpaceVelocity; +typedef struct XrSwapchainImageAcquireInfo XrSwapchainImageAcquireInfo; +typedef struct XrSwapchainImageWaitInfo XrSwapchainImageWaitInfo; +typedef struct XrSystemGetInfo XrSystemGetInfo; +typedef struct XrSystemProperties XrSystemProperties; +typedef struct XrVector4f XrVector4f; +typedef struct XrViewConfigurationProperties XrViewConfigurationProperties; +typedef struct XrViewState XrViewState; +typedef struct XrActionStatePose XrActionStatePose; +typedef struct XrApiLayerProperties XrApiLayerProperties; +typedef struct XrCompositionLayerCubeKHR XrCompositionLayerCubeKHR; +typedef struct XrDebugUtilsMessengerCallbackDataEXT XrDebugUtilsMessengerCallbackDataEXT; +typedef struct XrEventDataMainSessionVisibilityChangedEXTX XrEventDataMainSessionVisibilityChangedEXTX; +typedef struct XrExtent2Df XrExtent2Df; +typedef struct XrFrameWaitInfo XrFrameWaitInfo; +typedef struct XrHandJointVelocitiesEXT XrHandJointVelocitiesEXT; +typedef struct XrHandMeshVertexBufferMSFT XrHandMeshVertexBufferMSFT; +typedef struct XrHolographicWindowAttachmentMSFT XrHolographicWindowAttachmentMSFT; +typedef struct XrInteractionProfileSuggestedBinding XrInteractionProfileSuggestedBinding; +typedef struct XrRect2Df XrRect2Df; +typedef struct XrSecondaryViewConfigurationFrameEndInfoMSFT XrSecondaryViewConfigurationFrameEndInfoMSFT; +typedef struct XrSecondaryViewConfigurationStateMSFT XrSecondaryViewConfigurationStateMSFT; +typedef struct XrSwapchainImageD3D11KHR XrSwapchainImageD3D11KHR; +typedef struct XrSwapchainSubImage XrSwapchainSubImage; +typedef struct XrVector2f XrVector2f; +typedef struct XrViewConfigurationViewFovEPIC XrViewConfigurationViewFovEPIC; +typedef struct XrActionStateVector2f XrActionStateVector2f; +typedef struct XrCompositionLayerDepthInfoKHR XrCompositionLayerDepthInfoKHR; +typedef struct XrEventDataBuffer XrEventDataBuffer; +typedef struct XrFrameBeginInfo XrFrameBeginInfo; +typedef struct XrHandMeshIndexBufferMSFT XrHandMeshIndexBufferMSFT; +typedef struct XrHandTrackerCreateInfoEXT XrHandTrackerCreateInfoEXT; +typedef struct XrPosef XrPosef; +typedef struct XrSecondaryViewConfigurationFrameStateMSFT XrSecondaryViewConfigurationFrameStateMSFT; +typedef struct XrSpaceLocation XrSpaceLocation; +typedef struct XrSpatialAnchorSpaceCreateInfoMSFT XrSpatialAnchorSpaceCreateInfoMSFT; +typedef struct XrSwapchainImageReleaseInfo XrSwapchainImageReleaseInfo; +typedef struct XrView XrView; +typedef struct XrActionSpaceCreateInfo XrActionSpaceCreateInfo; +typedef struct XrCompositionLayerCylinderKHR XrCompositionLayerCylinderKHR; +typedef struct XrCompositionLayerProjectionView XrCompositionLayerProjectionView; +typedef struct XrEventDataReferenceSpaceChangePending XrEventDataReferenceSpaceChangePending; +typedef struct XrHandJointLocationEXT XrHandJointLocationEXT; +typedef struct XrHandMeshMSFT XrHandMeshMSFT; +typedef struct XrInstanceProperties XrInstanceProperties; +typedef struct XrSessionCreateInfo XrSessionCreateInfo; +typedef struct XrSpatialGraphNodeSpaceCreateInfoMSFT XrSpatialGraphNodeSpaceCreateInfoMSFT; +typedef struct XrVisibilityMaskKHR XrVisibilityMaskKHR; +typedef struct XrBoundSourcesForActionEnumerateInfo XrBoundSourcesForActionEnumerateInfo; +typedef struct XrCompositionLayerProjection XrCompositionLayerProjection; +typedef struct XrGraphicsBindingOpenGLWin32KHR XrGraphicsBindingOpenGLWin32KHR; +typedef struct XrHandMeshSpaceCreateInfoMSFT XrHandMeshSpaceCreateInfoMSFT; +typedef struct XrSpatialAnchorCreateInfoMSFT XrSpatialAnchorCreateInfoMSFT; +typedef struct XrCompositionLayerEquirectKHR XrCompositionLayerEquirectKHR; +typedef struct XrHandJointLocationsEXT XrHandJointLocationsEXT; +typedef struct XrSystemHandTrackingMeshPropertiesMSFT XrSystemHandTrackingMeshPropertiesMSFT; +typedef struct XrCompositionLayerQuad XrCompositionLayerQuad; +typedef struct XrReferenceSpaceCreateInfo XrReferenceSpaceCreateInfo; +typedef XrBool32 (XRAPI_PTR * PFN_xrDebugUtilsMessengerCallbackEXT)( + XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, + XrDebugUtilsMessageTypeFlagsEXT messageTypes, + const XrDebugUtilsMessengerCallbackDataEXT *callbackData, + void *userData); +typedef void (XRAPI_PTR * PFN_xrVoidFunction)( +void); + +struct XrActionCreateInfo +{ + XrStructureType type; + const void *next; + char actionName[XR_MAX_ACTION_NAME_SIZE]; + XrActionType actionType; + uint32_t countSubactionPaths; + const XrPath *subactionPaths; + char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE]; +}; + +struct XrActionStateBoolean +{ + XrStructureType type; + void *next; + XrBool32 currentState; + XrBool32 changedSinceLastSync; + XrTime lastChangeTime; + XrBool32 isActive; +}; + +struct XrActionStateGetInfo +{ + XrStructureType type; + const void *next; + XrAction action; + XrPath subactionPath; +}; + +struct XrActionSuggestedBinding +{ + XrAction action; + XrPath binding; +}; + +struct XrActiveActionSet +{ + XrActionSet actionSet; + XrPath subactionPath; +}; + +struct XrApplicationInfo +{ + char applicationName[XR_MAX_APPLICATION_NAME_SIZE]; + uint32_t applicationVersion; + char engineName[XR_MAX_ENGINE_NAME_SIZE]; + uint32_t engineVersion; + XrVersion apiVersion; +}; + +struct XrBaseOutStructure +{ + XrStructureType type; + struct XrBaseOutStructure *next; +}; + +struct XrColor4f +{ + float r; + float g; + float b; + float a; +}; + +struct XrDebugUtilsLabelEXT +{ + XrStructureType type; + const void *next; + const char *labelName; +}; + +struct XrEventDataBaseHeader +{ + XrStructureType type; + const void *next; +}; + +struct XrEventDataEventsLost +{ + XrStructureType type; + const void *next; + uint32_t lostEventCount; +}; + +struct XrEventDataInteractionProfileChanged +{ + XrStructureType type; + const void *next; + XrSession session; +}; + +struct XrEventDataPerfSettingsEXT +{ + XrStructureType type; + const void *next; + XrPerfSettingsDomainEXT domain; + XrPerfSettingsSubDomainEXT subDomain; + XrPerfSettingsNotificationLevelEXT fromLevel; + XrPerfSettingsNotificationLevelEXT toLevel; +}; + +struct XrEventDataSessionStateChanged +{ + XrStructureType type; + const void *next; + XrSession session; + XrSessionState state; + XrTime time; +}; + +struct XrExtensionProperties +{ + XrStructureType type; + void *next; + char extensionName[XR_MAX_EXTENSION_NAME_SIZE]; + uint32_t extensionVersion; +}; + +struct XrExtent2Di +{ + int32_t width; + int32_t height; +}; + +struct XrFovf +{ + float angleLeft; + float angleRight; + float angleUp; + float angleDown; +}; + +struct XrFrameState +{ + XrStructureType type; + void *next; + XrTime predictedDisplayTime; + XrDuration predictedDisplayPeriod; + XrBool32 shouldRender; +}; + +struct XrGraphicsBindingD3D11KHR +{ + XrStructureType type; + const void *next; + ID3D11Device *device; +}; + +struct XrGraphicsBindingVulkanKHR +{ + XrStructureType type; + const void *next; + VkInstance instance; + VkPhysicalDevice physicalDevice; + VkDevice device; + uint32_t queueFamilyIndex; + uint32_t queueIndex; +}; + +struct XrGraphicsRequirementsD3D12KHR +{ + XrStructureType type; + void *next; + LUID adapterLuid; + D3D_FEATURE_LEVEL minFeatureLevel; +}; + +struct XrGraphicsRequirementsOpenGLKHR +{ + XrStructureType type; + void *next; + XrVersion minApiVersionSupported; + XrVersion maxApiVersionSupported; +}; + +struct XrHandJointsLocateInfoEXT +{ + XrStructureType type; + const void *next; + XrSpace baseSpace; + XrTime time; +}; + +struct XrHandMeshUpdateInfoMSFT +{ + XrStructureType type; + const void *next; + XrTime time; + XrHandPoseTypeMSFT handPoseType; +}; + +struct XrHandPoseTypeInfoMSFT +{ + XrStructureType type; + const void *next; + XrHandPoseTypeMSFT handPoseType; +}; + +struct XrHapticActionInfo +{ + XrStructureType type; + const void *next; + XrAction action; + XrPath subactionPath; +}; + +struct XrHapticVibration +{ + XrStructureType type; + const void *next; + XrDuration duration; + float frequency; + float amplitude; +}; + +struct XrInputSourceLocalizedNameGetInfo +{ + XrStructureType type; + const void *next; + XrPath sourcePath; + XrInputSourceLocalizedNameFlags whichComponents; +}; + +struct XrInteractionProfileState +{ + XrStructureType type; + void *next; + XrPath interactionProfile; +}; + +struct XrOffset2Df +{ + float x; + float y; +}; + +struct XrQuaternionf +{ + float x; + float y; + float z; + float w; +}; + +struct XrSecondaryViewConfigurationSessionBeginInfoMSFT +{ + XrStructureType type; + const void *next; + uint32_t viewConfigurationCount; + const XrViewConfigurationType *enabledViewConfigurationTypes; +}; + +struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT +{ + XrStructureType type; + const void *next; + XrViewConfigurationType viewConfigurationType; +}; + +struct XrSessionBeginInfo +{ + XrStructureType type; + const void *next; + XrViewConfigurationType primaryViewConfigurationType; +}; + +struct XrSessionCreateInfoOverlayEXTX +{ + XrStructureType type; + const void *next; + XrOverlaySessionCreateFlagsEXTX createFlags; + uint32_t sessionLayersPlacement; +}; + +struct XrSwapchainCreateInfo +{ + XrStructureType type; + const void *next; + XrSwapchainCreateFlags createFlags; + XrSwapchainUsageFlags usageFlags; + int64_t format; + uint32_t sampleCount; + uint32_t width; + uint32_t height; + uint32_t faceCount; + uint32_t arraySize; + uint32_t mipCount; +}; + +struct XrSwapchainImageBaseHeader +{ + XrStructureType type; + void *next; +}; + +struct XrSwapchainImageD3D12KHR +{ + XrStructureType type; + void *next; + ID3D12Resource *texture; +}; + +struct XrSwapchainImageOpenGLKHR +{ + XrStructureType type; + void *next; + uint32_t image; +}; + +struct XrSwapchainImageVulkanKHR +{ + XrStructureType type; + void *next; + VkImage image; +}; + +struct XrSystemEyeGazeInteractionPropertiesEXT +{ + XrStructureType type; + void *next; + XrBool32 supportsEyeGazeInteraction; +}; + +struct XrSystemGraphicsProperties +{ + uint32_t maxSwapchainImageHeight; + uint32_t maxSwapchainImageWidth; + uint32_t maxLayerCount; +}; + +struct XrSystemHandTrackingPropertiesEXT +{ + XrStructureType type; + void *next; + XrBool32 supportsHandTracking; +}; + +struct XrSystemTrackingProperties +{ + XrBool32 orientationTracking; + XrBool32 positionTracking; +}; + +struct XrVector3f +{ + float x; + float y; + float z; +}; + +struct XrViewConfigurationDepthRangeEXT +{ + XrStructureType type; + void *next; + float recommendedNearZ; + float minNearZ; + float recommendedFarZ; + float maxFarZ; +}; + +struct XrViewConfigurationView +{ + XrStructureType type; + void *next; + uint32_t recommendedImageRectWidth; + uint32_t maxImageRectWidth; + uint32_t recommendedImageRectHeight; + uint32_t maxImageRectHeight; + uint32_t recommendedSwapchainSampleCount; + uint32_t maxSwapchainSampleCount; +}; + +struct XrViewLocateInfo +{ + XrStructureType type; + const void *next; + XrViewConfigurationType viewConfigurationType; + XrTime displayTime; + XrSpace space; +}; + +struct XrVulkanSwapchainFormatListCreateInfoKHR +{ + XrStructureType type; + const void *next; + uint32_t viewFormatCount; + const VkFormat *viewFormats; +}; + +struct XrActionSetCreateInfo +{ + XrStructureType type; + const void *next; + char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE]; + char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE]; + uint32_t priority; +}; + +struct XrActionStateFloat +{ + XrStructureType type; + void *next; + float currentState; + XrBool32 changedSinceLastSync; + XrTime lastChangeTime; + XrBool32 isActive; +}; + +struct XrActionsSyncInfo +{ + XrStructureType type; + const void *next; + uint32_t countActiveActionSets; + const XrActiveActionSet *activeActionSets; +}; + +struct XrBaseInStructure +{ + XrStructureType type; + const struct XrBaseInStructure *next; +}; + +struct XrCompositionLayerBaseHeader +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; +}; + +struct XrDebugUtilsObjectNameInfoEXT +{ + XrStructureType type; + const void *next; + XrObjectType objectType; + uint64_t WINE_XR_ALIGN(8) objectHandle; + const char *objectName; +}; + +struct XrEventDataInstanceLossPending +{ + XrStructureType type; + const void *next; + XrTime lossTime; +}; + +struct XrEventDataVisibilityMaskChangedKHR +{ + XrStructureType type; + const void *next; + XrSession session; + XrViewConfigurationType viewConfigurationType; + uint32_t viewIndex; +}; + +struct XrEyeGazeSampleTimeEXT +{ + XrStructureType type; + void *next; + XrTime time; +}; + +struct XrFrameEndInfo +{ + XrStructureType type; + const void *next; + XrTime displayTime; + XrEnvironmentBlendMode environmentBlendMode; + uint32_t layerCount; + const XrCompositionLayerBaseHeader * const*layers; +}; + +struct XrGraphicsBindingD3D12KHR +{ + XrStructureType type; + const void *next; + ID3D12Device *device; + ID3D12CommandQueue *queue; +}; + +struct XrGraphicsRequirementsD3D11KHR +{ + XrStructureType type; + void *next; + LUID adapterLuid; + D3D_FEATURE_LEVEL minFeatureLevel; +}; + +struct XrGraphicsRequirementsVulkanKHR +{ + XrStructureType type; + void *next; + XrVersion minApiVersionSupported; + XrVersion maxApiVersionSupported; +}; + +struct XrHandJointVelocityEXT +{ + XrSpaceVelocityFlags velocityFlags; + XrVector3f linearVelocity; + XrVector3f angularVelocity; +}; + +struct XrHandMeshVertexMSFT +{ + XrVector3f position; + XrVector3f normal; +}; + +struct XrHapticBaseHeader +{ + XrStructureType type; + const void *next; +}; + +struct XrInstanceCreateInfo +{ + XrStructureType type; + const void *next; + XrInstanceCreateFlags createFlags; + XrApplicationInfo applicationInfo; + uint32_t enabledApiLayerCount; + const char * const*enabledApiLayerNames; + uint32_t enabledExtensionCount; + const char * const*enabledExtensionNames; +}; + +struct XrInteractionProfileAnalogThresholdVALVE +{ + XrStructureType type; + const void *next; + XrAction action; + XrPath binding; + float onThreshold; + float offThreshold; + const XrHapticBaseHeader *onHaptic; + const XrHapticBaseHeader *offHaptic; +}; + +struct XrOffset2Di +{ + int32_t x; + int32_t y; +}; + +struct XrRect2Di +{ + XrOffset2Di offset; + XrExtent2Di extent; +}; + +struct XrSecondaryViewConfigurationLayerInfoMSFT +{ + XrStructureType type; + const void *next; + XrViewConfigurationType viewConfigurationType; + XrEnvironmentBlendMode environmentBlendMode; + uint32_t layerCount; + const XrCompositionLayerBaseHeader * const*layers; +}; + +struct XrSessionActionSetsAttachInfo +{ + XrStructureType type; + const void *next; + uint32_t countActionSets; + const XrActionSet *actionSets; +}; + +struct XrSpaceVelocity +{ + XrStructureType type; + void *next; + XrSpaceVelocityFlags velocityFlags; + XrVector3f linearVelocity; + XrVector3f angularVelocity; +}; + +struct XrSwapchainImageAcquireInfo +{ + XrStructureType type; + const void *next; +}; + +struct XrSwapchainImageWaitInfo +{ + XrStructureType type; + const void *next; + XrDuration timeout; +}; + +struct XrSystemGetInfo +{ + XrStructureType type; + const void *next; + XrFormFactor formFactor; +}; + +struct XrSystemProperties +{ + XrStructureType type; + void *next; + XrSystemId systemId; + uint32_t vendorId; + char systemName[XR_MAX_SYSTEM_NAME_SIZE]; + XrSystemGraphicsProperties graphicsProperties; + XrSystemTrackingProperties trackingProperties; +}; + +struct XrVector4f +{ + float x; + float y; + float z; + float w; +}; + +struct XrViewConfigurationProperties +{ + XrStructureType type; + void *next; + XrViewConfigurationType viewConfigurationType; + XrBool32 fovMutable; +}; + +struct XrViewState +{ + XrStructureType type; + void *next; + XrViewStateFlags viewStateFlags; +}; + +struct XrActionStatePose +{ + XrStructureType type; + void *next; + XrBool32 isActive; +}; + +struct XrApiLayerProperties +{ + XrStructureType type; + void *next; + char layerName[XR_MAX_API_LAYER_NAME_SIZE]; + XrVersion specVersion; + uint32_t layerVersion; + char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE]; +}; + +struct XrCompositionLayerCubeKHR +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; + XrEyeVisibility eyeVisibility; + XrSwapchain swapchain; + uint32_t imageArrayIndex; + XrQuaternionf orientation; +}; + +struct XrDebugUtilsMessengerCallbackDataEXT +{ + XrStructureType type; + const void *next; + const char *messageId; + const char *functionName; + const char *message; + uint32_t objectCount; + XrDebugUtilsObjectNameInfoEXT *objects; + uint32_t sessionLabelCount; + XrDebugUtilsLabelEXT *sessionLabels; +}; + +struct XrEventDataMainSessionVisibilityChangedEXTX +{ + XrStructureType type; + const void *next; + XrBool32 visible; + XrOverlayMainSessionFlagsEXTX flags; +}; + +struct XrExtent2Df +{ + float width; + float height; +}; + +struct XrFrameWaitInfo +{ + XrStructureType type; + const void *next; +}; + +struct XrHandJointVelocitiesEXT +{ + XrStructureType type; + void *next; + uint32_t jointCount; + XrHandJointVelocityEXT *jointVelocities; +}; + +struct XrHandMeshVertexBufferMSFT +{ + XrTime vertexUpdateTime; + uint32_t vertexCapacityInput; + uint32_t vertexCountOutput; + XrHandMeshVertexMSFT *vertices; +}; + +struct XrHolographicWindowAttachmentMSFT +{ + XrStructureType type; + const void *next; + IUnknown *holographicSpace; + IUnknown *coreWindow; +}; + +struct XrInteractionProfileSuggestedBinding +{ + XrStructureType type; + const void *next; + XrPath interactionProfile; + uint32_t countSuggestedBindings; + const XrActionSuggestedBinding *suggestedBindings; +}; + +struct XrRect2Df +{ + XrOffset2Df offset; + XrExtent2Df extent; +}; + +struct XrSecondaryViewConfigurationFrameEndInfoMSFT +{ + XrStructureType type; + const void *next; + uint32_t viewConfigurationCount; + const XrSecondaryViewConfigurationLayerInfoMSFT *viewConfigurationLayersInfo; +}; + +struct XrSecondaryViewConfigurationStateMSFT +{ + XrStructureType type; + void *next; + XrViewConfigurationType viewConfigurationType; + XrBool32 active; +}; + +struct XrSwapchainImageD3D11KHR +{ + XrStructureType type; + void *next; + ID3D11Texture2D *texture; +}; + +struct XrSwapchainSubImage +{ + XrSwapchain swapchain; + XrRect2Di imageRect; + uint32_t imageArrayIndex; +}; + +struct XrVector2f +{ + float x; + float y; +}; + +struct XrViewConfigurationViewFovEPIC +{ + XrStructureType type; + const void *next; + XrFovf recommendedFov; + XrFovf maxMutableFov; +}; + +struct XrActionStateVector2f +{ + XrStructureType type; + void *next; + XrVector2f currentState; + XrBool32 changedSinceLastSync; + XrTime lastChangeTime; + XrBool32 isActive; +}; + +struct XrCompositionLayerDepthInfoKHR +{ + XrStructureType type; + const void *next; + XrSwapchainSubImage subImage; + float minDepth; + float maxDepth; + float nearZ; + float farZ; +}; + +struct XrEventDataBuffer +{ + XrStructureType type; + const void *next; + uint8_t varying[4000]; +}; + +struct XrFrameBeginInfo +{ + XrStructureType type; + const void *next; +}; + +struct XrHandMeshIndexBufferMSFT +{ + uint32_t indexBufferKey; + uint32_t indexCapacityInput; + uint32_t indexCountOutput; + uint32_t *indices; +}; + +struct XrHandTrackerCreateInfoEXT +{ + XrStructureType type; + const void *next; + XrHandEXT hand; + XrHandJointSetEXT handJointSet; +}; + +struct XrPosef +{ + XrQuaternionf orientation; + XrVector3f position; +}; + +struct XrSecondaryViewConfigurationFrameStateMSFT +{ + XrStructureType type; + void *next; + uint32_t viewConfigurationCount; + XrSecondaryViewConfigurationStateMSFT *viewConfigurationStates; +}; + +struct XrSpaceLocation +{ + XrStructureType type; + void *next; + XrSpaceLocationFlags locationFlags; + XrPosef pose; +}; + +struct XrSpatialAnchorSpaceCreateInfoMSFT +{ + XrStructureType type; + const void *next; + XrSpatialAnchorMSFT anchor; + XrPosef poseInAnchorSpace; +}; + +struct XrSwapchainImageReleaseInfo +{ + XrStructureType type; + const void *next; +}; + +struct XrView +{ + XrStructureType type; + void *next; + XrPosef pose; + XrFovf fov; +}; + +struct XrActionSpaceCreateInfo +{ + XrStructureType type; + const void *next; + XrAction action; + XrPath subactionPath; + XrPosef poseInActionSpace; +}; + +struct XrCompositionLayerCylinderKHR +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; + XrEyeVisibility eyeVisibility; + XrSwapchainSubImage subImage; + XrPosef pose; + float radius; + float centralAngle; + float aspectRatio; +}; + +struct XrCompositionLayerProjectionView +{ + XrStructureType type; + const void *next; + XrPosef pose; + XrFovf fov; + XrSwapchainSubImage subImage; +}; + +struct XrEventDataReferenceSpaceChangePending +{ + XrStructureType type; + const void *next; + XrSession session; + XrReferenceSpaceType referenceSpaceType; + XrTime changeTime; + XrBool32 poseValid; + XrPosef poseInPreviousSpace; +}; + +struct XrHandJointLocationEXT +{ + XrSpaceLocationFlags locationFlags; + XrPosef pose; + float radius; +}; + +struct XrHandMeshMSFT +{ + XrStructureType type; + void *next; + XrBool32 isActive; + XrBool32 indexBufferChanged; + XrBool32 vertexBufferChanged; + XrHandMeshIndexBufferMSFT indexBuffer; + XrHandMeshVertexBufferMSFT vertexBuffer; +}; + +struct XrInstanceProperties +{ + XrStructureType type; + void *next; + XrVersion runtimeVersion; + char runtimeName[XR_MAX_RUNTIME_NAME_SIZE]; +}; + +struct XrSessionCreateInfo +{ + XrStructureType type; + const void *next; + XrSessionCreateFlags createFlags; + XrSystemId systemId; +}; + +struct XrSpatialGraphNodeSpaceCreateInfoMSFT +{ + XrStructureType type; + const void *next; + XrSpatialGraphNodeTypeMSFT nodeType; + uint8_t nodeId[16]; + XrPosef pose; +}; + +struct XrVisibilityMaskKHR +{ + XrStructureType type; + void *next; + uint32_t vertexCapacityInput; + uint32_t vertexCountOutput; + XrVector2f *vertices; + uint32_t indexCapacityInput; + uint32_t indexCountOutput; + uint32_t *indices; +}; + +struct XrBoundSourcesForActionEnumerateInfo +{ + XrStructureType type; + const void *next; + XrAction action; +}; + +struct XrCompositionLayerProjection +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; + uint32_t viewCount; + const XrCompositionLayerProjectionView *views; +}; + +struct XrGraphicsBindingOpenGLWin32KHR +{ + XrStructureType type; + const void *next; + HDC hDC; + HGLRC hGLRC; +}; + +struct XrHandMeshSpaceCreateInfoMSFT +{ + XrStructureType type; + const void *next; + XrHandPoseTypeMSFT handPoseType; + XrPosef poseInHandMeshSpace; +}; + +struct XrSpatialAnchorCreateInfoMSFT +{ + XrStructureType type; + const void *next; + XrSpace space; + XrPosef pose; + XrTime time; +}; + +struct XrCompositionLayerEquirectKHR +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; + XrEyeVisibility eyeVisibility; + XrSwapchainSubImage subImage; + XrPosef pose; + float radius; + XrVector2f scale; + XrVector2f bias; +}; + +struct XrHandJointLocationsEXT +{ + XrStructureType type; + void *next; + XrBool32 isActive; + uint32_t jointCount; + XrHandJointLocationEXT *jointLocations; +}; + +struct XrSystemHandTrackingMeshPropertiesMSFT +{ + XrStructureType type; + void *next; + XrBool32 supportsHandTrackingMesh; + uint32_t maxHandMeshIndexCount; + uint32_t maxHandMeshVertexCount; +}; + +struct XrCompositionLayerQuad +{ + XrStructureType type; + const void *next; + XrCompositionLayerFlags layerFlags; + XrSpace space; + XrEyeVisibility eyeVisibility; + XrSwapchainSubImage subImage; + XrPosef pose; + XrExtent2Df size; +}; + +struct XrReferenceSpaceCreateInfo +{ + XrStructureType type; + const void *next; + XrReferenceSpaceType referenceSpaceType; + XrPosef poseInReferenceSpace; +}; + +typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain, const XrSwapchainImageAcquireInfo *, uint32_t *); +typedef XrResult (XRAPI_PTR *PFN_xrApplyHapticFeedback)(XrSession, const XrHapticActionInfo *, const XrHapticBaseHeader *); +typedef XrResult (XRAPI_PTR *PFN_xrAttachSessionActionSets)(XrSession, const XrSessionActionSetsAttachInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrBeginFrame)(XrSession, const XrFrameBeginInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession, const XrSessionBeginInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance, XrTime, LARGE_INTEGER *); +typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance, const LARGE_INTEGER *, XrTime *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet, const XrActionCreateInfo *, XrAction *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance, const XrActionSetCreateInfo *, XrActionSet *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession, const XrActionSpaceCreateInfo *, XrSpace *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT, const XrHandMeshSpaceCreateInfoMSFT *, XrSpace *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateHandTrackerEXT)(XrSession, const XrHandTrackerCreateInfoEXT *, XrHandTrackerEXT *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateInstance)(const XrInstanceCreateInfo *, XrInstance *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession, const XrReferenceSpaceCreateInfo *, XrSpace *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSession)(XrInstance, const XrSessionCreateInfo *, XrSession *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorMSFT)(XrSession, const XrSpatialAnchorCreateInfoMSFT *, XrSpatialAnchorMSFT *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorSpaceMSFT)(XrSession, const XrSpatialAnchorSpaceCreateInfoMSFT *, XrSpace *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession, const XrSpatialGraphNodeSpaceCreateInfoMSFT *, XrSpace *); +typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession, const XrSwapchainCreateInfo *, XrSwapchain *); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyAction)(XrAction); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyActionSet)(XrActionSet); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyHandTrackerEXT)(XrHandTrackerEXT); +typedef XrResult (XRAPI_PTR *PFN_xrDestroyInstance)(XrInstance); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySession)(XrSession); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT); +typedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain); +typedef XrResult (XRAPI_PTR *PFN_xrEndFrame)(XrSession, const XrFrameEndInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateApiLayerProperties)(uint32_t, uint32_t *, XrApiLayerProperties *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateBoundSourcesForAction)(XrSession, const XrBoundSourcesForActionEnumerateInfo *, uint32_t, uint32_t *, XrPath *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateEnvironmentBlendModes)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrEnvironmentBlendMode *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateInstanceExtensionProperties)(const char *, uint32_t, uint32_t *, XrExtensionProperties *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession, uint32_t, uint32_t *, XrReferenceSpaceType *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession, uint32_t, uint32_t *, int64_t *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain, uint32_t, uint32_t *, XrSwapchainImageBaseHeader *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurationViews)(XrInstance, XrSystemId, XrViewConfigurationType, uint32_t, uint32_t *, XrViewConfigurationView *); +typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance, XrSystemId, uint32_t, uint32_t *, XrViewConfigurationType *); +typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateBoolean)(XrSession, const XrActionStateGetInfo *, XrActionStateBoolean *); +typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateFloat)(XrSession, const XrActionStateGetInfo *, XrActionStateFloat *); +typedef XrResult (XRAPI_PTR *PFN_xrGetActionStatePose)(XrSession, const XrActionStateGetInfo *, XrActionStatePose *); +typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateVector2f)(XrSession, const XrActionStateGetInfo *, XrActionStateVector2f *); +typedef XrResult (XRAPI_PTR *PFN_xrGetCurrentInteractionProfile)(XrSession, XrPath, XrInteractionProfileState *); +typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsD3D11KHR *); +typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsD3D12KHR *); +typedef XrResult (XRAPI_PTR *PFN_xrGetInputSourceLocalizedName)(XrSession, const XrInputSourceLocalizedNameGetInfo *, uint32_t, uint32_t *, char *); +typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance, const char *, PFN_xrVoidFunction *); +typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProperties)(XrInstance, XrInstanceProperties *); +typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsOpenGLKHR *); +typedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession, XrReferenceSpaceType, XrExtent2Df *); +typedef XrResult (XRAPI_PTR *PFN_xrGetSystem)(XrInstance, const XrSystemGetInfo *, XrSystemId *); +typedef XrResult (XRAPI_PTR *PFN_xrGetSystemProperties)(XrInstance, XrSystemId, XrSystemProperties *); +typedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance, XrSystemId, XrViewConfigurationType, XrViewConfigurationProperties *); +typedef XrResult (XRAPI_PTR *PFN_xrGetVisibilityMaskKHR)(XrSession, XrViewConfigurationType, uint32_t, XrVisibilityMaskTypeKHR, XrVisibilityMaskKHR *); +typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *); +typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance, XrSystemId, VkInstance, VkPhysicalDevice *); +typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance, XrSystemId, XrGraphicsRequirementsVulkanKHR *); +typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance, XrSystemId, uint32_t, uint32_t *, char *); +typedef XrResult (XRAPI_PTR *PFN_xrLocateHandJointsEXT)(XrHandTrackerEXT, const XrHandJointsLocateInfoEXT *, XrHandJointLocationsEXT *); +typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace, XrSpace, XrTime, XrSpaceLocation *); +typedef XrResult (XRAPI_PTR *PFN_xrLocateViews)(XrSession, const XrViewLocateInfo *, XrViewState *, uint32_t, uint32_t *, XrView *); +typedef XrResult (XRAPI_PTR *PFN_xrPathToString)(XrInstance, XrPath, uint32_t, uint32_t *, char *); +typedef XrResult (XRAPI_PTR *PFN_xrPerfSettingsSetPerformanceLevelEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsLevelEXT); +typedef XrResult (XRAPI_PTR *PFN_xrPollEvent)(XrInstance, XrEventDataBuffer *); +typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain, const XrSwapchainImageReleaseInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession); +typedef XrResult (XRAPI_PTR *PFN_xrResultToString)(XrInstance, XrResult, char[]); +typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceActiveEXT)(XrSession, XrPath, XrPath, XrBool32); +typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceLocationEXT)(XrSession, XrPath, XrPath, XrSpace, XrPosef); +typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateBoolEXT)(XrSession, XrPath, XrPath, XrBool32); +typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateFloatEXT)(XrSession, XrPath, XrPath, float); +typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateVector2fEXT)(XrSession, XrPath, XrPath, XrVector2f); +typedef XrResult (XRAPI_PTR *PFN_xrStopHapticFeedback)(XrSession, const XrHapticActionInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrStringToPath)(XrInstance, const char *, XrPath *); +typedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString)(XrInstance, XrStructureType, char[]); +typedef XrResult (XRAPI_PTR *PFN_xrSuggestInteractionProfileBindings)(XrInstance, const XrInteractionProfileSuggestedBinding *); +typedef XrResult (XRAPI_PTR *PFN_xrSyncActions)(XrSession, const XrActionsSyncInfo *); +typedef XrResult (XRAPI_PTR *PFN_xrThermalGetTemperatureTrendEXT)(XrSession, XrPerfSettingsDomainEXT, XrPerfSettingsNotificationLevelEXT *, float *, float *); +typedef XrResult (XRAPI_PTR *PFN_xrUpdateHandMeshMSFT)(XrHandTrackerEXT, const XrHandMeshUpdateInfoMSFT *, XrHandMeshMSFT *); +typedef XrResult (XRAPI_PTR *PFN_xrWaitFrame)(XrSession, const XrFrameWaitInfo *, XrFrameState *); +typedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain, const XrSwapchainImageWaitInfo *); + +#ifndef XR_NO_PROTOTYPES +XrResult XRAPI_CALL xrAcquireSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo *acquireInfo, uint32_t *index); +XrResult XRAPI_CALL xrApplyHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo, const XrHapticBaseHeader *hapticFeedback); +XrResult XRAPI_CALL xrAttachSessionActionSets(XrSession session, const XrSessionActionSetsAttachInfo *attachInfo); +XrResult XRAPI_CALL xrBeginFrame(XrSession session, const XrFrameBeginInfo *frameBeginInfo); +XrResult XRAPI_CALL xrBeginSession(XrSession session, const XrSessionBeginInfo *beginInfo); +XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, XrTime time, LARGE_INTEGER *performanceCounter); +XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, const LARGE_INTEGER *performanceCounter, XrTime *time); +XrResult XRAPI_CALL xrCreateAction(XrActionSet actionSet, const XrActionCreateInfo *createInfo, XrAction *action); +XrResult XRAPI_CALL xrCreateActionSet(XrInstance instance, const XrActionSetCreateInfo *createInfo, XrActionSet *actionSet); +XrResult XRAPI_CALL xrCreateActionSpace(XrSession session, const XrActionSpaceCreateInfo *createInfo, XrSpace *space); +XrResult XRAPI_CALL xrCreateHandMeshSpaceMSFT(XrHandTrackerEXT handTracker, const XrHandMeshSpaceCreateInfoMSFT *createInfo, XrSpace *space); +XrResult XRAPI_CALL xrCreateHandTrackerEXT(XrSession session, const XrHandTrackerCreateInfoEXT *createInfo, XrHandTrackerEXT *handTracker); +XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *createInfo, XrInstance *instance); +XrResult XRAPI_CALL xrCreateReferenceSpace(XrSession session, const XrReferenceSpaceCreateInfo *createInfo, XrSpace *space); +XrResult XRAPI_CALL xrCreateSession(XrInstance instance, const XrSessionCreateInfo *createInfo, XrSession *session); +XrResult XRAPI_CALL xrCreateSpatialAnchorMSFT(XrSession session, const XrSpatialAnchorCreateInfoMSFT *createInfo, XrSpatialAnchorMSFT *anchor); +XrResult XRAPI_CALL xrCreateSpatialAnchorSpaceMSFT(XrSession session, const XrSpatialAnchorSpaceCreateInfoMSFT *createInfo, XrSpace *space); +XrResult XRAPI_CALL xrCreateSpatialGraphNodeSpaceMSFT(XrSession session, const XrSpatialGraphNodeSpaceCreateInfoMSFT *createInfo, XrSpace *space); +XrResult XRAPI_CALL xrCreateSwapchain(XrSession session, const XrSwapchainCreateInfo *createInfo, XrSwapchain *swapchain); +XrResult XRAPI_CALL xrDestroyAction(XrAction action); +XrResult XRAPI_CALL xrDestroyActionSet(XrActionSet actionSet); +XrResult XRAPI_CALL xrDestroyHandTrackerEXT(XrHandTrackerEXT handTracker); +XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance); +XrResult XRAPI_CALL xrDestroySession(XrSession session); +XrResult XRAPI_CALL xrDestroySpace(XrSpace space); +XrResult XRAPI_CALL xrDestroySpatialAnchorMSFT(XrSpatialAnchorMSFT anchor); +XrResult XRAPI_CALL xrDestroySwapchain(XrSwapchain swapchain); +XrResult XRAPI_CALL xrEndFrame(XrSession session, const XrFrameEndInfo *frameEndInfo); +XrResult XRAPI_CALL xrEndSession(XrSession session); +XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrApiLayerProperties *properties); +XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(XrSession session, const XrBoundSourcesForActionEnumerateInfo *enumerateInfo, uint32_t sourceCapacityInput, uint32_t *sourceCountOutput, XrPath *sources); +XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t *environmentBlendModeCountOutput, XrEnvironmentBlendMode *environmentBlendModes); +XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, XrExtensionProperties *properties); +XrResult XRAPI_CALL xrEnumerateReferenceSpaces(XrSession session, uint32_t spaceCapacityInput, uint32_t *spaceCountOutput, XrReferenceSpaceType *spaces); +XrResult XRAPI_CALL xrEnumerateSwapchainFormats(XrSession session, uint32_t formatCapacityInput, uint32_t *formatCountOutput, int64_t *formats); +XrResult XRAPI_CALL xrEnumerateSwapchainImages(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t *imageCountOutput, XrSwapchainImageBaseHeader *images); +XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrViewConfigurationView *views); +XrResult XRAPI_CALL xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t *viewConfigurationTypeCountOutput, XrViewConfigurationType *viewConfigurationTypes); +XrResult XRAPI_CALL xrGetActionStateBoolean(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateBoolean *state); +XrResult XRAPI_CALL xrGetActionStateFloat(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateFloat *state); +XrResult XRAPI_CALL xrGetActionStatePose(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStatePose *state); +XrResult XRAPI_CALL xrGetActionStateVector2f(XrSession session, const XrActionStateGetInfo *getInfo, XrActionStateVector2f *state); +XrResult XRAPI_CALL xrGetCurrentInteractionProfile(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState *interactionProfile); +XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR *graphicsRequirements); +XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR *graphicsRequirements); +XrResult XRAPI_CALL xrGetInputSourceLocalizedName(XrSession session, const XrInputSourceLocalizedNameGetInfo *getInfo, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer); +XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char *name, PFN_xrVoidFunction *function); +XrResult XRAPI_CALL xrGetInstanceProperties(XrInstance instance, XrInstanceProperties *instanceProperties); +XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR *graphicsRequirements); +XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df *bounds); +XrResult XRAPI_CALL xrGetSystem(XrInstance instance, const XrSystemGetInfo *getInfo, XrSystemId *systemId); +XrResult XRAPI_CALL xrGetSystemProperties(XrInstance instance, XrSystemId systemId, XrSystemProperties *properties); +XrResult XRAPI_CALL xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties *configurationProperties); +XrResult XRAPI_CALL xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR *visibilityMask); +XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer); +XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice *vkPhysicalDevice); +XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR *graphicsRequirements); +XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer); +XrResult XRAPI_CALL xrLocateHandJointsEXT(XrHandTrackerEXT handTracker, const XrHandJointsLocateInfoEXT *locateInfo, XrHandJointLocationsEXT *locations); +XrResult XRAPI_CALL xrLocateSpace(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation *location); +XrResult XRAPI_CALL xrLocateViews(XrSession session, const XrViewLocateInfo *viewLocateInfo, XrViewState *viewState, uint32_t viewCapacityInput, uint32_t *viewCountOutput, XrView *views); +XrResult XRAPI_CALL xrPathToString(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t *bufferCountOutput, char *buffer); +XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level); +XrResult XRAPI_CALL xrPollEvent(XrInstance instance, XrEventDataBuffer *eventData); +XrResult XRAPI_CALL xrReleaseSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo *releaseInfo); +XrResult XRAPI_CALL xrRequestExitSession(XrSession session); +XrResult XRAPI_CALL xrResultToString(XrInstance instance, XrResult value, char buffer[]); +XrResult XRAPI_CALL xrSetInputDeviceActiveEXT(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive); +XrResult XRAPI_CALL xrSetInputDeviceLocationEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose); +XrResult XRAPI_CALL xrSetInputDeviceStateBoolEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state); +XrResult XRAPI_CALL xrSetInputDeviceStateFloatEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state); +XrResult XRAPI_CALL xrSetInputDeviceStateVector2fEXT(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state); +XrResult XRAPI_CALL xrStopHapticFeedback(XrSession session, const XrHapticActionInfo *hapticActionInfo); +XrResult XRAPI_CALL xrStringToPath(XrInstance instance, const char *pathString, XrPath *path); +XrResult XRAPI_CALL xrStructureTypeToString(XrInstance instance, XrStructureType value, char buffer[]); +XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(XrInstance instance, const XrInteractionProfileSuggestedBinding *suggestedBindings); +XrResult XRAPI_CALL xrSyncActions(XrSession session, const XrActionsSyncInfo *syncInfo); +XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT *notificationLevel, float *tempHeadroom, float *tempSlope); +XrResult XRAPI_CALL xrUpdateHandMeshMSFT(XrHandTrackerEXT handTracker, const XrHandMeshUpdateInfoMSFT *updateInfo, XrHandMeshMSFT *handMesh); +XrResult XRAPI_CALL xrWaitFrame(XrSession session, const XrFrameWaitInfo *frameWaitInfo, XrFrameState *frameState); +XrResult XRAPI_CALL xrWaitSwapchainImage(XrSwapchain swapchain, const XrSwapchainImageWaitInfo *waitInfo); +#endif /* XR_NO_PROTOTYPES */ + +#endif /* __WINE_OPENXR_H */ diff --git a/wineopenxr/wineopenxr.spec b/wineopenxr/wineopenxr.spec new file mode 100644 index 00000000..e76d15f4 --- /dev/null +++ b/wineopenxr/wineopenxr.spec @@ -0,0 +1,3 @@ +@ stdcall xrNegotiateLoaderRuntimeInterface(ptr ptr) wine_xrNegotiateLoaderRuntimeInterface +@ stdcall __wineopenxr_GetVulkanInstanceExtensions(ptr) +@ stdcall __wineopenxr_GetVulkanDeviceExtensions(ptr) diff --git a/wineopenxr/wineopenxr64.json b/wineopenxr/wineopenxr64.json new file mode 100644 index 00000000..b82f743e --- /dev/null +++ b/wineopenxr/wineopenxr64.json @@ -0,0 +1,6 @@ +{ + "file_format_version": "1.0.0", + "runtime": { + "library_path": "C:\\windows\\system32\\wineopenxr.dll" + } +}